diff options
Diffstat (limited to 'vutil.c')
-rw-r--r-- | vutil.c | 65 |
1 files changed, 64 insertions, 1 deletions
@@ -625,7 +625,11 @@ VER_NV: * locales without letting perl know, therefore we have to find it * from first principals. See [perl #121930]. */ - /* if it isn't C, set it to C. */ + /* In windows, or not threaded, or not thread-safe, if it isn't C, + * set it to C. */ + +# ifndef USE_POSIX_2008_LOCALE + const char * locale_name_on_entry; LC_NUMERIC_LOCK(0); /* Start critical section */ @@ -641,6 +645,48 @@ VER_NV: locale_name_on_entry = NULL; } +# else + + const locale_t locale_obj_on_entry = uselocale((locale_t) 0); + const char * locale_name_on_entry = NULL; + DECLARATION_FOR_LC_NUMERIC_MANIPULATION; + + if (locale_obj_on_entry == LC_GLOBAL_LOCALE) { + + /* in the global locale, we can call system setlocale and if it + * isn't C, set it to C. */ + LC_NUMERIC_LOCK(0); + + locale_name_on_entry = setlocale(LC_NUMERIC, NULL); + if ( strNE(locale_name_on_entry, "C") + && strNE(locale_name_on_entry, "POSIX")) + { + setlocale(LC_NUMERIC, "C"); + } + else { /* This value indicates to the restore code that we + didn't change the locale */ + locale_name_on_entry = NULL; + } + } + else if (locale_obj_on_entry == PL_underlying_numeric_obj) { + /* Here, the locale appears to have been changed to use the + * program's underlying locale. Just use our mechanisms to + * switch back to C. It might be possible for this pointer to + * actually refer to something else if it got released and + * reused somehow. But it doesn't matter, our mechanisms will + * work even so */ + STORE_LC_NUMERIC_SET_STANDARD(); + } + else if (locale_obj_on_entry != PL_C_locale_obj) { + /* The C object should be unchanged during a program's + * execution, so it should be safe to assume it means what it + * says, so if we are in it, no locale change is required. + * Otherwise, simply use the thread-safe operation. */ + uselocale(PL_C_locale_obj); + } + +# endif + /* Prevent recursed calls from trying to change back */ LOCK_LC_NUMERIC_STANDARD(); @@ -660,12 +706,29 @@ VER_NV: UNLOCK_LC_NUMERIC_STANDARD(); +# ifndef USE_POSIX_2008_LOCALE + if (locale_name_on_entry) { setlocale(LC_NUMERIC, locale_name_on_entry); } LC_NUMERIC_UNLOCK; /* End critical section */ +# else + + if (locale_name_on_entry) { + setlocale(LC_NUMERIC, locale_name_on_entry); + LC_NUMERIC_UNLOCK; + } + else if (locale_obj_on_entry == PL_underlying_numeric_obj) { + RESTORE_LC_NUMERIC(); + } + else if (locale_obj_on_entry != PL_C_locale_obj) { + uselocale(locale_obj_on_entry); + } + +# endif + } #endif /* USE_LOCALE_NUMERIC */ |