[PATCH 0/2] MR10907: Draft: vbscript: Parse &H8000 as Long(-32768) like native.
Native cscript parses every 4-digit hex literal that fits 16 bits as Integer except &H8000: its value -32768 (INT16_MIN) has no positive Int16 representation, so native promotes it to Long. Wine returned Integer for that one case because interp_int narrows any value that fits VT_I2. Introduce OP_long that unconditionally pushes VT_I4, and route the &H8000 case through it via a new tLong token. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10907
From: Francis De Brabandere <francisdb@gmail.com> --- dlls/vbscript/tests/lang.vbs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/dlls/vbscript/tests/lang.vbs b/dlls/vbscript/tests/lang.vbs index 1b6cdf763e4..01f86406965 100644 --- a/dlls/vbscript/tests/lang.vbs +++ b/dlls/vbscript/tests/lang.vbs @@ -72,6 +72,17 @@ Call ok(&H000000031& = 49, "&H000000031& <> 49") Call ok(getVT(&H00000000000000FF) = "VT_I2", "getVT(&H00000000000000FF) is not VT_I2") Call ok(getVT(&H007FFFFFFF) = "VT_I4", "getVT(&H007FFFFFFF) is not VT_I4") Call ok(&h0 = 0, "&h0 <> 0") + +' &H8000 (INT16_MIN bit pattern) is the one 16-bit value parsed as Long, not +' Integer: -32768 has no positive Int16 representation, so native promotes it. +Call ok(&H8000 = -32768, "&H8000 <> -32768") +todo_wine_ok getVT(&H8000) = "VT_I4", "getVT(&H8000) is not VT_I4" +Call ok(&H8001 = -32767, "&H8001 <> -32767") +Call ok(getVT(&H8001) = "VT_I2", "getVT(&H8001) is not VT_I2") +Call ok(&H7FFF = 32767, "&H7FFF <> 32767") +Call ok(getVT(&H7FFF) = "VT_I2", "getVT(&H7FFF) is not VT_I2") +Call ok(&H8000& = 32768, "&H8000& <> 32768") +Call ok(getVT(&H8000&) = "VT_I4", "getVT(&H8000&) is not VT_I4") Call ok(&h0& = 0, "&h0& <> 0") Call ok(&h00 = 0, "&h00 <> 0") Call ok(&h000000000 = 0, "&h000000000 <> 0") -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10907
From: Francis De Brabandere <francisdb@gmail.com> Native cscript parses every 4-digit hex literal that fits 16 bits as Integer except &H8000: its value -32768 (INT16_MIN) has no positive Int16 representation, so native promotes it to Long. Wine returned Integer for that one case because interp_int narrows any value that fits VT_I2. Introduce OP_long that unconditionally pushes VT_I4, and route the &H8000 case through it via a new tLong token. --- dlls/vbscript/compile.c | 2 ++ dlls/vbscript/interp.c | 14 ++++++++++++++ dlls/vbscript/lex.c | 5 +++++ dlls/vbscript/parse.h | 1 + dlls/vbscript/parser.y | 2 ++ dlls/vbscript/tests/lang.vbs | 2 +- dlls/vbscript/vbscript.h | 1 + 7 files changed, 26 insertions(+), 1 deletion(-) diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c index 0b3fbaf97d9..b330582b6c8 100644 --- a/dlls/vbscript/compile.c +++ b/dlls/vbscript/compile.c @@ -726,6 +726,8 @@ static HRESULT compile_expression(compile_ctx_t *ctx, expression_t *expr) return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_sub); case EXPR_INT: return push_instr_int(ctx, OP_int, ((int_expression_t*)expr)->value); + case EXPR_LONG: + return push_instr_int(ctx, OP_long, ((int_expression_t*)expr)->value); case EXPR_XOR: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_xor); default: diff --git a/dlls/vbscript/interp.c b/dlls/vbscript/interp.c index 219b4fdefda..b5113878bf7 100644 --- a/dlls/vbscript/interp.c +++ b/dlls/vbscript/interp.c @@ -2003,6 +2003,20 @@ static HRESULT interp_int(exec_ctx_t *ctx) return stack_push(ctx, &v); } +/* OP_long unconditionally produces VT_I4. Used for literals like &H8000 + * whose value fits VT_I2 but native parses as Long anyway. */ +static HRESULT interp_long(exec_ctx_t *ctx) +{ + const LONG arg = ctx->instr->arg1.lng; + VARIANT v; + + TRACE("%ld\n", arg); + + V_VT(&v) = VT_I4; + V_I4(&v) = arg; + return stack_push(ctx, &v); +} + static HRESULT interp_double(exec_ctx_t *ctx) { const DOUBLE *arg = ctx->instr->arg1.dbl; diff --git a/dlls/vbscript/lex.c b/dlls/vbscript/lex.c index 81cc67e037b..5f1c421ffcc 100644 --- a/dlls/vbscript/lex.c +++ b/dlls/vbscript/lex.c @@ -388,6 +388,11 @@ static int parse_hex_literal(parser_ctx_t *ctx, LONG *ret) if(*ctx->ptr == '&') { ctx->ptr++; *ret = l; + }else if(l == 0x8000) { + /* INT16_MIN has no positive Int16 representation; native parses + * &H8000 as Long(-32768) rather than Integer. */ + *ret = (INT16)l; + return tLong; }else { *ret = l == (UINT16)l ? (INT16)l : l; } diff --git a/dlls/vbscript/parse.h b/dlls/vbscript/parse.h index 4febe0ca535..1b25c5cdab4 100644 --- a/dlls/vbscript/parse.h +++ b/dlls/vbscript/parse.h @@ -37,6 +37,7 @@ typedef enum { EXPR_IMP, EXPR_INT, EXPR_IS, + EXPR_LONG, EXPR_LT, EXPR_LTEQ, EXPR_ME, diff --git a/dlls/vbscript/parser.y b/dlls/vbscript/parser.y index ec67cde2215..69cc6e4827f 100644 --- a/dlls/vbscript/parser.y +++ b/dlls/vbscript/parser.y @@ -143,6 +143,7 @@ static statement_t *link_statements(statement_t*,statement_t*); %token <string> tIdentifier tString %token <string> tDEFAULT tERROR tEXPLICIT tPROPERTY tSTEP %token <integer> tInt +%token <integer> tLong %token <dbl> tDouble %token <date> tDate @@ -562,6 +563,7 @@ LiteralExpression NumericLiteralExpression : '0' { $$ = new_long_expression(ctx, EXPR_INT, 0); CHECK_ERROR; } | tInt { $$ = new_long_expression(ctx, EXPR_INT, $1); CHECK_ERROR; } + | tLong { $$ = new_long_expression(ctx, EXPR_LONG, $1); CHECK_ERROR; } | tDouble { $$ = new_double_expression(ctx, $1); CHECK_ERROR; } IntegerValue diff --git a/dlls/vbscript/tests/lang.vbs b/dlls/vbscript/tests/lang.vbs index 01f86406965..ef5b3445b39 100644 --- a/dlls/vbscript/tests/lang.vbs +++ b/dlls/vbscript/tests/lang.vbs @@ -76,7 +76,7 @@ Call ok(&h0 = 0, "&h0 <> 0") ' &H8000 (INT16_MIN bit pattern) is the one 16-bit value parsed as Long, not ' Integer: -32768 has no positive Int16 representation, so native promotes it. Call ok(&H8000 = -32768, "&H8000 <> -32768") -todo_wine_ok getVT(&H8000) = "VT_I4", "getVT(&H8000) is not VT_I4" +Call ok(getVT(&H8000) = "VT_I4", "getVT(&H8000) is not VT_I4") Call ok(&H8001 = -32767, "&H8001 <> -32767") Call ok(getVT(&H8001) = "VT_I2", "getVT(&H8001) is not VT_I2") Call ok(&H7FFF = 32767, "&H7FFF <> 32767") diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h index eda5d8740b4..dd2cc59d07d 100644 --- a/dlls/vbscript/vbscript.h +++ b/dlls/vbscript/vbscript.h @@ -294,6 +294,7 @@ typedef enum { X(jmp_true, 0, ARG_ADDR, 0) \ X(lt, 1, ARG_UINT, 0) \ X(lteq, 1, ARG_UINT, 0) \ + X(long, 1, ARG_INT, 0) \ X(mcall, 1, ARG_BSTR, ARG_UINT) \ X(mcallv, 1, ARG_BSTR, ARG_UINT) \ X(mget, 1, ARG_BSTR, 0) \ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10907
participants (2)
-
Francis De Brabandere -
Francis De Brabandere (@francisdb)