This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
.github - switch to v3 actions
[perl5.git] / Configure
index 913e080..6727379 100755 (executable)
--- a/Configure
+++ b/Configure
@@ -391,9 +391,11 @@ d_attribute_nonnull=''
 d_attribute_noreturn=''
 d_attribute_pure=''
 d_attribute_unused=''
+d_attribute_visibility=''
 d_attribute_warn_unused_result=''
 d_printf_format_null=''
 d_backtrace=''
+d_non_int_bitfields=''
 d_builtin_choose_expr=''
 d_builtin_expect=''
 d_builtin_add_overflow=''
@@ -477,6 +479,8 @@ d_fds_bits=''
 d_fdclose=''
 d_fdim=''
 d_fegetround=''
+d_ffs=''
+d_ffsl=''
 d_fgetpos=''
 d_finite=''
 d_finitel=''
@@ -697,10 +701,12 @@ d_newlocale=''
 d_querylocale=''
 d_uselocale=''
 i_xlocale=''
+xlocale_needed=''
 d_nextafter=''
 d_nexttoward=''
 d_nice=''
 d_nl_langinfo=''
+d_nl_langinfo_l=''
 d_thread_safe_nl_langinfo_l=''
 d_off64_t=''
 d_open3=''
@@ -756,6 +762,7 @@ d_semget=''
 d_semop=''
 d_sendmsg=''
 d_setegid=''
+d_setenv=''
 d_seteuid=''
 d_setgrent=''
 d_setgrent_r=''
@@ -889,6 +896,7 @@ d_strtoul=''
 d_strtoull=''
 d_strtouq=''
 d_strxfrm=''
+d_strxfrm_l=''
 d_symlink=''
 d_syscall=''
 d_syscallproto=''
@@ -898,6 +906,8 @@ d_tcgetpgrp=''
 d_tcsetpgrp=''
 d_telldirproto=''
 d_tgamma=''
+d_thread_local=''
+perl_thread_local=''
 d_time=''
 timetype=''
 d_asctime64=''
@@ -1225,6 +1235,7 @@ u8size=''
 u8type=''
 uvsize=''
 uvtype=''
+i32dformat=''
 ivdformat=''
 nvEUformat=''
 nvFUformat=''
@@ -1232,6 +1243,10 @@ nvGUformat=''
 nveformat=''
 nvfformat=''
 nvgformat=''
+u32XUformat=''
+u32oformat=''
+u32uformat=''
+u32xformat=''
 uvXUformat=''
 uvoformat=''
 uvuformat=''
@@ -1315,6 +1330,8 @@ shsharp=''
 spitshell=''
 src=''
 ssizetype=''
+st_dev_sign=''
+st_dev_size=''
 st_ino_sign=''
 st_ino_size=''
 startperl=''
@@ -1493,7 +1510,7 @@ archname=''
 usereentrant='undef'
 : List of libraries we want.
 : If anyone needs extra -lxxx, put those in a hint file.
-libswanted="cl pthread socket bind inet nsl ndbm gdbm dbm db malloc dl ld"
+libswanted="cl pthread socket bind inet ndbm gdbm dbm db malloc dl ld"
 libswanted="$libswanted sun m crypt sec util c cposix posix ucb bsd BSD"
 : We probably want to search /usr/shlib before most other libraries.
 : This is only used by the lib/ExtUtils/MakeMaker.pm routine extliblist.
@@ -2203,6 +2220,7 @@ $startsh
 xxxm=\$dflt
 $myecho
 ans='!'
+counter=42
 case "\$fastread" in
 yes) case "\$dflt" in
        '') ;;
@@ -2277,6 +2295,12 @@ while expr "X\$ans" : "X!" >/dev/null; do
                $myecho
                ;;
        esac
