From f0e85ee2f35816684f72582d5641f5da09fe69dd Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Thu, 5 Jun 2014 11:45:41 +0200 Subject: [PATCH] vbscript: Added support for exponential form of numeric literals. --- dlls/vbscript/lex.c | 60 +++++++++++++++++++++++++++++++----- dlls/vbscript/tests/lang.vbs | 9 ++++++ 2 files changed, 61 insertions(+), 8 deletions(-) diff --git a/dlls/vbscript/lex.c b/dlls/vbscript/lex.c index dc5a9fe9beb..98b4cbb842c 100644 --- a/dlls/vbscript/lex.c +++ b/dlls/vbscript/lex.c @@ -20,6 +20,7 @@ #include "wine/port.h" #include +#include #include "vbscript.h" #include "parse.h" @@ -261,8 +262,10 @@ static int parse_string_literal(parser_ctx_t *ctx, const WCHAR **ret) static int parse_numeric_literal(parser_ctx_t *ctx, void **ret) { + BOOL use_int = TRUE; LONGLONG d = 0, hlp; int exp = 0; + double r; if(*ctx->ptr == '0' && !('0' <= ctx->ptr[1] && ctx->ptr[1] <= '9') && ctx->ptr[1] != '.') return *ctx->ptr++; @@ -281,13 +284,8 @@ static int parse_numeric_literal(parser_ctx_t *ctx, void **ret) ctx->ptr++; } - if(*ctx->ptr != '.') { - if(!exp && (LONG)d == d) { - LONG l = d; - *(LONG*)ret = l; - return (short)l == l ? tShort : tLong; - } - }else { + if(*ctx->ptr == '.') { + use_int = FALSE; ctx->ptr++; while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) { @@ -302,7 +300,53 @@ static int parse_numeric_literal(parser_ctx_t *ctx, void **ret) ctx->ptr++; } - *(double*)ret = exp>=0 ? d*pow(10, exp) : d/pow(10, -exp); + if(*ctx->ptr == 'e' || *ctx->ptr == 'E') { + int e = 0, sign = 1; + + if(*++ctx->ptr == '-') { + ctx->ptr++; + sign = -1; + } + + if(!isdigitW(*ctx->ptr)) { + FIXME("Invalid numeric literal\n"); + return 0; + } + + use_int = FALSE; + + do { + e = e*10 + *(ctx->ptr++) - '0'; + if(sign == -1 && -e+exp < -(INT_MAX/100)) { + /* The literal will be rounded to 0 anyway. */ + while(isdigitW(*ctx->ptr)) + ctx->ptr++; + *(double*)ret = 0; + return tDouble; + } + + if(sign*e + exp > INT_MAX/100) { + FIXME("Invalid numeric literal\n"); + return 0; + } + } while(isdigitW(*ctx->ptr)); + + exp += sign*e; + } + + if(use_int && (LONG)d == d) { + LONG l = d; + *(LONG*)ret = l; + return (short)l == l ? tShort : tLong; + } + + r = exp>=0 ? d*pow(10, exp) : d/pow(10, -exp); + if(isinf(r)) { + FIXME("Invalid numeric literal\n"); + return 0; + } + + *(double*)ret = r; return tDouble; } diff --git a/dlls/vbscript/tests/lang.vbs b/dlls/vbscript/tests/lang.vbs index 530c5dd8f21..3ee445c8d4a 100644 --- a/dlls/vbscript/tests/lang.vbs +++ b/dlls/vbscript/tests/lang.vbs @@ -40,6 +40,12 @@ Call ok(010 = 10, "010 <> 10") Call ok(10. = 10, "10. <> 10") Call ok(&hffFFffFF& = -1, "&hffFFffFF& <> -1") Call ok(&hffFFffFF& = -1, "&hffFFffFF& <> -1") +Call ok(34e5 = 3400000, "34e5 <> 3400000") +Call ok(56.789e5 = 5678900, "56.789e5 = 5678900") +Call ok(56.789e-2 = 0.56789, "56.789e-2 <> 0.56789") +Call ok(1e-94938484 = 0, "1e-... <> 0") +Call ok(34e0 = 34, "34e0 <> 34") +Call ok(34E1 = 340, "34E0 <> 340") Call ok(--1 = 1, "--1 = " & --1) Call ok(-empty = 0, "-empty = " & (-empty)) Call ok(true = -1, "! true = -1") @@ -78,6 +84,9 @@ Call ok(getVT(&h10&) = "VT_I2", "getVT(&h10&) is not VT_I2") Call ok(getVT(&h10000&) = "VT_I4", "getVT(&h10000&) is not VT_I4") Call ok(getVT(&H10000&) = "VT_I4", "getVT(&H10000&) is not VT_I4") Call ok(getVT(&hffFFffFF&) = "VT_I2", "getVT(&hffFFffFF&) is not VT_I2") +Call ok(getVT(1e2) = "VT_R8", "getVT(1e2) is not VT_R8") +Call ok(getVT(1e0) = "VT_R8", "getVT(1e0) is not VT_R8") +Call ok(getVT(0.1e2) = "VT_R8", "getVT(0.1e2) is not VT_R8") Call ok(getVT(1 & 100000) = "VT_BSTR", "getVT(1 & 100000) is not VT_BSTR") Call ok(getVT(-empty) = "VT_I2", "getVT(-empty) = " & getVT(-empty)) Call ok(getVT(-null) = "VT_NULL", "getVT(-null) = " & getVT(-null))