From 933e701dac1936c6f15c765b5687fbc623464ec7 Mon Sep 17 00:00:00 2001 From: Mike Sperber Date: Thu, 22 Mar 2012 18:00:31 +0100 Subject: Unbreak floating point on middle-endian machines. On some ARMs (and maybe other platforms), doubles are stored with the the two 32-bit words reversed with respect to more common architectures. The symptom is this: > io_lib:write(1.0). "0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005299808824" Detect that and account for it when decoding floats. --- lib/odbc/aclocal.m4 | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) (limited to 'lib/odbc') diff --git a/lib/odbc/aclocal.m4 b/lib/odbc/aclocal.m4 index 339a15a2bb..9c5bcd6dc6 100644 --- a/lib/odbc/aclocal.m4 +++ b/lib/odbc/aclocal.m4 @@ -59,6 +59,7 @@ AC_ARG_VAR(erl_xcomp_isysroot, [Absolute cross system root include path (only us dnl Cross compilation variables AC_ARG_VAR(erl_xcomp_bigendian, [big endian system: yes|no (only used when cross compiling)]) +AC_ARG_VAR(erl_xcomp_double_middle_endian, [double-middle-endian system: yes|no (only used when cross compiling)]) AC_ARG_VAR(erl_xcomp_linux_clock_gettime_correction, [clock_gettime() can be used for time correction: yes|no (only used when cross compiling)]) AC_ARG_VAR(erl_xcomp_linux_nptl, [have Native POSIX Thread Library: yes|no (only used when cross compiling)]) AC_ARG_VAR(erl_xcomp_linux_usable_sigusrx, [SIGUSR1 and SIGUSR2 can be used: yes|no (only used when cross compiling)]) @@ -606,6 +607,60 @@ ifelse([$5], , , [$5 fi ]) +dnl ---------------------------------------------------------------------- +dnl +dnl AC_DOUBLE_MIDDLE_ENDIAN +dnl +dnl Checks whether doubles are represented in "middle-endian" format. +dnl Sets ac_cv_double_middle_endian={no,yes,unknown} accordingly, +dnl as well as DOUBLE_MIDDLE_ENDIAN. +dnl +dnl + +AC_DEFUN([AC_C_DOUBLE_MIDDLE_ENDIAN], +[AC_CACHE_CHECK(whether double word ordering is middle-endian, ac_cv_c_double_middle_endian, +[# It does not; compile a test program. +AC_RUN_IFELSE( +[AC_LANG_SOURCE([[int +main(void) +{ + int i = 0; + int zero = 0; + union + { + double d; + char c[sizeof (double)]; + } v; + v.d = 1.0; + + + while (i < sizeof(double) / 2) + { + if (v.c[i] != 0) + zero = 1; + ++i; + } + exit (zero); +} +]])], + [ac_cv_c_double_middle_endian=no], + [ac_cv_c_double_middle_endian=yes], + [ac_cv_c_double_middle=unknown])]) +case $ac_cv_c_double_middle_endian in + yes) + m4_default([$1], + [AC_DEFINE([DOUBLE_MIDDLE_ENDIAN], 1, + [Define to 1 if your processor stores the words in a double in + middle-endian format (like some ARMs).])]) ;; + no) + $2 ;; + *) + m4_default([$3], + [AC_MSG_ERROR([unknown double endianness +presetting ac_cv_c_double_middle_endian=no (or yes) will help])]) ;; +esac +])# AC_C_DOUBLE_MIDDLE_ENDIAN + dnl ---------------------------------------------------------------------- dnl @@ -1337,6 +1392,14 @@ if test "$ac_cv_c_bigendian" = "yes"; then AC_DEFINE(ETHR_BIGENDIAN, 1, [Define if bigendian]) fi +case X$erl_xcomp_double_middle_endian in + X) ;; + Xyes|Xno) ac_cv_c_double_middle_endian=$erl_xcomp_double_middle_endian;; + *) AC_MSG_ERROR([Bad erl_xcomp_double_middle_endian value: $erl_xcomp_double_middle_endian]);; +esac + +AC_C_DOUBLE_MIDDLE_ENDIAN + AC_ARG_ENABLE(native-ethr-impls, AS_HELP_STRING([--disable-native-ethr-impls], [disable native ethread implementations]), -- cgit v1.2.3 From eba4d247740189c3b8045edeaf8224651e77a3e0 Mon Sep 17 00:00:00 2001 From: Mike Sperber Date: Fri, 20 Jul 2012 11:27:47 +0200 Subject: Revise the autoconf tests for double middle endianness. The previous iteration didn't work for big-endian systems. Now use code very close to what Erts does internally. Also, only warn when the double endianness is unknown - i.e. when we're cross-compiling. --- lib/odbc/aclocal.m4 | 65 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 11 deletions(-) (limited to 'lib/odbc') diff --git a/lib/odbc/aclocal.m4 b/lib/odbc/aclocal.m4 index 9c5bcd6dc6..a76594d86f 100644 --- a/lib/odbc/aclocal.m4 +++ b/lib/odbc/aclocal.m4 @@ -621,25 +621,68 @@ AC_DEFUN([AC_C_DOUBLE_MIDDLE_ENDIAN], [AC_CACHE_CHECK(whether double word ordering is middle-endian, ac_cv_c_double_middle_endian, [# It does not; compile a test program. AC_RUN_IFELSE( -[AC_LANG_SOURCE([[int +[AC_LANG_SOURCE([[#include + +int main(void) { int i = 0; int zero = 0; + int bigendian; + int zero_index = 0; + + union + { + long int l; + char c[sizeof (long int)]; + } u; + + /* we'll use the one with 32-bit words */ + union + { + double d; + unsigned int c[2]; + } vint; + + union + { + double d; + unsigned long c[2]; + } vlong; + union { double d; - char c[sizeof (double)]; - } v; - v.d = 1.0; - - - while (i < sizeof(double) / 2) + unsigned short c[2]; + } vshort; + + + /* Are we little or big endian? From Harbison&Steele. */ + u.l = 1; + bigendian = (u.c[sizeof (long int) - 1] == 1); + + zero_index = bigendian ? 1 : 0; + + vint.d = 1.0; + vlong.d = 1.0; + vshort.d = 1.0; + + if (sizeof(unsigned int) == 4) + { + if (vint.c[zero_index] != 0) + zero = 1; + } + else if (sizeof(unsigned long) == 4) + { + if (vlong.c[zero_index] != 0) + zero = 1; + } + else if (sizeof(unsigned short) == 4) { - if (v.c[i] != 0) + if (vshort.c[zero_index] != 0) zero = 1; - ++i; } + exit (zero); } ]])], @@ -656,7 +699,7 @@ case $ac_cv_c_double_middle_endian in $2 ;; *) m4_default([$3], - [AC_MSG_ERROR([unknown double endianness + [AC_MSG_WARN([unknown double endianness presetting ac_cv_c_double_middle_endian=no (or yes) will help])]) ;; esac ])# AC_C_DOUBLE_MIDDLE_ENDIAN @@ -1394,7 +1437,7 @@ fi case X$erl_xcomp_double_middle_endian in X) ;; - Xyes|Xno) ac_cv_c_double_middle_endian=$erl_xcomp_double_middle_endian;; + Xyes|Xno|Xunknown) ac_cv_c_double_middle_endian=$erl_xcomp_double_middle_endian;; *) AC_MSG_ERROR([Bad erl_xcomp_double_middle_endian value: $erl_xcomp_double_middle_endian]);; esac -- cgit v1.2.3