@@ -11562,7 +11562,9 @@ S_hextract(pTHX_ const NV nv, int* exponent, bool *subnormal,
11562
11562
* The rest of the args have the same meaning as the local vars of the
11563
11563
* same name within Perl_sv_vcatpvfn_flags().
11564
11564
*
11565
- * It assumes the caller has already done STORE_LC_NUMERIC_SET_TO_NEEDED();
11565
+ * The caller's determination of IN_LC(LC_NUMERIC), passed as in_lc_numeric,
11566
+ * is used to ensure we do the right thing when we need to access the locale's
11567
+ * numeric radix.
11566
11568
*
11567
11569
* It requires the caller to make buf large enough.
11568
11570
*/
@@ -11571,7 +11573,7 @@ static STRLEN
11571
11573
S_format_hexfp (pTHX_ char * const buf , const STRLEN bufsize , const char c ,
11572
11574
const NV nv , const vcatpvfn_long_double_t fv ,
11573
11575
bool has_precis , STRLEN precis , STRLEN width ,
11574
- bool alt , char plus , bool left , bool fill )
11576
+ bool alt , char plus , bool left , bool fill , bool in_lc_numeric )
11575
11577
{
11576
11578
/* Hexadecimal floating point. */
11577
11579
char * p = buf ;
@@ -11778,17 +11780,19 @@ S_format_hexfp(pTHX_ char * const buf, const STRLEN bufsize, const char c,
11778
11780
11779
11781
if (hexradix ) {
11780
11782
#ifndef USE_LOCALE_NUMERIC
11781
- * p ++ = '.' ;
11783
+ * p ++ = '.' ;
11782
11784
#else
11783
- if (IN_LC (LC_NUMERIC )) {
11784
- STRLEN n ;
11785
+ if (in_lc_numeric ) {
11786
+ STRLEN n ;
11787
+ WITH_LC_NUMERIC_SET_TO_NEEDED ({
11785
11788
const char * r = SvPV (PL_numeric_radix_sv , n );
11786
11789
Copy (r , p , n , char );
11787
- p += n ;
11788
- }
11789
- else {
11790
- * p ++ = '.' ;
11791
- }
11790
+ });
11791
+ p += n ;
11792
+ }
11793
+ else {
11794
+ * p ++ = '.' ;
11795
+ }
11792
11796
#endif
11793
11797
}
11794
11798
@@ -11894,9 +11898,10 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
11894
11898
char ebuf [IV_DIG * 4 + NV_DIG + 32 ];
11895
11899
bool no_redundant_warning = FALSE; /* did we use any explicit format parameter index? */
11896
11900
#ifdef USE_LOCALE_NUMERIC
11897
- DECLARATION_FOR_LC_NUMERIC_MANIPULATION ;
11898
- bool lc_numeric_set = FALSE; /* called STORE_LC_NUMERIC_SET_TO_NEEDED? */
11901
+ bool have_in_lc_numeric = FALSE;
11899
11902
#endif
11903
+ /* we never change this unless USE_LOCALE_NUMERIC */
11904
+ bool in_lc_numeric = FALSE;
11900
11905
11901
11906
PERL_ARGS_ASSERT_SV_VCATPVFN_FLAGS ;
11902
11907
PERL_UNUSED_ARG (maybe_tainted );
@@ -12967,33 +12972,31 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
12967
12972
* below, or implicitly, via an snprintf() variant.
12968
12973
* Note also things like ps_AF.utf8 which has
12969
12974
* "\N{ARABIC DECIMAL SEPARATOR} as a radix point */
12970
- if (!lc_numeric_set ) {
12971
- /* only set once and reuse in-locale value on subsequent
12972
- * iterations.
12973
- * XXX what happens if we die in an eval?
12974
- */
12975
- STORE_LC_NUMERIC_SET_TO_NEEDED ();
12976
- lc_numeric_set = TRUE;
12975
+ if (! have_in_lc_numeric ) {
12976
+ in_lc_numeric = IN_LC (LC_NUMERIC );
12977
+ have_in_lc_numeric = TRUE;
12977
12978
}
12978
12979
12979
- if (IN_LC (LC_NUMERIC )) {
12980
- /* this can't wrap unless PL_numeric_radix_sv is a string
12981
- * consuming virtually all the 32-bit or 64-bit address
12982
- * space
12983
- */
12984
- float_need += (SvCUR (PL_numeric_radix_sv ) - 1 );
12985
-
12986
- /* floating-point formats only get utf8 if the radix point
12987
- * is utf8. All other characters in the string are < 128
12988
- * and so can be safely appended to both a non-utf8 and utf8
12989
- * string as-is.
12990
- * Note that this will convert the output to utf8 even if
12991
- * the radix point didn't get output.
12992
- */
12993
- if (SvUTF8 (PL_numeric_radix_sv ) && !has_utf8 ) {
12994
- sv_utf8_upgrade (sv );
12995
- has_utf8 = TRUE;
12996
- }
12980
+ if (in_lc_numeric ) {
12981
+ WITH_LC_NUMERIC_SET_TO_NEEDED ({
12982
+ /* this can't wrap unless PL_numeric_radix_sv is a string
12983
+ * consuming virtually all the 32-bit or 64-bit address
12984
+ * space
12985
+ */
12986
+ float_need += (SvCUR (PL_numeric_radix_sv ) - 1 );
12987
+
12988
+ /* floating-point formats only get utf8 if the radix point
12989
+ * is utf8. All other characters in the string are < 128
12990
+ * and so can be safely appended to both a non-utf8 and utf8
12991
+ * string as-is.
12992
+ * Note that this will convert the output to utf8 even if
12993
+ * the radix point didn't get output.
12994
+ */
12995
+ if (SvUTF8 (PL_numeric_radix_sv ) && !has_utf8 ) {
12996
+ sv_utf8_upgrade (sv );
12997
+ has_utf8 = TRUE;
12998
+ }
12999
+ });
12997
13000
}
12998
13001
#endif
12999
13002
@@ -13068,7 +13071,9 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
13068
13071
&& !fill
13069
13072
&& intsize != 'q'
13070
13073
) {
13071
- SNPRINTF_G (fv , ebuf , sizeof (ebuf ), precis );
13074
+ WITH_LC_NUMERIC_SET_TO_NEEDED (
13075
+ SNPRINTF_G (fv , ebuf , sizeof (ebuf ), precis )
13076
+ );
13072
13077
elen = strlen (ebuf );
13073
13078
eptr = ebuf ;
13074
13079
goto float_concat ;
@@ -13113,7 +13118,7 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
13113
13118
if (UNLIKELY (hexfp )) {
13114
13119
elen = S_format_hexfp (aTHX_ PL_efloatbuf , PL_efloatsize , c ,
13115
13120
nv , fv , has_precis , precis , width ,
13116
- alt , plus , left , fill );
13121
+ alt , plus , left , fill , in_lc_numeric );
13117
13122
}
13118
13123
else {
13119
13124
char * ptr = ebuf + sizeof ebuf ;
@@ -13169,8 +13174,10 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
13169
13174
const char * qfmt = quadmath_format_single (ptr );
13170
13175
if (!qfmt )
13171
13176
Perl_croak_nocontext ("panic: quadmath invalid format \"%s\"" , ptr );
13172
- elen = quadmath_snprintf (PL_efloatbuf , PL_efloatsize ,
13173
- qfmt , nv );
13177
+ WITH_LC_NUMERIC_SET_TO_NEEDED (
13178
+ elen = quadmath_snprintf (PL_efloatbuf , PL_efloatsize ,
13179
+ qfmt , nv );
13180
+ );
13174
13181
if ((IV )elen == -1 ) {
13175
13182
if (qfmt != ptr )
13176
13183
SAVEFREEPV (qfmt );
@@ -13180,11 +13187,15 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
13180
13187
Safefree (qfmt );
13181
13188
}
13182
13189
#elif defined(HAS_LONG_DOUBLE )
13183
- elen = ((intsize == 'q' )
13184
- ? my_snprintf (PL_efloatbuf , PL_efloatsize , ptr , fv )
13185
- : my_snprintf (PL_efloatbuf , PL_efloatsize , ptr , (double )fv ));
13190
+ WITH_LC_NUMERIC_SET_TO_NEEDED (
13191
+ elen = ((intsize == 'q' )
13192
+ ? my_snprintf (PL_efloatbuf , PL_efloatsize , ptr , fv )
13193
+ : my_snprintf (PL_efloatbuf , PL_efloatsize , ptr , (double )fv ))
13194
+ );
13186
13195
#else
13187
- elen = my_snprintf (PL_efloatbuf , PL_efloatsize , ptr , fv );
13196
+ WITH_LC_NUMERIC_SET_TO_NEEDED (
13197
+ elen = my_snprintf (PL_efloatbuf , PL_efloatsize , ptr , fv )
13198
+ );
13188
13199
#endif
13189
13200
GCC_DIAG_RESTORE_STMT ;
13190
13201
}
@@ -13406,16 +13417,6 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
13406
13417
}
13407
13418
13408
13419
SvTAINT (sv );
13409
-
13410
- #ifdef USE_LOCALE_NUMERIC
13411
-
13412
- if (lc_numeric_set ) {
13413
- RESTORE_LC_NUMERIC (); /* Done outside loop, so don't have to
13414
- save/restore each iteration. */
13415
- }
13416
-
13417
- #endif
13418
-
13419
13420
}
13420
13421
13421
13422
/* =========================================================================
0 commit comments