Jacek Caban : vbscript: Added support for exponential form of numeric literals.

Alexandre Julliard julliard at winehq.org
Wed Jun 11 13:36:24 CDT 2014


Module: wine
Branch: master
Commit: f0e85ee2f35816684f72582d5641f5da09fe69dd
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=f0e85ee2f35816684f72582d5641f5da09fe69dd

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Thu Jun  5 11:45:41 2014 +0200

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 dc5a9fe..98b4cbb 100644
--- a/dlls/vbscript/lex.c
+++ b/dlls/vbscript/lex.c
@@ -20,6 +20,7 @@
 #include "wine/port.h"
 
 #include <assert.h>
+#include <limits.h>
 
 #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 530c5dd..3ee445c 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))




More information about the wine-cvs mailing list