One area where there has been conflict is in regards to C locales. (See
L<perllocale>.) perl, with one exception and unless told otherwise,
-sets up the underlying locale the program is running in to that passed
-into it from the environment. As of v5.20, this underlying locale is
-completely hidden from pure perl code outside the lexical scope of
-C<S<use locale>>; except a couple of function calls in the POSIX
-module of necessity use it. But the underlying locale, with that one
-exception is exposed to XS code, affecting all C library routines whose
-behavior is locale-dependent. The exception is the
+sets up the underlying locale the program is running in to the locale
+passed
+into it from the environment. This is an important difference from a
+generic C language program, where the underlying locale is the "C"
+locale unless the program changes it. As of v5.20, this underlying
+locale is completely hidden from pure perl code outside the lexical
+scope of C<S<use locale>> except for a couple of function calls in the
+POSIX module which of necessity use it. But the underlying locale, with
+that
+one exception is exposed to XS code, affecting all C library routines
+whose behavior is locale-dependent. Your XS code better not assume that
+the underlying locale is "C". The exception is the
L<C<LC_NUMERIC>|perllocale/Category LC_NUMERIC: Numeric Formatting>
locale category, and the reason it is an exception is that experience
has shown that it can be problematic for XS code, whereas we have not
a function will indicate that dependency, but the documentation is
imperfect.
-The current locale is exposed to XS code except possibly C<LC_NUMERIC>.
-There have not been reports of problems with these other categories.
+The current locale is exposed to XS code except possibly C<LC_NUMERIC>
+(explained in the next paragraph).
+There have not been reports of problems with the other categories.
+Perl initializes things on start-up so that the current locale is the
+one which is indicated by the user's environment in effect at that time.
+See L<perllocale/ENVIRONMENT>.
-Up through v5.20, Perl initializes things on start-up so that
-C<LC_NUMERIC> is set to the "C" locale. But if any code anywhere
-changes it, it will stay changed. This means that your module can't
+However, up through v5.20, Perl initialized things on start-up so that
+C<LC_NUMERIC> was set to the "C" locale. But if any code anywhere
+changed it, it would stay changed. This means that your module can't
count on C<LC_NUMERIC> being something in particular, and you can't
expect floating point numbers (including version strings) to have dots
in them. If you don't allow for a non-dot, your code could break if
-anyone anywhere changes the locale. For this reason, v5.22 is changing
+anyone anywhere changed the locale. For this reason, v5.22 changed
the behavior so that Perl tries to keep C<LC_NUMERIC> in the "C" locale
except around the operations internally where it should be something
else. Misbehaving XS code will always be able to change the locale
Starting in v5.20.1, calling the function
L<sync_locale()|perlapi/sync_locale> from XS should be sufficient to
avoid most of these problems. Prior to this, you need a pure Perl
-segment that does this:
+statement that does this:
POSIX::setlocale(LC_ALL, POSIX::setlocale(LC_ALL));
-Macros are provided for XS code to temporarily change to use the
-underlying C<LC_NUMERIC> locale when necessary. An API is being
-developed for this, but has not yet been nailed down, but will be during
-the course of v5.21. Send email to L<mailto:perl5-porters@perl.org> for
-guidance.
+In the event that your XS code may need the underlying C<LC_NUMERIC>
+locale, there are macros available to access this; see
+L<perlapi/Locale-related functions and macros>.
=back
#ifdef USE_LOCALE_NUMERIC
/* These macros are for toggling between the underlying locale (UNDERLYING or
- * LOCAL) and the C locale (STANDARD). */
+ * LOCAL) and the C locale (STANDARD).
+
+=head1 Locale-related functions and macros
+
+=for apidoc Amn|void|DECLARATION_FOR_LC_NUMERIC_MANIPULATION
+
+This macro should be used as a statement. It declares a private variable
+(whose name begins with an underscore) that is needed by the other macros in
+this section. Failing to include this correctly should lead to a syntax error.
+For compatibility with C89 C compilers it should be placed in a block before
+any executable statements.
+
+=for apidoc Am|void|STORE_LC_NUMERIC_FORCE_TO_UNDERLYING
+
+This is used by XS code that that is C<LC_NUMERIC> locale-aware to force the
+locale for category C<LC_NUMERIC> to be what perl thinks is the current
+underlying locale. (The perl interpreter could be wrong about what the
+underlying locale actually is if some C or XS code has called the C library
+function L<setlocale(3)> behind its back; calling L</sync_locale> before calling
+this macro will update perl's records.)
+
+A call to L</DECLARATION_FOR_LC_NUMERIC_MANIPULATION> must have been made to
+declare at compile time a private variable used by this macro. This macro
+should be called as a single statement, not an expression, but with an empty
+argument list, like this:
+
+ {
+ DECLARATION_FOR_LC_NUMERIC_MANIPULATION;
+ ...
+ STORE_LC_NUMERIC_FORCE_TO_UNDERLYING();
+ ...
+ RESTORE_LC_NUMERIC();
+ ...
+ }
+
+The private variable is used to save the current locale state, so
+that the requisite matching call to L</RESTORE_LC_NUMERIC> can restore it.
+
+=for apidoc Am|void|STORE_LC_NUMERIC_SET_TO_NEEDED
+
+This is used to help wrap XS or C code that that is C<LC_NUMERIC> locale-aware.
+This locale category is generally kept set to the C locale by Perl for
+backwards compatibility, and because most XS code that reads floating point
+values can cope only with the decimal radix character being a dot.
+
+This macro makes sure the current C<LC_NUMERIC> state is set properly, to be
+aware of locale if the call to the XS or C code from the Perl program is
+from within the scope of a S<C<use locale>>; or to ignore locale if the call is
+instead from outside such scope.
+
+This macro is the start of wrapping the C or XS code; the wrap ending is done
+by calling the L</RESTORE_LC_NUMERIC> macro after the operation. Otherwise
+the state can be changed that will adversely affect other XS code.
+
+A call to L</DECLARATION_FOR_LC_NUMERIC_MANIPULATION> must have been made to
+declare at compile time a private variable used by this macro. This macro
+should be called as a single statement, not an expression, but with an empty
+argument list, like this:
+
+ {
+ DECLARATION_FOR_LC_NUMERIC_MANIPULATION;
+ ...
+ STORE_LC_NUMERIC_SET_TO_NEEDED();
+ ...
+ RESTORE_LC_NUMERIC();
+ ...
+ }
+
+=for apidoc Am|void|RESTORE_LC_NUMERIC
+
+This is used in conjunction with one of the macros
+L</STORE_LC_NUMERIC_SET_TO_NEEDED>
+and
+L</STORE_LC_NUMERIC_FORCE_TO_UNDERLYING>
+
+to properly restore the C<LC_NUMERIC> state.
+
+A call to L</DECLARATION_FOR_LC_NUMERIC_MANIPULATION> must have been made to
+declare at compile time a private variable used by this macro and the two
+C<STORE> ones. This macro should be called as a single statement, not an
+expression, but with an empty argument list, like this:
+
+ {
+ DECLARATION_FOR_LC_NUMERIC_MANIPULATION;
+ ...
+ RESTORE_LC_NUMERIC();
+ ...
+ }
+
+=cut
+
+*/
#define _NOT_IN_NUMERIC_STANDARD (! PL_numeric_standard)