diff options
Diffstat (limited to 'vutil.c')
-rw-r--r-- | vutil.c | 32 |
1 files changed, 32 insertions, 0 deletions
@@ -591,6 +591,37 @@ VER_NV: char tbuf[64]; SV *sv = SvNVX(ver) > 10e50 ? newSV(64) : 0; char *buf; +#ifdef USE_LOCALE_NUMERIC + const char * const cur_numeric = setlocale(LC_NUMERIC, NULL); + assert(cur_numeric); + + /* XS code can set the locale without us knowing. To protect the + * version number parsing, which requires the radix character to be a + * dot, update our records as to what the locale is, so that our + * existing macro mechanism can correctly change it to a dot and back + * if necessary. This code is extremely unlikely to be in a loop, so + * the extra work will have a negligible performance impact. See [perl + * #121930]. + * + * If the current locale is a standard one, but we are expecting it to + * be a different, underlying locale, update our records to make the + * underlying locale this (standard) one. If the current locale is not + * a standard one, we should be expecting a non-standard one, the same + * one that we have recorded as the underlying locale. If not, update + * our records. */ + if (strEQ(cur_numeric, "C") || strEQ(cur_numeric, "POSIX")) { + if (! PL_numeric_standard) { + new_numeric(cur_numeric); + } + } + else if (PL_numeric_standard + || ! PL_numeric_name + || strNE(PL_numeric_name, cur_numeric)) + { + new_numeric(cur_numeric); + } +#endif + { /* Braces needed because macro just below declares a variable */ STORE_NUMERIC_LOCAL_SET_STANDARD(); LOCK_NUMERIC_STANDARD(); if (sv) { @@ -604,6 +635,7 @@ VER_NV: } UNLOCK_NUMERIC_STANDARD(); RESTORE_NUMERIC_LOCAL(); + } while (buf[len-1] == '0' && len > 0) len--; if ( buf[len-1] == '.' ) len--; /* eat the trailing decimal */ version = savepvn(buf, len); |