~ chicken-core (chicken-5) c2ea63b340995b1882d9ed400db0019c1686aa11


commit c2ea63b340995b1882d9ed400db0019c1686aa11
Author:     felix <felix@call-with-current-continuation.org>
AuthorDate: Fri Dec 28 00:13:27 2012 +0100
Commit:     felix <felix@call-with-current-continuation.org>
CommitDate: Sat Jan 5 20:20:12 2013 +0100

    Corrected behaviour for "C_i_foreign_[unsigned]_integer64_argumentp"
    
    Extract floating-point values from argument and compare with MIN/MAX
    for the associated C type). Added limits to chicken.h, which uses stdint.h
    now (or inttypes.h on SunOS).
    
    Disabled compiler-test added by Peter for #955 for 32-bit platforms.
    
    Signed-off-by: Peter Bex <peter.bex@xs4all.nl>

diff --git a/chicken.h b/chicken.h
index 0a45f1b5..566aad3e 100644
--- a/chicken.h
+++ b/chicken.h
@@ -502,9 +502,17 @@ static inline int isinf_ld (long double x)
 #define C_F32_LOCATIVE            8
 #define C_F64_LOCATIVE            9
 
+#if defined (__MINGW32__)
+# define C_s64                    __int64
+# define C_u64                    unsigned __int64
+#else
+# define C_s64                    int64_t
+# define C_u64                    uint64_t
+#endif
+
 #ifdef C_SIXTY_FOUR
 # ifdef C_LLP
-#  define C_word                  __int64
+#  define C_word                  C_s64
 # else
 #  define C_word                  long
 # endif
@@ -516,24 +524,47 @@ static inline int isinf_ld (long double x)
 # define C_s32                    int
 #endif
 
-#if defined (__MINGW32__)
-# define C_s64                    __int64
-# define C_u64                    unsigned __int64
-#else
-# define C_s64                    int64_t
-# define C_u64                    uint64_t
-#endif
-
 #define C_char                    char
 #define C_uchar                   unsigned C_char
 #define C_byte                    char
 #define C_uword                   unsigned C_word
 #define C_header                  C_uword
 
+#if defined(__sun__) && !defined(__svr4__) 
+/* SunOS is supposed not to have stdint.h */
+# include <inttypes.h>
+#else
+# include <stdint.h>
+#endif
+
+/* if all else fails, use these:
+ #define UINT64_MAX (18446744073709551615ULL)
+ #define INT64_MAX  (9223372036854775807LL)
+ #define INT64_MIN  (-INT64_MAX - 1)
+ #define UINT32_MAX (4294967295U)
+ #define INT32_MAX  (2147483647)
+ #define INT32_MIN  (-INT32_MAX - 1)
+ #define UINT16_MAX (65535U)
+ #define INT16_MAX  (32767)
+ #define INT16_MIN  (-INT16_MAX - 1)
+ #define UINT8_MAX  (255)
+ #define INT8_MAX   (127)
+ #define INT8_MIN   (-INT8_MAX - 1)
+*/
+
+#define C_U64_MAX    UINT64_MAX
+#define C_S64_MIN    INT64_MIN
+#define C_S64_MAX    INT64_MAX
+
 #if defined(C_LLP) && defined(C_SIXTY_FOUR)
-# define C_long                   __int64
-# define C_LONG_MAX               LONG_LONG_MAX
-# define C_LONG_MIN               LONG_LONG_MIN
+# define C_long                   C_s64
+# ifndef LONG_LONG_MAX
+#  define C_LONG_MAX              LLONG_MAX
+#  define C_LONG_MIN              LLONG_MIN
+# else
+#  define C_LONG_MAX              LONG_LONG_MAX
+#  define C_LONG_MIN              LONG_LONG_MIN
+# endif
 #else
 # define C_long                   long
 # define C_LONG_MAX               LONG_MAX
diff --git a/runtime.c b/runtime.c
index 017e76f5..2265f82f 100644
--- a/runtime.c
+++ b/runtime.c
@@ -5879,10 +5879,15 @@ C_regparm C_word C_fcall C_i_foreign_integer_argumentp(C_word x)
 
 C_regparm C_word C_fcall C_i_foreign_integer64_argumentp(C_word x)
 {
-  double m;
+  double m, r;
 
-  if((x & C_FIXNUM_BIT) != 0 || (!C_immediatep(x) && C_block_header(x) == C_FLONUM_TAG))
-    return x;
+  if((x & C_FIXNUM_BIT) != 0) return x;
+  
+  if(!C_immediatep(x) && C_block_header(x) == C_FLONUM_TAG) {
+    m = C_flonum_magnitude(x);
+
+    if(m >= C_S64_MIN && m <= C_S64_MAX && C_modf(m, &r) == 0.0) return x;
+  }
 
   barf(C_BAD_ARGUMENT_TYPE_NO_INTEGER_ERROR, NULL, x);
   return C_SCHEME_UNDEFINED;
@@ -5891,14 +5896,14 @@ C_regparm C_word C_fcall C_i_foreign_integer64_argumentp(C_word x)
 
 C_regparm C_word C_fcall C_i_foreign_unsigned_integer_argumentp(C_word x)
 {
-  double m;
+  double m ,r;
 
   if((x & C_FIXNUM_BIT) != 0) return x;
 
   if(!C_immediatep(x) && C_block_header(x) == C_FLONUM_TAG) {
     m = C_flonum_magnitude(x);
 
-    if(m >= 0 && m <= C_UWORD_MAX) return x;
+    if(m >= 0 && m <= C_UWORD_MAX && C_modf(m, &r) == 0.0) return x;
   }
 
   barf(C_BAD_ARGUMENT_TYPE_NO_UINTEGER_ERROR, NULL, x);
@@ -5908,14 +5913,14 @@ C_regparm C_word C_fcall C_i_foreign_unsigned_integer_argumentp(C_word x)
 
 C_regparm C_word C_fcall C_i_foreign_unsigned_integer64_argumentp(C_word x)
 {
-  double m;
+  double m, r;
 
   if((x & C_FIXNUM_BIT) != 0) return x;
 
   if(!C_immediatep(x) && C_block_header(x) == C_FLONUM_TAG) {
     m = C_flonum_magnitude(x);
 
-    if(m >= 0 && m <= C_UWORD_MAX) return x;
+    if(m >= 0 && m <= C_U64_MAX && C_modf(m, &r) == 0.0) return x;
   }
 
   barf(C_BAD_ARGUMENT_TYPE_NO_UINTEGER_ERROR, NULL, x);
Trap