Fix locale problems on mingw
authorKarl Williamson <khw@cpan.org>
Sun, 18 Mar 2018 18:39:47 +0000 (12:39 -0600)
committerKarl Williamson <khw@cpan.org>
Mon, 19 Mar 2018 18:18:15 +0000 (12:18 -0600)
Various symbols get exported (or not) by makedef.pl.  The determination
of some of the new ones is fairly complex in perl.h, and unfortunately
in general the code logic to do so must be copied into makedef.pl (until
a volunteer fixes this).  I thought I could avoid a bunch of this by
using the symbol ${^SAFE_LOCALES} which in fact was created so that
programs wouldn't have to know about this complexity.

The problem is that on Windows, miniperl is always compiled
single-thread and so locales are always safe, and so makedef.pl (which
is called by miniperl) got the wrong information.  The solution,
unfortunately, is to reproduce the complexity in makedef.pl

Spotted by Daniel Dragan.

makedef.pl
perl.h

index 88273e5..f2beb94 100644 (file)
@@ -129,6 +129,32 @@ if ($define{USE_ITHREADS} && $ARGS{PLATFORM} ne 'win32' && $ARGS{PLATFORM} ne 'n
     $define{USE_REENTRANT_API} = 1;
 }
 
+if (     $define{USE_ITHREADS}
+    &&   $define{HAS_SETLOCALE}
+    && ! $define{NO_LOCALE}
+    && ! $define{NO_POSIX_2008_LOCALE})
+{
+    $define{HAS_POSIX_2008_LOCALE} = 1 if $define{HAS_NEWLOCALE}
+                                       && $define{HAS_FREELOCALE}
+                                       && $define{HAS_USELOCALE};
+    my $cctype = $ARGS{CCTYPE} =~ s/MSVC//r;
+    if (    ! $define{NO_THREAD_SAFE_LOCALE}
+        && (  $define{HAS_POSIX_2008_LOCALE}
+            || ($ARGS{PLATFORM} eq 'win32' && (   $cctype !~ /\D/
+                                               && $cctype >= 80))))
+    {
+        $define{USE_THREAD_SAFE_LOCALE} = 1;
+        $define{USE_POSIX_2008_LOCALE} = 1 if $define{HAS_POSIX_2008_LOCALE};
+    }
+
+    if (   $ARGS{PLATFORM} eq 'win32'
+        && $define{USE_THREAD_SAFE_LOCALE}
+        && $cctype < 140)
+    {
+        $define{TS_W32_BROKEN_LOCALECONV} = 1;
+    }
+}
+
 # perl.h logic duplication ends
 
 print STDERR "Defines: (" . join(' ', sort keys %define) . ")\n"
@@ -438,12 +464,12 @@ unless ($define{'PERL_IMPLICIT_CONTEXT'}) {
                         );
 }
 
-if (${^SAFE_LOCALES}) {    # Don't need mutexes if have thread-safe operations
-                           # except early versions of Windows need this one
-    ++$skip{PL_locale_mutex} unless $ARGS{PLATFORM} eq 'win32'
-                                && ($ARGS{CCTYPE} =~ s/MSVC//r) < 140;
+if ($define{USE_THREAD_SAFE_LOCALE}) {
     ++$skip{PL_lc_numeric_mutex};
     ++$skip{PL_lc_numeric_mutex_depth};
+    if (! $define{TS_W32_BROKEN_LOCALECONV}) {
+        ++$skip{PL_locale_mutex};
+    }
 }
 
 unless ($define{'PERL_OP_PARENT'}) {
diff --git a/perl.h b/perl.h
index e76b9b8..2a50015 100644 (file)
--- a/perl.h
+++ b/perl.h
 #   endif
 #endif /* !NO_LOCALE && HAS_SETLOCALE */
 
+/* XXX The next few defines are unfortunately duplicated in makedef.pl, and
+ * changes here MUST also be made there */
+
 #ifdef USE_LOCALE /* These locale things are all subject to change */
 #  if      defined(HAS_NEWLOCALE)               \
       &&   defined(LC_ALL_MASK)                 \