shithub: femtolisp

Download patch

ref: 581afbf636745df48c52cae17678259103f7fce5
parent: c8c59b1dfc38561e21a16e97bbf7325e62b1a0e1
author: JeffBezanson <jeff.bezanson@gmail.com>
date: Tue Oct 7 21:14:23 EDT 2008

fixing the result of casting floating point numbers to uint64

handling NULL locale


--- a/femtolisp/unittest.lsp
+++ b/femtolisp/unittest.lsp
@@ -62,6 +62,8 @@
 (assert (equal (* 2 #int64(0x4000000000000000))
                #uint64(0x8000000000000000)))
 
+(assert (equal (uint64 (double -123)) #uint64(0xffffffffffffff85)))
+
 (assert (equal (string 'sym #char(65) #wchar(945) "blah") "symA\u03B1blah"))
 
 
--- a/llt/operators.c
+++ b/llt/operators.c
@@ -89,7 +89,7 @@
         if (d > 0 && *(int64_t*)dest < 0)  // 0x8000000000000000 is a bitch
             *(int64_t*)dest = S64_MAX;
         break;
-    case T_UINT64: *(uint64_t*)dest = d; break;
+    case T_UINT64: *(uint64_t*)dest = (int64_t)d; break;
     case T_FLOAT:  *(float*)dest = d; break;
     case T_DOUBLE: *(double*)dest = d; break;
     }
@@ -115,10 +115,30 @@
 }
 
 CONV_TO_INTTYPE(int64)
-CONV_TO_INTTYPE(uint64)
 CONV_TO_INTTYPE(int32)
 CONV_TO_INTTYPE(uint32)
 
+// this is needed to work around a possible compiler bug
+// casting negative floats and doubles to uint64. you need
+// to cast to int64 first.
+uint64_t conv_to_uint64(void *data, numerictype_t tag)
+{
+    uint64_t i=0;
+    switch (tag) {
+    case T_INT8:   i = (uint64_t)*(int8_t*)data; break;
+    case T_UINT8:  i = (uint64_t)*(uint8_t*)data; break;
+    case T_INT16:  i = (uint64_t)*(int16_t*)data; break;
+    case T_UINT16: i = (uint64_t)*(uint16_t*)data; break;
+    case T_INT32:  i = (uint64_t)*(int32_t*)data; break;
+    case T_UINT32: i = (uint64_t)*(uint32_t*)data; break;
+    case T_INT64:  i = (uint64_t)*(int64_t*)data; break;
+    case T_UINT64: i = (uint64_t)*(uint64_t*)data; break;
+    case T_FLOAT:  i = (uint64_t)(int64_t)*(float*)data; break;
+    case T_DOUBLE: i = (uint64_t)(int64_t)*(double*)data; break;
+    }
+    return i;
+}
+
 int cmp_same_lt(void *a, void *b, numerictype_t tag)
 {
     switch (tag) {
@@ -226,7 +246,7 @@
             return ((int64_t)*(uint64_t*)a == *(int64_t*)b);
         }
         else if (btag == T_DOUBLE) {
-            return (*(uint64_t*)a == (uint64_t)*(double*)b);
+            return (*(uint64_t*)a == (uint64_t)(int64_t)*(double*)b);
         }
     }
     else if (atag == T_INT64) {
@@ -242,7 +262,7 @@
             return ((int64_t)*(uint64_t*)b == *(int64_t*)a);
         }
         else if (atag == T_DOUBLE) {
-            return (*(uint64_t*)b == (uint64_t)*(double*)a);
+            return (*(uint64_t*)b == (uint64_t)(int64_t)*(double*)a);
         }
     }
     else if (btag == T_INT64) {
--- a/llt/utf8.c
+++ b/llt/utf8.c
@@ -546,6 +546,8 @@
 
 int u8_is_locale_utf8(const char *locale)
 {
+    if (locale == NULL) return 0;
+
     /* this code based on libutf8 */
     const char* cp = locale;