[m-rev.] diff: fix float64_bits_string where sizeof(long) == 4

Julien Fischer jfischer at opturion.com
Thu May 23 13:27:22 AEST 2013


More fixes for float.float64_bits_string/1.

The implementation of float64_bits_string/1 does not work correctly on
platforms where sizeof(long) == 4.  This is the case for the i386 version of
NetBSD.  Also, make the code in the float module consistent with the fact the
runtime allows there to be no 64-bit integer type defined at all.

configure.ac:
runtime/mercury_conf.h.in:
 	Define a new macro that expands to the integer length modifier for
 	the MR_int_least64_t type.

library/float.m:
 	Use the new macro to avoid a spot that was assuming that a long is
 	a 64-bit quantity.  (TODO: we can probably now simplify some of the
 	Windows specific code here, but I don't want to do that until I have
 	tested it.)

 	Have float64_bits_string/1 call MR_fatal_error() if MR_INT_LEAST64_TYPE
 	is not defined.

Julien.

diff --git a/configure.ac b/configure.ac
index 75486cd..8a8ada2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1796,7 +1796,21 @@ if test "$mercury_cv_int_least64_type" != unknown; then
      AC_DEFINE_UNQUOTED(MR_INT_LEAST64_TYPE, $mercury_cv_int_least64_type)
      MR_INT_LEAST64_TYPE=$mercury_cv_int_least64_type
      AC_SUBST(MR_INT_LEAST64_TYPE)
+
+    if test "$mercury_cv_int_least64_type" = int; then
+        AC_DEFINE_UNQUOTED(MR_INT_LEAST64_LENGTH_MODIFIER, "")
+    elif test "$mercury_cv_int_least64_type" = long; then
+        AC_DEFINE_UNQUOTED(MR_INT_LEAST64_LENGTH_MODIFIER, "l")
+    elif test "$mercury_cv_int_least64_type" = "long long"; then
+        AC_DEFINE_UNQUOTED(MR_INT_LEAST64_LENGTH_MODIFIER, "ll")
+    elif test "$mercury_cv_int_least64_type" = "__int64"; then
+        AC_DEFINE_UNQUOTED(MR_INT_LEAST64_LENGTH_MODIFIER, "I64")
+    else
+        AC_MSG_ERROR(Cannot determine the length modifier for the MR_int_least64_t type.)
+    fi
+    AC_SUBST(MR_INT_LEAST64_LENGTH_MODIFIER)
  fi
+
  #-----------------------------------------------------------------------------#

  AC_MSG_CHECKING(for an integer type of at least 32 bits)
diff --git a/library/float.m b/library/float.m
index 9f44591..0cf2135 100644
--- a/library/float.m
+++ b/library/float.m
@@ -934,27 +934,33 @@ float.float_to_doc(X) = str(string.float_to_string(X)).
      float64_bits_string(Flt::in) = (Str::uo),
      [will_not_call_mercury, promise_pure, thread_safe],
  "
-    union {
-        double f;
-        MR_int_least64_t i;
-    } u;
-    char buf[64];
-
-    u.f = (double) Flt;
-    #if defined(MR_MINGW64) || defined(MR_CYGWIN)
-        sprintf(buf, ""%lld"", u.i);
-    #elif defined(MR_WIN32)
-        /*
-        ** The I64 size prefix is specific to the Microsoft
-        ** C library -- we use it here since MSVC and (some)
-        ** versions of 32-bit MinGW GCC do not support the
-        ** standard ll size prefix.
-        */
-        sprintf(buf, ""%I64d"", u.i);
+    #if defined(MR_INT_LEAST64_TYPE)
+ 
+        union {
+            double f;
+            MR_int_least64_t i;
+        } u;
+        char buf[64];
+
+        u.f = (double) Flt;
+        #if defined(MR_MINGW64) || defined(MR_CYGWIN)
+            sprintf(buf, ""%lld"", u.i);
+        #elif defined(MR_WIN32)
+            /*
+            ** The I64 size prefix is specific to the Microsoft
+            ** C library -- we use it here since MSVC and (some)
+            ** versions of 32-bit MinGW GCC do not support the
+            ** standard ll size prefix.
+            */
+            sprintf(buf, ""%I64d"", u.i);
+        #else
+            sprintf(buf, ""%"" MR_INT_LEAST64_LENGTH_MODIFIER ""d"", u.i);
+        #endif 
+        MR_make_aligned_string_copy(Str, buf);
      #else
-        sprintf(buf, ""%ld"", u.i);
-    #endif 
-    MR_make_aligned_string_copy(Str, buf);
+        MR_fatal_error(
+        ""64-bit integers not supported on this platform"");
+    #endif
  ").

  :- pragma foreign_proc("Java",
diff --git a/runtime/mercury_conf.h.in b/runtime/mercury_conf.h.in
index 3904d98..fbc1edc 100644
--- a/runtime/mercury_conf.h.in
+++ b/runtime/mercury_conf.h.in
@@ -66,6 +66,12 @@
  ** It may be bigger, but any bits beyond 64 are not used.
  */
  #undef	MR_INT_LEAST64_TYPE
+ 
+/*
+** MR_INT_LEAST64_LENGTH_MODIFIER: the print() length modifier for 
+** a MR_int_least64_t.
+*/
+#undef	MR_INT_LEAST64_LENGTH_MODIFIER

  /*
  ** MR_INT_LEAST32_TYPE:



More information about the reviews mailing list