This is an (almost) drop-in replacement for the system setlocale(3), taking the same parameters, and returning the same information, except that it returns the correct underlying LC_NUMERIC locale. Regular setlocale will instead return C if the underlying locale has a non-dot decimal point character, or a non-empty thousands separator for displaying floating point numbers. This is because perl keeps that locale category such that it has a dot and empty separator, changing the locale briefly during the operations where the underlying one is required. Perl_setlocale knows about this, and compensates; regular setlocale doesn't.

Another reason it isn't completely a drop-in replacement is that it is declared to return const char *, whereas the system setlocale omits the const (presumably because its API was specified long ago, and can't be updated; it is illegal to change the information setlocale returns; doing so leads to segfaults.)

Finally, Perl_setlocale works under all circumstances, whereas plain setlocale can be completely ineffective on some platforms under some configurations.

Changing the locale is not a good idea when more than one thread is running, except on systems where the predefined variable ${^SAFE_LOCALES} is non-zero. This is because on such systems the locale is global to the whole process and not local to just the thread calling the function. So changing it in one thread instantaneously changes it in all. On some such systems, the system setlocale() is ineffective, returning the wrong information, and failing to actually change the locale. z/OS refuses to try to change the locale once a second thread is created. Perl_setlocale, should give you accurate results of what actually happened on these problematic platforms, returning NULL if the system forbade the locale change.

The return points to a per-thread static buffer, which is overwritten the next time Perl_setlocale is called from the same thread.

This is a thread-safe version of the libc localeconv(3). It is the same as POSIX::localeconv (returning a hash of the localeconv() fields), but directly callable from XS code. The hash is mortalized, so must be dealt with immediately.

Perl_langinfo is an (almost) drop-in replacement for the system nl_langinfo(3), taking the same item parameter values, and returning the same information. But it is more thread-safe than regular nl_langinfo(), and hides the quirks of Perl's locale handling from your code, and can be used on systems that lack a native nl_langinfo.

However, you should instead use either the improved version of this, "Perl_langinfo8", or even better, "sv_langinfo". The latter returns an SV, handling all the possible non-standard returns of nl_langinfo(), including the UTF8ness of any returned string.

Perl_langinfo8 is identical to Perl_langinfo except for an additional parameter, a pointer to a variable declared as "utf8ness_t", into which it returns to you how you should treat the returned string with regards to it being encoded in UTF-8 or not.

These two functions share private per-thread memory that will be changed the next time either one of them is called with any input, but not before.

Concerning the differences between these and plain nl_langinfo():

a.

Perl_langinfo8 has an extra parameter, described above. Besides this, the other reason they aren't quite a drop-in replacement is actually an advantage. The constness of the return allows the compiler to catch attempts to write into the returned buffer, which is illegal and could cause run-time crashes.

b.

