Is this a suitable patch to apply to Configure (and backport to the metaconfig units), for the purpose of testing whether 0.0 is stored as all bits zero in memory? It's a useful thing to know, because if it's true (which I think is generally the case), then memset of a block of memory to 0 is sufficient to correctly initialise any NVs that it contains. It's quite safe for it to default to #undef on non-Configure platforms.
In theory we should also be checking that NULL pointers are stored as all bits zero, but I think that that portability battle is already lost - we already Zero() SV bodies that contain pointers and expect things to work. Also, I think that by adding another symbol to config_h.SH this breaks VMS, but I can't remember the correct fix, or where it goes. Can someone help? Nicholas Clark --- Configure.orig Tue May 31 07:09:02 2005 +++ Configure Sat Jun 18 17:55:48 2005 @@ -1002,6 +1002,7 @@ perl5='' perladmin='' perlpath='' d_nv_preserves_uv='' +d_nv_zero_is_allbits_zero='' i16size='' i16type='' i32size='' @@ -14833,6 +14834,128 @@ esac $rm -f try.* try +$echo "Checking whether NV 0.0 is all bits zero in memory..." >&4 +: volatile so that the compiler has to store it out to memory. +if test X"$d_volatile" = X"$define"; then + volatile=volatile +fi +$cat <<EOP >try.c +#include <stdio.h> +#$i_stdlib I_STDLIB +#ifdef I_STDLIB +#include <stdlib.h> +#endif +#$i_string I_STRING +#ifdef I_STRING +# include <string.h> +#else +# include <strings.h> +#endif +#include <sys/types.h> +#include <signal.h> +#ifdef SIGFPE +$volatile int bletched = 0; +$signal_t blech(s) int s; { bletched = 1; } +#endif + +int checkit($nvtype d, char *where) { + unsigned char *p = (char *)&d; + unsigned char *end = p + sizeof(d); + int fail = 0; + + while (p < end) + fail += *p++; + + if (!fail) + return 0; + + p = (char *)&d; + printf("No - %s: 0x", where); + while (p < end) + printf ("%02X", *p++); + printf("\n"); + return 1; +} + +int main(int argc, char **argv) { + $nvtype d = 0.0; + int fail = 0; + fail += checkit(d, "0.0"); + + /* The compiler shouldn't be assuming that bletched is 0 */ + d = bletched; + + fail += checkit(d, "bleched"); + +#ifdef SIGFPE + signal(SIGFPE, blech); +#endif + + /* Paranoia - the compiler should have no way of knowing that ANSI says + that argv[argc] will always be NULL. Actually, if it did assume this it + would be buggy, as this is C and main() can be called from elsewhere in + the program. */ + d = argv[argc] ? 1 : 0; + + if (d) { + printf("Odd argv[argc]=%p, d=%g\n", argv[argc], d); + } + + fail += checkit(d, "ternary"); + + memset(&d, sizeof(d), argv[argc] ? 1 : 0); + + if (d != 0.0) { + printf("No - memset doesn't give 0.0\n"); + /* This might just blow up: */ + printf("(gives %g)\n", d); + return 1; + } + +#ifdef SIGFPE + if (bletched) { + printf("No - something bleched\n"); + return 1; + } +#endif + if (fail) { + printf("No - %d fail(s)\n", fail); + return 1; + } + printf("Yes\n"); + return 0; +} +EOP +set try + +d_nv_zero_is_allbits_zero="$undef" +if eval $compile; then + xxx="`$run ./try`" + case "$?" in + 0) + case "$xxx" in + Yes) cat >&4 <<EOM +0.0 is represented as all bits zero in memory +EOM + d_nv_zero_is_allbits_zero="$define" + ;; + *) cat >&4 <<EOM +0.0 is not represented as all bits zero in memory +EOM + d_nv_zero_is_allbits_zero="$undef" + ;; + esac + ;; + *) cat >&4 <<EOM +0.0 is not represented as all bits zero in memory +EOM + d_nv_zero_is_allbits_zero="$undef" + ;; + esac +fi + +$rm -f try.* try + : check for off64_t echo " " @@ -21012,6 +21135,7 @@ d_mymalloc='$d_mymalloc' d_nice='$d_nice' d_nl_langinfo='$d_nl_langinfo' d_nv_preserves_uv='$d_nv_preserves_uv' +d_nv_zero_is_allbits_zero='$d_nv_zero_is_allbits_zero' d_off64_t='$d_off64_t' d_old_pthread_create_joinable='$d_old_pthread_create_joinable' d_oldpthreads='$d_oldpthreads' --- config_h.SH.orig Thu May 26 12:56:06 2005 +++ config_h.SH Sat Jun 18 17:31:21 2005 @@ -3235,6 +3235,10 @@ sed <<!GROK!THIS! >$CONFIG_H -e 's!^#und * This symbol contains the number of bits a variable of type NVTYPE * can preserve of a variable of type UVTYPE. */ +/* NV_ZERO_IS_ALLBITS_ZERO + * This symbol, if defined, indicates that a variable of type NVTYPE + * stores 0.0 in memory as all bits zero. + */ #define IVTYPE $ivtype /**/ #define UVTYPE $uvtype /**/ #define I8TYPE $i8type /**/ @@ -3263,6 +3267,7 @@ sed <<!GROK!THIS! >$CONFIG_H -e 's!^#und #define NVSIZE $nvsize /**/ #$d_nv_preserves_uv NV_PRESERVES_UV #define NV_PRESERVES_UV_BITS $nv_preserves_uv_bits +#$d_nv_zero_is_allbits_zero NV_ZERO_IS_ALLBITS_ZERO #if UVSIZE == 8 # ifdef BYTEORDER # if BYTEORDER == 0x1234 --- Porting/Glossary.orig Fri May 20 09:23:14 2005 +++ Porting/Glossary Sat Jun 18 17:32:22 2005 @@ -1383,6 +1383,10 @@ d_nv_preserves_uv (perlxv.U): This variable indicates whether a variable of type nvtype can preserve all the bits a variable of type uvtype. +d_nv_zero_is_allbits_zero (perlxv.U): + This variable indicates whether a variable of type nvtype + stores 0.0 in memory as all bits zero. + d_off64_t (d_off64_t.U): This symbol will be defined if the C compiler supports off64_t.