[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