They deliver the correct results for the RADIXCHAR and THOUSEP items, without you having to write extra code. The reason for the extra code would be because these are from the LC_NUMERIC locale category, which is normally kept set by Perl so that the radix is a dot, and the separator is the empty string, no matter what the underlying locale is supposed to be, and so to get the expected results, you have to temporarily toggle into the underlying locale, and later toggle back. (You could use plain nl_langinfo and "STORE_LC_NUMERIC_FORCE_TO_UNDERLYING" for this but then you wouldn't get the other advantages of Perl_langinfo(); not keeping LC_NUMERIC in the C (or equivalent) locale would break a lot of CPAN, which is expecting the radix (decimal point) character to be a dot.)

c.

The system function they replace can have its static return buffer trashed, not only by a subsequent call to that function, but by a freelocale, setlocale, or other locale change. The returned buffer of these functions is not changed until the next call to one or the other, so the buffer is never in a trashed state.

d.

The return buffer is per-thread, so it also is never overwritten by a call to these functions from another thread; unlike the function it replaces.

e.

But most importantly, they work on systems that don't have nl_langinfo, such as Windows, hence making your code more portable. Of the fifty-some possible items specified by the POSIX 2008 standard, https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/langinfo.h.html, only one is completely unimplemented, though on non-Windows platforms, another significant one is not fully implemented). They use various techniques to recover the other items, including calling localeconv(3), and strftime(3), both of which are specified in C89, so should be always be available. Later strftime() versions have additional capabilities. If an item is not available on your system, this returns either the value associated with the C locale, or simply "", whichever is more appropriate.

It is important to note that, when called with an item that is recovered by using localeconv, the buffer from any previous explicit call to localeconv(3) will be overwritten. But you shouldn't be using localeconv anyway because it is is very much not thread-safe, and suffers from the same problems outlined in item 'b.' above for the fields it returns that are controlled by the LC_NUMERIC locale category. Instead, avoid all of those problems by calling "Perl_localeconv", which is thread-safe; or by using the methods given in perlcall to call POSIX::localeconv(), which is also thread-safe.

The details for those items which may deviate from what this emulation returns and what a native nl_langinfo() would return are specified in I18N::Langinfo.

This is the preferred interface for accessing the data that nl_langinfo(3) provides (or Perl's emulation of it on platforms lacking it), returning an SV. Unlike, the earlier-defined interfaces to this ("Perl_langinfo" and "Perl_langinfo8"), which return strings, the UTF8ness of the result is automatically handled for you. And like them, it is thread-safe and automatically handles getting the proper values for the RADIXCHAR and THOUSEP items (that calling the plain libc nl_langinfo() could give the wrong results for). Like them, this also doesn't play well with the libc localeconv(); use POSIX::localeconv() instead.

There are a few deviations from what a native nl_langinfo() would return and what this returns on platforms that don't implement that function. These are detailed in I18N::Langinfo.

These implement the libc strftime().

On failure, they return NULL, and set errno to EINVAL.

sv_strftime_tm is preferred, as it transparently handles the UTF-8ness of the current locale, the input fmt, and the returned result. Only if the current LC_TIME locale is a UTF-8 one (and use bytes is not in effect) will the result be marked as UTF-8.

sv_strftime_tm takes a pointer to a filled-in struct tm parameter. It ignores the values of the wday and yday fields in it. The other fields give enough information to accurately calculate these values, and are used for that purpose.

The caller assumes ownership of the returned SV with a reference count of 1.

my_strftime is kept for backwards compatibility. Knowing if its result should be considered UTF-8 or not requires significant extra logic.

The return value is a pointer to the formatted result (which MUST be arranged to be FREED BY THE CALLER). This allows this function to increase the buffer size as needed, so that the caller doesn't have to worry about that, unlike libc strftime().

The wday, yday, and isdst parameters are ignored by my_strftime. Daylight savings time is never considered to exist, and the values returned for the other two fields (if fmt even calls for them) are calculated from the other parameters, without need for referencing these.

Note that both functions are always executed in the underlying LC_TIME locale of the program, giving results based on that locale.

This function copies the locale state of the calling thread into the program's global locale, and converts the thread to use that global locale.

It is intended so that Perl can safely be used with C libraries that access the global locale and which can't be converted to not access it. Effectively, this means libraries that call setlocale(3) on non-Windows systems. (For portability, it is a good idea to use it on Windows as well.)

A downside of using it is that it disables the services that Perl provides to hide locale gotchas from your code. The service you most likely will miss regards the radix character (decimal point) in floating point numbers. Code executed after this function is called can no longer just assume that this character is correct for the current circumstances.

To return to Perl control, and restart the gotcha prevention services, call "sync_locale". Behavior is undefined for any pure Perl code that executes while the switch is in effect.

The global locale and the per-thread locales are independent. As long as just one thread converts to the global locale, everything works smoothly. But if more than one does, they can easily interfere with each other, and races are likely. On Windows systems prior to Visual Studio 15 (at which point Microsoft fixed a bug), races can occur (even if only one thread has been converted to the global locale), but only if you use the following operations:

POSIX::localeconv
I18N::Langinfo, items CRNCYSTR and THOUSEP
"sv_langinfo" in perlapi, items CRNCYSTR and THOUSEP

The first item is not fixable (except by upgrading to a later Visual Studio release), but it would be possible to work around the latter two items by having Perl change its algorithm for calculating these to use Windows API functions (likely GetNumberFormat and GetCurrencyFormat); patches welcome.

XS code should never call plain setlocale, but should instead be converted to either call Perl_setlocale (which is a drop-in for the system setlocale) or use the methods given in perlcall to call POSIX::setlocale. Either one will transparently properly handle all cases of single- vs multi-thread, POSIX 2008-supported or not.

This function copies the state of the program global locale into the calling thread, and converts that thread to using per-thread locales, if it wasn't already, and the platform supports them. The LC_NUMERIC locale is toggled into the standard state (using the C locale's conventions), if not within the lexical scope of use locale.

Perl will now consider itself to have control of the locale.

Since unthreaded perls have only a global locale, this function is a no-op without threads.

This function is intended for use with C libraries that do locale manipulation. It allows Perl to accommodate the use of them. Call this function before transferring back to Perl space so that it knows what state the C code has left things in.

XS code should not manipulate the locale on its own. Instead, Perl_setlocale can be used at any time to query or change the locale (though changing the locale is antisocial and dangerous on multi-threaded systems that don't have multi-thread safe locale operations. (See "Multi-threaded operation" in perllocale).

Using the libc setlocale(3) function should be avoided. Nevertheless, certain non-Perl libraries called from XS, do call it, and their behavior may not be able to be changed. This function, along with "switch_to_global_locale", can be used to get seamless behavior in these circumstances, as long as only one thread is involved.

If the library has an option to turn off its locale manipulation, doing that is preferable to using this mechanism. Gtk is such a library.

The return value is a boolean: TRUE if the global locale at the time of call was in effect for the caller; and FALSE if a per-thread locale was in effect.