+       counter=\`echo \$counter | awk '{ print --\$0 }'\`
+       if [ \$counter = 0 ]; then
+               echo >&4
+               echo >&4 Too many attempts asking the same question.  Giving up.
+               exit 1
+       fi
 done
 case "\$ans" in
 '') ans="\$xxxm";;
@@ -2779,7 +2803,7 @@ EOM
                     if $test -f UU/myread; then
                         . ./UU/myread
                     else
-                        echo "Cannot find myread, sorry.  Aborting." >&2
+                        echo "Cannot find myread, sorry.  Aborting." >&4
                         exit 1
                     fi
                 fi
@@ -3482,7 +3506,10 @@ EOM
                        osvers="$3"
                        ;;
                dragonfly) osname=dragonfly
-                       osvers="$3"
+                        case "$3" in
+                            [0-9]*) osvers="$3" ;;
+                            *) osvers="$2" ;;
+                        esac
                        ;;
                dynixptx*) osname=dynixptx
                        osvers=`echo "$4"|sed 's/^v//'`
@@ -4655,6 +4682,61 @@ case "$gccversion" in
     esac
 esac
 
+# Really old versions of gcc default to C89 and will error for this code.
+# See if the compiler (gcc or otherwise) needs a flag to compile C99 code
+# Initialisations in for loops seem to be the particular problem
+# (Does this syntax conflict with something else that was valid C89?)
+# We also add a declaration after a statement to detect whether the compiler
+# (or the user supplied -Accflags) consider such declarations to be errors.
+# This causes 'Configure with -Accflags="-Werror=declaration-after-statement"'
+# to fail hard and early.
+#
+# Annoyingly -std=c99 will cause gcc to tell glibc not to define prototypes for
+# syscall, drand48 etc when including <unistd.h>, which messes up our build.
+# I guess we *could* loop round trying -std=c99 first with checks both for the
+# prototype found and the code compiling (because -std=gnu99 might do other
+# things we don't want, particularly on non-GCC compilers) but
+# 1) We would need to check for the prototype first (without any flags)
+# 2) We would still end up with most Linux systems either being -std=gnu99
+#    or "" (no flag), and so both common options would not rigorously check our
+#    portability to other platforms.
+# So it doesn't seem worth the complexity and chance of different failure.
+$cat >try.c <<'EOCP'
+int main(int argc, char **argv) {
+    argc = argc + 1;
+    /* This is deliberately a declaration after a statement. */
+    unsigned long long count = 0;
+    for (char **p = argv; *p; ++p) {
+        ++count;
+    }
+    return count == 1 ? 0 : argc;
+}
+EOCP
+c99_for=no
+for flag in '' '-std=gnu99' '-std=c99'; do
+    if $cc -o try $flag $ccflags $ldflags try.c 2>/dev/null && ./try; then
+        c99_for="$flag"
+        break;
+    fi
+done
+case "$c99_for" in
+'') echo "Your C compiler doesn't need any special flags to compile C99 code"
+    ;;
+no) echo >&4 "Your C compiler doesn't seem to be able to compile C99 code"
+    rp='Do you really want to continue?'
+    dflt='n'
+    . ./myread
+    case "$ans" in
+       [yY])   echo >&4 "Okay, continuing."    ;;
+       *)      exit 1                          ;;
+    esac
+    ;;
+*)  echo "Your C compiler needs $c99_for to compile C99 code"
+    ccflags="$c99_for $ccflags"
+    ;;
+esac
+$rm -f try try.*
+
 : What should the include directory be ?
 : Use sysroot if set, so findhdr looks in the right place.
 echo " "
@@ -4867,7 +4949,7 @@ case "$ccname" in
        $echo 'extern int foo;' > try.c
        set X `$cppstdin -v try.c 2>&1 | $awk '/^#include </,/^End of search /'|$cppfilter $grep '/include'`
        shift
-       inclinpth=""
+       inclibpth=""
        if $test $# -gt 0; then
            for i in $*; do
                case $realpath in
@@ -5200,6 +5282,16 @@ for thislib in $libswanted; do
                $test -f "$xxx" && libstyle=shared
            fi
            if test ! -f "$xxx"; then
+               xxx=$thisdir/lib$thislib.$so$_a
+               $test -f "$xxx" && eval $libscheck
+               $test -f "$xxx" && libstyle="import"
+           fi
+           if test ! -f "$xxx"; then
+               xxx=$thisdir/$thislib.$so$_a
+               $test -f "$xxx" && eval $libscheck
+               $test -f "$xxx" && libstyle="import"
+           fi
+           if test ! -f "$xxx"; then
                xxx=$thisdir/lib$thislib.$so
                $test -f "$xxx" && eval $libscheck
                $test -f "$xxx" && libstyle=shared
@@ -5333,18 +5425,18 @@ esac
 : think is an option
 checkccflag='check=$1; flag=$2; callback=$3;
 echo " ";
-echo "Checking if your compiler accepts $flag" 2>&1;
+echo "Checking if your compiler accepts $flag" >&4;
 [ "X$sysroot" != "X" ] && echo "For sysroot = $sysroot";
 echo "int main(void) { return 0; }" > gcctest.c;
 if $cc $_sysroot -O2 $flag -o gcctest gcctest.c 2>gcctest.out && $run ./gcctest; then
-    echo "Yes, it does." 2>&1;
+    echo "Yes, it does." >&4;
     if $test -s gcctest.out ; then
         echo "But your platform does not like it:";
         cat gcctest.out;
     else
        case "$ccflags" in
        *$check*)
-           echo "Leaving current flags $ccflags alone." 2>&1
+           echo "Leaving current flags $ccflags alone." >&4
            ;;
        *) dflt="$dflt $flag";
            eval $callback
@@ -5352,7 +5444,7 @@ if $cc $_sysroot -O2 $flag -o gcctest gcctest.c 2>gcctest.out && $run ./gcctest;
        esac
     fi
 else
-    echo "Nope, it does not, but that is ok." 2>&1;
+    echo "Nope, it does not, but that is ok." >&4;
 fi
 '
 
@@ -9325,9 +9417,7 @@ $cat <<EOM
 
 If you or somebody else will be maintaining perl at your site, please
 fill in the correct e-mail address here so that they may be contacted
-if necessary. Currently, the "perlbug" program included with perl
-will send mail to this address in addition to perlbug@perl.org. You may
-enter "none" for no administrator.
+if necessary. You may enter "none" for no administrator.
 
 EOM
 case "$perladmin" in
@@ -11263,6 +11353,34 @@ set d_attribute_always_inline
 eval $setvar
 $rm -f attrib*
 
+: Look for GCC-style attribute visibility
+case "$d_attribute_visibility" in
+'')
+echo " "
+echo "Checking whether your compiler can handle __attribute__((visibility)) ..." >&4
+$cat >attrib.c <<'EOCP'
+#include <stdio.h>
+__attribute__((visibility("hidden"))) int I_will_be_hidden(void);
+EOCP
+if $cc $ccflags -c attrib.c >attrib.out 2>&1 ; then
+        if $compiler_warning attrib.out >/dev/null 2>&1; then
+                echo "Your C compiler doesn't support __attribute__((visibility))."
+                val="$undef"
+        else
+                echo "Your C compiler supports __attribute__((visibility))."
+                val="$define"
+        fi
+else
+        echo "Your C compiler doesn't seem to understand __attribute__ at all."
+        val="$undef"
+fi
+;;
+*) val="$d_attribute_visibility" ;;
+esac
+set d_attribute_visibility
+eval $setvar
+$rm -f attrib*
+
 : see if getpgrp exists
 set getpgrp d_getpgrp
 eval $inlibc
@@ -12676,6 +12794,10 @@ eval $inlibc
 set dup3 d_dup3
 eval $inlibc
 
+: see if localeconv_l exists
+set localeconv_l d_localeconv_l
+eval $inlibc
+
 : see if this is an xlocale.h system
 set xlocale.h i_xlocale
 eval $inhdr
@@ -12700,6 +12822,54 @@ eval $inlibc
 set querylocale d_querylocale
 eval $inlibc
 
+: if we have xlocale.h, check whether it is needed
+case "$i_xlocale$d_newlocale$xlocale_needed" in
+"$define$define")
+       echo "Checking if xlocale.h is needed..." >&4
+       $cat >try.c <<EOF
+#include <locale.h>
+#include <stdio.h>
+#ifdef TRY_XLOCALE
+#include <xlocale.h>
+#endif
+#$d_localeconv_l HAVE_LOCALECONV_L
+
+#ifdef HAVE_LOCALECONV_L
+struct lconv *(*lcptr)(locale_t) = localeconv_l;
+#endif
+
+int main(void) {
+  locale_t lc = newlocale(LC_ALL_MASK, "C", (locale_t)0);
+
+#ifdef HAVE_LOCALECONV_L
+  /* FreeBSD hides only localeconv_l() in xlocale.h */
+  struct lconv *lcbuf = localeconv_l(lc);
+  printf("decimal: %s\n", lcbuf->decimal_point);
+#endif
+
+  freelocale(lc);
+  return 0;
+}
+EOF
+       set try
+       if eval $compile && $run ./try > /dev/null 2>&1 ; then
+               echo "xlocale.h isn't needed" >&4
+               xlocale_needed=$undef
+       else
+               set try -DTRY_XLOCALE
+               if eval $compile && $run ./try > /dev/null 2>&1 ; then
+                       xlocale_needed=$define
+                       echo "xlocale.h is needed" >&4
+               else
+                       echo "I can't build my test either way" >&4
+                       xlocale_needed=$undef
+               fi
+       fi
+       $rm_try
+       ;;
+*) xlocale_needed=$undef ;;
+esac
+
 : see if eaccess exists
 set eaccess d_eaccess
 eval $inlibc
@@ -13745,7 +13915,7 @@ case "$d_stdstdio:$d_stdio_ptr_lval" in
 "$define:$define")
        case "$d_stdio_cnt_lval$d_stdio_ptr_lval_sets_cnt" in
        *$define*)
-               echo "You seem to have 'fast stdio' to directly manipulate the stdio buffers." >& 4
+               echo "You seem to have 'fast stdio' to directly manipulate the stdio buffers." >&4
                val="$define"
                ;;
        esac
@@ -13942,6 +14112,13 @@ eval $inlibc
 set fegetround d_fegetround
 eval $inlibc
 
+: see if ffs exists
+set ffs d_ffs
+eval $inlibc
+: see if ffsl exists
+set ffsl d_ffsl
+eval $inlibc
+
 : see if fgetpos exists
 set fgetpos d_fgetpos
 eval $inlibc
@@ -14249,7 +14426,7 @@ $cat >try.c <<EOCP
 void *
 thread_start(void * arg)
 {
-    (void *) getenv("HOME");
+    return (void *) getenv("HOME");
 }
 
 int main() {
@@ -14280,7 +14457,7 @@ int main() {
         exit(2);
     }
 
-    exit(! strcmp(main_buffer, save_main_buffer) == 0);
+    exit(! (strcmp(main_buffer, save_main_buffer) == 0));
 }
 EOCP
 val=
@@ -16079,10 +16256,6 @@ eval $inlibc
 set llroundl d_llroundl
 eval $inlibc
 
-: see if localeconv_l exists
-set localeconv_l d_localeconv_l
-eval $inlibc
-
 : see if localtime_r exists
 set localtime_r d_localtime_r
 eval $inlibc
@@ -16541,6 +16714,130 @@ eval $inhdr
 set nl_langinfo d_nl_langinfo
 eval $inlibc
 
+: see if locale.h is available
+set locale.h i_locale
+eval $inhdr
+
+: check for nl_langinfo_l item
+$cat <<EOM
+
+Checking to see if you have nl_langinfo_l(), and that it is thread-safe
+EOM
+$cat >try.c <<EOCP
+#$i_stdlib I_STDLIB
+#ifdef I_STDLIB
+#  include <stdlib.h>
+#endif
+#include <string.h>
+#$i_langinfo I_LANGINFO
+#ifdef I_LANGINFO
+#  include <langinfo.h>
+#endif
+#$i_pthread I_PTHREAD
+#ifdef I_PTHREAD
+#  include <pthread.h>
+#endif
+#$i_locale I_LOCALE
+#ifdef I_LOCALE
+#  include <locale.h>
+#endif
+
+void *
+thread_start(void * arg)
+{
+    nl_langinfo(RADIXCHAR);
+}
+
+int main() {
+    char * main_buffer;
+    char save_main_buffer[1000];
+    pthread_t subthread;
+    pthread_attr_t attr;
+
+    main_buffer = nl_langinfo_l(CODESET, newlocale(LC_ALL_MASK, "C", 0));
+
+    /* If too large for our generous allowance, just assume we don't have
+     * it. */
+    if (strlen(main_buffer) >= sizeof(save_main_buffer)) {
+        exit(1);
+    }
+
+    strcpy(save_main_buffer, main_buffer);
+
+    if (pthread_attr_init(&attr) != 0) {
+        exit(1);
+    }
+
+    if (pthread_create(&subthread, &attr, thread_start, NULL) != 0) {
+        exit(1);
+    }
+
+    if (pthread_join(subthread, NULL) != 0) {
+        exit(1);
+    }
+
+    exit(! (strcmp(main_buffer, save_main_buffer) == 0));
+}
+EOCP
+case "$usethreads" in
+    define)
+        set try
+        if eval $compile; then
+            echo "Your system has nl_langinfo_l()..." >&4
+            d_nl_langinfo_l="$define"
+            echo "$d_nl_langinfo_l" >&4
+            if $run ./try; then
+                echo "and it is thread-safe (just as I'd hoped)." >&4
+                d_thread_safe_nl_langinfo_l="$define"
+                echo "$d_thread_safe_nl_langinfo_l" >&4
+            else
+                echo "but it isn't thread-safe." >&4
+            fi
+        else
+            echo "your system does not have nl_langinfo_l()" >&4
+        fi
+        ;;
+    *) echo "Since threads aren't selected, we won't bother looking for nl_langinfo_l()" >&4
+esac
+if test X"$d_nl_langinfo_l" = X; then
+       d_nl_langinfo_l="$undef"
+fi
+if test X"$d_thread_safe_nl_langinfo_l" = X; then
+       d_thread_safe_nl_langinfo_l="$undef"
+fi
+$rm_try
+
+: Look for non 'int'-sized bitfields
+case "$d_non_int_bitfields" in
+'')
+echo " " >&4
+echo "Checking whether your compiler can handle struct bitfields that aren't 'int' or 'unsigned int' ..." >&4
+$cat >try.c <<'EOCP'
+#include <stdio.h>
+struct foo {
+    unsigned char byte:1;
+    unsigned short halfword:1;
+} bar;
+EOCP
+if $cc $ccflags -c try.c >try.out 2>&1 ; then
+       if $compiler_warning try.out >/dev/null 2>&1; then
+               echo "Your C compiler doesn't support struct bitfields that aren't 'int' or 'unsigned int'." >&4
+               val="$undef"
+       else
+               echo "Your C compiler supports struct bitfields besides 'int' and 'unsigned int'." >&4
+               val="$define"
+       fi
+else
+       echo "Your C compiler doesn't seem to understand struct bitfields that aren't 'int' or 'unsigned int' at all." >&4
+       val="$undef"
+fi
+;;
+*) val="$d_non_int_bitfields" ;;
+esac
+set d_non_int_bitfields
+eval $setvar
+$rm_try
+
 : see if this is a quadmath.h system
 set quadmath.h i_quadmath
 eval $inhdr
@@ -16744,6 +17041,10 @@ $cat <<EOP >try.c
 #ifdef I_STDLIB
 #include <stdlib.h>
 #endif
+#$i_inttypes I_INTTYPES
+#ifdef I_INTTYPES
+#include <inttypes.h>
+#endif
 #include <sys/types.h>
 #include <signal.h>
 #ifdef SIGFPE
 case "$nv_preserves_uv_bits" in
 \-[1-9]*)
        nv_preserves_uv_bits=`expr 0 - $nv_preserves_uv_bits`
-       $echo "Your NVs can preserve all $nv_preserves_uv_bits bits of your UVs."  2>&1
+       $echo "Your NVs can preserve all $nv_preserves_uv_bits bits of your UVs."  >&4
        d_nv_preserves_uv="$define"
        ;;
-[1-9]*)        $echo "Your NVs can preserve only $nv_preserves_uv_bits bits of your UVs."  2>&1
+[1-9]*)        $echo "Your NVs can preserve only $nv_preserves_uv_bits bits of your UVs."  >&4
        d_nv_preserves_uv="$undef" ;;
-*)     $echo "Can't figure out how many bits your NVs preserve." 2>&1
+*)     $echo "Can't figure out how many bits your NVs preserve." >&4
        nv_preserves_uv_bits="0" ;;
 esac
 $rm_try
@@ -17796,6 +18097,10 @@ eval $inlibc
 set setegid d_setegid
 eval $inlibc
 
+: see if setenv exists
+set setenv d_setenv
+eval $inlibc
+
 : see if seteuid exists
 set seteuid d_seteuid
 eval $inlibc
@@ -17906,10 +18211,6 @@ eval $inlibc
 set setlinebuf d_setlinebuf
 eval $inlibc
 
-: see if locale.h is available
-set locale.h i_locale
-eval $inhdr
-
 : see if this system has wctype.h
 set wctype.h i_wctype
 eval $inhdr
@@ -18063,7 +18364,7 @@ case $d_setlocale in
            echo "Your system has setlocale()..." >&4
            $run ./try
            case $? in
-               0) echo "and it seems sane; you don't have a C.UTF8 locale" >&4
+               0) echo "and it seems sane; you don't have a C.UTF-8 locale" >&4
                   d_setlocale="$define"
                   d_setlocale_accepts_any_locale_name="$undef"
                   d_has_C_UTF8="false"
@@ -18073,7 +18374,7 @@ case $d_setlocale in
                   d_setlocale_accepts_any_locale_name="$define"
                   d_has_C_UTF8="false"
                   ;;
-               2) echo "and it seems sane; you have a C.UTF8 locale" >&4
+               2) echo "and it seems sane; you have a C.UTF-8 locale" >&4
                   d_setlocale="$define"
                   d_setlocale_accepts_any_locale_name="$undef"
                   d_has_C_UTF8="true"
@@ -18105,12 +18406,12 @@ $rm_try
         $undef) echo "There may be other ways to set the locale on your system, so we need to ask:" >&4
         ;;
     esac
-    rp="Does your system have the C.UTF8 locale?"
+    rp="Does your system have the C.UTF-8 locale?"
     dflt=n
     . ./myread
     case "$ans" in
         [Yy]*) d_has_C_UTF8="true"
-               c_utf8_locale=" or C.UTF8"
+               c_utf8_locale=" or C.UTF-8"
                ;;
         *)     d_has_C_UTF8="false"
                c_utf8_locale=""
@@ -19470,6 +19771,10 @@ esac
 set strxfrm d_strxfrm
 eval $inlibc
 
+: see if strxfrm_l exists
+set strxfrm_l d_strxfrm_l
+eval $inlibc
+
 : see if symlink exists
 set symlink d_symlink
 eval $inlibc
@@ -19520,88 +19825,127 @@ eval $hasproto
 set tgamma d_tgamma
 eval $inlibc
 
-: check for thread_safe_nl_langinfo_l item
-$cat <<EOM
+: see what flavor, if any, of thread local storage is supported
+echo " "
+echo "Checking to see if your system supports C11 thread local storage..."
+$cat > try.c <<'EOCP'
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
 
-Checking to see if you have nl_langinfo_l() and that it is thread-safe
-EOM
-$cat >try.c <<EOCP
-#$i_stdlib I_STDLIB
-#ifdef I_STDLIB
-#  include <stdlib.h>
-#endif
-#include <string.h>
-#$i_langinfo I_LANGINFO
-#ifdef I_LANGINFO
-#  include <langinfo.h>
-#endif
-#$i_pthread I_PTHREAD
-#ifdef I_PTHREAD
-#  include <pthread.h>
-#endif
-#$i_locale I_LOCALE
-#ifdef I_LOCALE
-#  include <locale.h>
-#endif
+static int plus_one = 1;
+static int minus_one = -1;
 
-void *
-thread_start(void * arg)
-{
-    nl_langinfo(RADIXCHAR);
+PROBE_MACRO int *minion;
+
+int callback (const void *a, const void *b) {
+    int val_a = *minion * *(const int *)a;
+    int val_b = *minion * *(const int *)b;
+    return val_a < val_b ? -1 : val_a > val_b;
 }
 
-int main() {
-    char * main_buffer;
-    char save_main_buffer[1000];
-    pthread_t subthread;
-    pthread_attr_t attr;
+#define SIZE 8
 
-    main_buffer = nl_langinfo_l(CODESET, newlocale(LC_ALL_MASK, "C", 0));
+void *thread_function(void *arg) {
+    /* thread local variables should start zeroed in each thread. */
+    if (minion != NULL) {
+        fprintf(stderr, "__thread variable started with %p, should be NULL\n",
+                minion);
+        exit(2);
+    }
+    minion = &minus_one;
 
-    /* If too large for our generous allowance, just assume we don't have
-     * it. */
-    if (strlen(main_buffer) >= sizeof(save_main_buffer)) {
-        exit(1);
+    int array[SIZE];
+    unsigned int i;
+    for (i = 0; i < SIZE; ++i) {
+        /* "Hash randomisation" - this array isn't in sorted order: */
+        array[i ^ 5] = i * i;
     }
 
-    strcpy(save_main_buffer, main_buffer);
+    qsort(array, SIZE, sizeof(int), callback);
 
-    if (pthread_attr_init(&attr) != 0) {
-        exit(1);
+    int bad = 0;
+    for (i = 0; i < SIZE; ++i) {
+        int want = (SIZE - 1 - i) * (SIZE - 1 - i);
+        int have = array[i];
+        if (want != have) {
+            ++bad;
+            fprintf(stderr, "array[%u] - want %i, have %i\n", i, want, have);
+        }
     }
+    if (bad)
+        exit(3);
 
-    if (pthread_create(&subthread, &attr, thread_start, NULL) != 0) {
-        exit(1);
+    return NULL;
+}
+
+int main(int argc, char **argv) {
+    if (minion != NULL) {
+        fprintf(stderr, "__thread variable started with %p, should be NULL\n",
+                minion);
+        exit(4);
     }
 
-    if (pthread_join(subthread, NULL) != 0) {
-        exit(1);
+    minion = &plus_one;
+
+    pthread_t tid;
+    int result = pthread_create(&tid, NULL, thread_function, NULL);
+    if (result) {
+        fprintf(stderr, "pthread_create failed (%d)\n", result);
+        exit(5);
     }
 
-    exit(! (strcmp(main_buffer, save_main_buffer) == 0));
+    result = pthread_join(tid, NULL);
+    if (result) {
+        fprintf(stderr, "pthread_join failed (%d)\n", result);
+        exit(6);
+    }
+
+    if (minion == NULL) {
+        fprintf(stderr, "__thread variable should not be NULL\n");
+        exit(7);
+    }
+    if (!(minion == &plus_one && *minion == 1)) {
+        fprintf(stderr, "__thread variable should be %d @ %p, not %d @ %p\n",
+                1, &plus_one, *minion, minion);
+        exit(8);
+    }
+
+    return 0;
 }
 EOCP
-case "$usethreads" in
-    define)
-        set try
-        if eval $compile; then
-            echo "Your system has nl_langinfo_l()..." >&4
-            if $run ./try; then
-                echo "and it is thread-safe (just as I'd hoped)." >&4
-                d_thread_safe_nl_langinfo_l="$define"
-                echo "$d_thread_safe_nl_langinfo_l" >&4
-            else
-                echo "but it isn't thread-safe, so we won't use it." >&4
-            fi
-        else
-            echo "your system does not have nl_langinfo_l()" >&4
-        fi
-        ;;
-    *) echo "Since threads aren't selected, we won't bother looking for nl_langinfo_l()" >&4
+
+# Respect a hint (or previous) value for perl_thread_local, if there is one.
+case "$perl_thread_local" in
+'')    # Check the various possibilities, and break out on success.
+       for thread_local in _Thread_local __thread; do
+               set try -DPROBE_MACRO=$thread_local
+               if eval $compile && $run ./try; then
+                       $echo "Your compiler supports $thread_local." >&4
+                       val=$define
+                       perl_thread_local="$thread_local";
+                       break;
+               fi
+               $echo "Your compiler does NOT support $thread_local." >&4
+               val="$undef"
+       done
+       ;;
+*thread*|*Thread*) # Some variant of thread local exists.
+       echo "Keeping your $hint value of $perl_thread_local."
+       val=$define
+       ;;
+*)  # Unrecognized previous value -- blindly trust the supplied
+       # value and hope it makes sense.  Use old value for
+       # d_thread_local, if there is one.
+       echo "Keeping your $hint value of $perl_thread_local."
+       case "$d_thread_local" in
+               '') val=$define ;;
+               *)  val=$d_thread_local ;;
+       esac
+       ;;
 esac
-if test X"$d_thread_safe_nl_langinfo_l" = X; then
-       d_thread_safe_nl_langinfo_l="$undef"
-fi
+set d_thread_local
+eval $setvar
 $rm_try
 
 : see if time exists
@@ -19799,6 +20143,10 @@ EOM
 #ifdef I_STDLIB
 #include <stdlib.h>
 #endif
+#$i_inttypes I_INTTYPES
+#ifdef I_INTTYPES
+#include <inttypes.h>
+#endif
 #include <sys/types.h>
 typedef $uvtype UV;
 int main()
@@ -20495,10 +20843,12 @@ int main(int argc, char *argv[]) {
     memset((char *)&ldinf + 10, '\0', LONG_DOUBLESIZE - 10);
     memset((char *)&ldnan + 10, '\0', LONG_DOUBLESIZE - 10);
 # endif
+#endif
   if (argc == 2) {
     switch (argv[1][0]) {
     case '1': bytes(&dinf, sizeof(dinf)); break;
     case '2': bytes(&dnan, sizeof(dnan)); break;
+#ifdef HAS_LONG_DOUBLE
     case '3': bytes(&ldinf, sizeof(ldinf)); break;
     case '4': bytes(&ldnan, sizeof(ldnan)); break;
 #endif
@@ -21305,7 +21655,7 @@ EOCP
                case "$yyy" in
                12345678901)
                        sPRId64=PRId64; sPRIi64=PRIi64; sPRIu64=PRIu64;
-                       sPRIo64=PRIo64; sPRIx64=PRIx64; sPRIXU64=PRIXU64;
+                       sPRIo64=PRIo64; sPRIx64=PRIx64; sPRIXU64=PRIX64;
                        echo "We will use the C9X style."
                        ;;
                esac
@@ -21462,6 +21812,45 @@ case "$ivdformat" in
     ;;
 esac
 
+case "$i32dformat" in
+'')    case "$i32type" in
+       int)
+               i32dformat='"d"'
+               u32uformat='"u"'
+               u32oformat='"o"'
+               u32xformat='"x"'
+               u32XUformat='"X"'
+               ;;
+       long)
+               i32dformat='"ld"'
+               u32uformat='"lu"'
+               u32oformat='"lo"'
+               u32xformat='"lx"'
+               u32XUformat='"lX"'
+               ;;
+       int_least32_t)                  : will not happen currently
+               i32dformat=PRIdLEAST32
+               u32uformat=PRIuLEAST32
+               u32oformat=PRIoLEAST32
+               u32xformat=PRIxLEAST32
+               u32XUformat=PRIXLEAST32
+               ;;
+       int32_t)
+               i32dformat=PRId32
+               u32uformat=PRIu32
+               u32oformat=PRIo32
+               u32xformat=PRIx32
+               u32XUformat=PRIX32
+               ;;
+       esac ;;
+esac
+
+case "$i32dformat" in
+'') echo "$0: Fatal: failed to find format strings for 32-bit integers, cannot continue." >&4
+    exit 1
+    ;;
+esac
+
 : Check format string for GID
 
 echo " "
@@ -22575,6 +22964,74 @@ EOM
 fi
 $rm_try
 
+: Check the size of st_dev
+$echo " "
+$echo "Checking the size of st_dev..." >&4
+$cat > try.c <<EOCP
+#include <sys/stat.h>
+#include <stdio.h>
+#$i_stdlib I_STDLIB
+#ifdef I_STDLIB
+#include <stdlib.h>
+#endif
+int main() {
+    struct stat st;
+    printf("%d\n", (int)sizeof(st.st_dev));
+    exit(0);
+}
+EOCP
+set try
+if eval $compile_ok; then
+       val=`$run ./try`
+       case "$val" in
+       '')     st_dev_size=4
+               $echo "(I can't execute the test program--guessing $st_dev_size.)" >&4
+               ;;
+       *)      st_dev_size=$val
+               $echo "Your st_dev is $st_dev_size bytes long."
+               ;;
+       esac
+else
+       st_dev_size=4
+       $echo "(I can't compile the test program--guessing $st_dev_size.)" >&4
+fi
+$rm_try
+
+: Check if st_dev is signed
+$echo " "
+$echo "Checking the sign of st_dev..." >&4
+$cat > try.c <<EOCP
+#include <sys/stat.h>
+#include <stdio.h>
+int main() {
+       struct stat foo;
+        foo.st_dev = -1;
+       if (foo.st_dev < 0)
+               printf("-1\n");
+       else
+               printf("1\n");
+}
+EOCP
+set try
+if eval $compile; then
+       val=`$run ./try`
+       case "$val" in
+       '')     st_dev_sign=1
+               $echo "(I can't execute the test program--guessing unsigned.)" >&4
+               ;;
+       *)      st_dev_sign=$val
+               case "$st_dev_sign" in
+                1) $echo "Your st_dev is unsigned." ;;
+               -1) $echo "Your st_dev is signed."   ;;
+               esac
+               ;;
+       esac
+else
+       st_dev_sign=1
+       $echo "(I can't compile the test program--guessing unsigned.)" >&4
+fi
+$rm_try
+
 : Check the size of st_ino
 $echo " "
 $echo "Checking the size of st_ino..." >&4
@@ -24232,6 +24689,7 @@ d_attribute_nonnull='$d_attribute_nonnull'
 d_attribute_noreturn='$d_attribute_noreturn'
 d_attribute_pure='$d_attribute_pure'
 d_attribute_unused='$d_attribute_unused'
+d_attribute_visibility='$d_attribute_visibility'
 d_attribute_warn_unused_result='$d_attribute_warn_unused_result'
 d_backtrace='$d_backtrace'
 d_bsd='$d_bsd'
@@ -24320,6 +24778,8 @@ d_fdclose='$d_fdclose'
 d_fdim='$d_fdim'
 d_fds_bits='$d_fds_bits'
 d_fegetround='$d_fegetround'
+d_ffs='$d_ffs'
+d_ffsl='$d_ffsl'
 d_fgetpos='$d_fgetpos'
 d_finite='$d_finite'
 d_finitel='$d_finitel'
@@ -24527,6 +24987,8 @@ d_nextafter='$d_nextafter'
 d_nexttoward='$d_nexttoward'
 d_nice='$d_nice'
 d_nl_langinfo='$d_nl_langinfo'
+d_nl_langinfo_l='$d_nl_langinfo_l'
+d_non_int_bitfields='$d_non_int_bitfields'
 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'
@@ -24596,6 +25058,7 @@ d_semget='$d_semget'
 d_semop='$d_semop'
 d_sendmsg='$d_sendmsg'
 d_setegid='$d_setegid'
+d_setenv='$d_setenv'
 d_seteuid='$d_seteuid'
 d_setgrent='$d_setgrent'
 d_setgrent_r='$d_setgrent_r'
@@ -24694,6 +25157,7 @@ d_strtoul='$d_strtoul'
 d_strtoull='$d_strtoull'
 d_strtouq='$d_strtouq'
 d_strxfrm='$d_strxfrm'
+d_strxfrm_l='$d_strxfrm_l'
 d_suidsafe='$d_suidsafe'
 d_symlink='$d_symlink'
 d_syscall='$d_syscall'
@@ -24707,6 +25171,7 @@ d_tcsetpgrp='$d_tcsetpgrp'
 d_telldir='$d_telldir'
 d_telldirproto='$d_telldirproto'
 d_tgamma='$d_tgamma'
+d_thread_local='$d_thread_local'
 d_thread_safe_nl_langinfo_l='$d_thread_safe_nl_langinfo_l'
 d_time='$d_time'
 d_timegm='$d_timegm'
@@ -24849,6 +25314,7 @@ html3dir='$html3dir'
 html3direxp='$html3direxp'
 i16size='$i16size'
 i16type='$i16type'
+i32dformat='$i32dformat'
 i32size='$i32size'
 i32type='$i32type'
 i64size='$i64size'
@@ -25082,6 +25548,7 @@ perl5='$perl5'
 perl='$perl'
 perl_patchlevel='$perl_patchlevel'
 perl_static_inline='$perl_static_inline'
+perl_thread_local='$perl_thread_local'
 perladmin='$perladmin'
 perllibs='$perllibs'
 perlpath='$perlpath'
@@ -25193,6 +25660,8 @@ srand48_r_proto='$srand48_r_proto'
 srandom_r_proto='$srandom_r_proto'
 src='$src'
 ssizetype='$ssizetype'
+st_dev_sign='$st_dev_sign'
+st_dev_size='$st_dev_size'
 st_ino_sign='$st_ino_sign'
 st_ino_size='$st_ino_size'
 startperl='$startperl'
@@ -25233,8 +25702,12 @@ troff='$troff'
 ttyname_r_proto='$ttyname_r_proto'
 u16size='$u16size'
 u16type='$u16type'
+u32XUformat='$u32XUformat'
+u32oformat='$u32oformat'
 u32size='$u32size'
 u32type='$u32type'
+u32uformat='$u32uformat'
+u32xformat='$u32xformat'
 u64size='$u64size'
 u64type='$u64type'
 u8size='$u8size'
@@ -25311,6 +25784,7 @@ version_patchlevel_string='$version_patchlevel_string'
 versiononly='$versiononly'
 vi='$vi'
 xlibpth='$xlibpth'
+xlocale_needed='$xlocale_needed'
 yacc='$yacc'
 yaccflags='$yaccflags'
 zcat='$zcat'