Perl_pregfree(aTHX_ (prog))
#define CALLREGFREE_PVT(prog) \
- if(prog) RX_ENGINE(prog)->free(aTHX_ (prog))
+ if(prog) RX_ENGINE(prog)->rxfree(aTHX_ (prog))
#define CALLREG_NUMBUF_FETCH(rx,paren,usesv) \
RX_ENGINE(rx)->numbered_buff_FETCH(aTHX_ (rx),(paren),(usesv))
# endif
#endif
-/* Some platforms require marking function declarations
- * for them to be exportable. Used in perlio.h, proto.h
- * is handled either by the makedef.pl or by defining the
- * PERL_CALLCONV to be something special. See also the
- * definition of XS() in XSUB.h. */
-#ifndef PERL_EXPORT_C
-# ifdef __cplusplus
-# define PERL_EXPORT_C extern "C"
-# else
-# define PERL_EXPORT_C extern
-# endif
-#endif
-#ifndef PERL_XS_EXPORT_C
-# ifdef __cplusplus
-# define PERL_XS_EXPORT_C extern "C"
-# else
-# define PERL_XS_EXPORT_C
-# endif
-#endif
-
#if defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN) && !defined(__cplusplus)
# ifndef PERL_USE_GCC_BRACE_GROUPS
# define PERL_USE_GCC_BRACE_GROUPS
# define NV_EPSILON FLT128_EPSILON
# define NV_MIN_10_EXP FLT128_MIN_10_EXP
# define NV_MAX_10_EXP FLT128_MAX_10_EXP
-# define NV_INF HUGE_VALQ
-# define NV_NAN nanq("0")
# define Perl_acos acosq
# define Perl_asin asinq
# define Perl_atan atanq
#endif
#include "handy.h"
+#include "charclass_invlists.h"
#if defined(USE_LARGE_FILES) && !defined(NO_64_BIT_RAWIO)
# if LSEEKSIZE == 8 && !defined(USE_64_BIT_RAWIO)
signal(SIGFPE, SIG_IGN); \
} STMT_END
#endif
+/* In IRIX the default for Flush to Zero bit is true,
+ * which means that results going below the minimum of normal
+ * floating points go to zero, instead of going denormal/subnormal.
+ * This is unlike almost any other system running Perl, so let's clear it.
+ * [perl #123767] IRIX64 blead (ddce084a) opbasic/arith.t failure, originally
+ * [perl #120426] small numbers shouldn't round to zero if they have extra floating digits
+ *
+ * XXX The flush-to-zero behaviour should be a Configure scan.
+ * To change the behaviour usually requires some system-specific
+ * incantation, though, like the below. */
+#ifdef __sgi
+# include <sys/fpu.h>
+# define PERL_SYS_FPU_INIT \
+ STMT_START { \
+ union fpc_csr csr; \
+ csr.fc_word = get_fpc_csr(); \
+ csr.fc_struct.flush = 0; \
+ set_fpc_csr(csr.fc_word); \
+ } STMT_END
+#endif
#ifndef PERL_SYS_FPU_INIT
# define PERL_SYS_FPU_INIT NOOP
appropriate to call return. In either case, include the lint directive.
*/
#ifdef HASATTRIBUTE_NORETURN
-# define NORETURN_FUNCTION_END NOT_REACHED; /* NOTREACHED */
+# define NORETURN_FUNCTION_END NOT_REACHED;
#else
-# define NORETURN_FUNCTION_END NOT_REACHED; /* NOTREACHED */ return 0
+# define NORETURN_FUNCTION_END NOT_REACHED; return 0
#endif
/* Some OS warn on NULL format to printf */
/* placeholder */
#endif
+/* STATIC_ASSERT_GLOBAL/STATIC_ASSERT_STMT are like assert(), but for compile
+ time invariants. That is, their argument must be a constant expression that
+ can be verified by the compiler. This expression can contain anything that's
+ known to the compiler, e.g. #define constants, enums, or sizeof (...). If
+ the expression evaluates to 0, compilation fails.
+ Because they generate no runtime code (i.e. their use is "free"), they're
+ always active, even under non-DEBUGGING builds.
+ STATIC_ASSERT_GLOBAL expands to a declaration and is suitable for use at
+ file scope (outside of any function).
+ STATIC_ASSERT_STMT expands to a statement and is suitable for use inside a
+ function.
+*/
#if (defined(static_assert) || (defined(__cplusplus) && __cplusplus >= 201103L)) && (!defined(__IBMC__) || __IBMC__ >= 1210)
/* static_assert is a macro defined in <assert.h> in C11 or a compiler
builtin in C++11.
#endif /* threading */
#endif /* AIX */
+#ifndef PERL_CALLCONV
+# ifdef __cplusplus
+# define PERL_CALLCONV extern "C"
+# else
+# define PERL_CALLCONV
+# endif
+#endif
+#ifndef PERL_CALLCONV_NO_RET
+# define PERL_CALLCONV_NO_RET PERL_CALLCONV
+#endif
+
+/* PERL_STATIC_NO_RET is supposed to be equivalent to STATIC on builds that
+ dont have a noreturn as a declaration specifier
+*/
+#ifndef PERL_STATIC_NO_RET
+# define PERL_STATIC_NO_RET STATIC
+#endif
+/* PERL_STATIC_NO_RET is supposed to be equivalent to PERL_STATIC_INLINE on
+ builds that dont have a noreturn as a declaration specifier
+*/
+#ifndef PERL_STATIC_INLINE_NO_RET
+# define PERL_STATIC_INLINE_NO_RET PERL_STATIC_INLINE
+#endif
+
#if !defined(OS2)
# include "iperlsys.h"
#endif
#define DEBUG_MASK 0x07FFEFFF /* mask of all the standard flags */
#define DEBUG_DB_RECURSE_FLAG 0x40000000
-#define DEBUG_TOP_FLAG 0x80000000 /* XXX what's this for ??? Signal
- that something was done? */
+#define DEBUG_TOP_FLAG 0x80000000 /* -D was given --> PL_debug |= FLAG */
# define DEBUG_p_TEST_ (PL_debug & DEBUG_p_FLAG)
# define DEBUG_s_TEST_ (PL_debug & DEBUG_s_FLAG)
END_EXTERN_C
#endif
-/* If you are thinking of using HUGE_VAL for infinity, or using
- * <math.h> functions to generate NV_INF (e.g. exp(1e9), log(-1.0)),
- * stop. Neither will work portably: HUGE_VAL can be just DBL_MAX,
- * and the math functions might be just generating DBL_MAX, or even
- * zero. */
-
-#if !defined(NV_INF) && defined(USE_LONG_DOUBLE)
-# if !defined(NV_INF) && defined(LDBL_INFINITY)
-# define NV_INF LDBL_INFINITY
-# endif
-# if !defined(NV_INF) && defined(INFINITYL)
-# define NV_INF INFINITYL
-# endif
-#endif
-#if !defined(NV_INF) && defined(DBL_INFINITY)
-# define NV_INF (NV)DBL_INFINITY
-#endif
-#if !defined(NV_INF) && defined(INFINITY)
-# define NV_INF (NV)INFINITY
-#endif
-#if !defined(NV_INF) && defined(INF)
-# define NV_INF (NV)INF
-#endif
-#if !defined(NV_INF)
-# if INTSIZE == 4
-/* At this point we assume the IEEE 754 floating point (and of course,
- * we also assume a floating point format that can encode an infinity).
- * We will coerce an int32 (which will encode the infinity) into
- * a 32-bit float, which will then be cast into NV.
- *
- * Note that we intentionally use a float and 32-bit int, instead of
- * shifting a small integer into a full IV, and from that into a full
- * NV, because:
- *
- * (1) an IV might not be wide enough to cover all the bits of an NV.
- * (2) the exponent part (including the infinity and nan bits) of a NV
- * might be wider than just 16 bits.
- *
- * Below the NV_NAN logic has similar __PL_nan_u fallback, the only
- * difference being the int32 constant being coerced. */
-# define __PL_inf_float_int32 0x7F800000
-static const union { unsigned int __i; float __f; } __PL_inf_u =
- { __PL_inf_float_int32 };
-# define NV_INF ((NV)(__PL_inf_u.__f))
-# endif
-#endif
-#if !defined(NV_INF)
-# define NV_INF ((NV)1.0/0.0) /* Some compilers will warn. */
-#endif
-
-#if !defined(NV_NAN) && defined(USE_LONG_DOUBLE)
-# if !defined(NV_NAN) && defined(LDBL_NAN)
-# define NV_NAN LDBL_NAN
-# endif
-# if !defined(NV_NAN) && defined(NANL)
-# define NV_NAN NANL
-# endif
-# if !defined(NV_NAN) && defined(LDBL_QNAN)
-# define NV_NAN LDBL_QNAN
-# define NV_QNAN LDBL_QNAN
-# endif
-# if !defined(NV_NAN) && defined(LDBL_SNAN)
-# define NV_SNAN LDBL_SNAN
-# endif
-#endif
-#if !defined(NV_NAN) && defined(DBL_NAN)
-# define NV_NAN (NV)DBL_NAN
-#endif
-#if !defined(NV_NAN) && defined(DBL_QNAN)
-# define NV_NAN (NV)DBL_QNAN
-# define NV_QNAN DBL_QNAN
-#endif
-#if !defined(NV_NAN) && defined(DBL_SNAN)
-# define NV_SNAN DBL_SNAN
-#endif
-#if !defined(NV_NAN) && defined(NAN)
-# define NV_NAN (NV)NAN
-#endif
-#if !defined(NV_NAN) && defined(QNAN)
-# define NV_NAN (NV)QNAN
-# define NV_QNAN QNAN
-#endif
-#if !defined(NV_NAN) && defined(SNAN)
-# define NV_SNAN SNAN
-#endif
-#if !defined(NV_NAN) && defined(I_SUNMATH)
-# define NV_NAN (NV)quiet_nan()
-# define NV_QNAN (NV)quiet_nan()
-# define NV_SNAN (NV)signaling_nan()
-#endif
-#if !defined(NV_NAN)
-# if INTSIZE == 4
-/* See the discussion near __PL_inf_u. */
-# define __PL_nan_float_int32 0x7FC00000
-static const union { unsigned int __i; float __f; } __PL_nan_u =
- { __PL_nan_float_int32 };
-# define NV_NAN ((NV)(__PL_nan_u.__f))
-# endif
-#endif
-#if !defined(NV_NAN)
-# define NV_NAN ((NV)0.0/0.0) /* Some compilers will warn. */
-#endif
-/* Do NOT try doing NV_NAN based on NV_INF and trying (NV_INF-NV_INF).
- * Though IEEE-754-logically correct, some compilers (like Visual C 2003)
- * falsely misoptimize that to zero (x-x is zero, right?) */
-
#ifndef __cplusplus
# if !defined(WIN32) && !defined(VMS)
#ifndef crypt
#include "thread.h"
#include "pp.h"
-#ifndef PERL_CALLCONV
-# ifdef __cplusplus
-# define PERL_CALLCONV extern "C"
-# else
-# define PERL_CALLCONV
-# endif
-#endif
-#ifndef PERL_CALLCONV_NO_RET
-# define PERL_CALLCONV_NO_RET PERL_CALLCONV
-#endif
-
-/* PERL_STATIC_NO_RET is supposed to be equivalent to STATIC on builds that
- dont have a noreturn as a declaration specifier
-*/
-#ifndef PERL_STATIC_NO_RET
-# define PERL_STATIC_NO_RET STATIC
-#endif
-/* PERL_STATIC_NO_RET is supposed to be equivalent to PERL_STATIC_INLINE on
- builds that dont have a noreturn as a declaration specifier
-*/
-#ifndef PERL_STATIC_INLINE_NO_RET
-# define PERL_STATIC_INLINE_NO_RET PERL_STATIC_INLINE
-#endif
-
-
#undef PERL_CKDEF
#undef PERL_PPDEF
#define PERL_CKDEF(s) PERL_CALLCONV OP *s (pTHX_ OP *o);
# include "malloc_ctl.h"
#endif
+/*
+ * This provides a layer of functions and macros to ensure extensions will
+ * get to use the same RTL functions as the core.
+ */
+#if defined(WIN32)
+# include "win32iop.h"
+#endif
+
#include "proto.h"
/* this has structure inits, so it cannot be included before here */
#endif
+/* In C99 we could use designated (named field) union initializers.
+ * In C89 we need to initialize the member declared first.
+ *
+ * With the U8_NV version you will want to have inner braces,
+ * while with the NV_U8 use just the NV.*/
+#define INFNAN_U8_NV_DECL EXTCONST union { U8 u8[NVSIZE]; NV nv; }
+#define INFNAN_NV_U8_DECL EXTCONST union { NV nv; U8 u8[NVSIZE]; }
+
+#ifdef DOINIT
+
+/* PL_inf and PL_nan initialization.
+ *
+ * For inf and nan initialization the ultimate fallback is dividing
+ * one or zero by zero: however, some compilers will warn or even fail
+ * on divide-by-zero, but hopefully something earlier will work.
+ *
+ * If you are thinking of using HUGE_VAL for infinity, or using
+ * <math.h> functions to generate NV_INF (e.g. exp(1e9), log(-1.0)),
+ * stop. Neither will work portably: HUGE_VAL can be just DBL_MAX,
+ * and the math functions might be just generating DBL_MAX, or even zero.
+ *
+ * Also, do NOT try doing NV_NAN based on NV_INF and trying (NV_INF-NV_INF).
+ * Though logically correct, some compilers (like Visual C 2003)
+ * falsely misoptimize that to zero (x-x is always zero, right?)
+ */
+
+# ifdef USE_QUADMATH
+/* Cannot use HUGE_VALQ for PL_inf because not a compile-time
+ * constant. Also, the quadmath literals are anon structs which
+ * -Wc++-compat doesn't like. */
+GCC_DIAG_IGNORE(-Wc++-compat);
+INFNAN_NV_U8_DECL PL_inf = { 1.0Q/0.0Q };
+GCC_DIAG_RESTORE;
+# elif NVSIZE == LONG_DOUBLESIZE && defined(LONGDBLINFBYTES)
+INFNAN_U8_NV_DECL PL_inf = { { LONGDBLINFBYTES } };
+# elif NVSIZE == DOUBLESIZE && defined(DOUBLEINFBYTES)
+INFNAN_U8_NV_DECL PL_inf = { { DOUBLEINFBYTES } };
+# else
+# if NVSIZE == LONG_DOUBLESIZE && defined(USE_LONG_DOUBLE)
+# if defined(LDBL_INFINITY)
+INFNAN_NV_U8_DECL PL_inf = { LDBL_INFINITY };
+# elif defined(LDBL_INF)
+INFNAN_NV_U8_DECL PL_inf = { LDBL_INF };
+# elif defined(INFINITY)
+INFNAN_NV_U8_DECL PL_inf = { (NV)INFINITY };
+# elif defined(INF)
+INFNAN_NV_U8_DECL PL_inf = { (NV)INF };
+# else
+INFNAN_NV_U8_DECL PL_inf = { 1.0L/0.0L }; /* keep last */
+# endif
+# else
+# if defined(DBL_INFINITY)
+INFNAN_NV_U8_DECL PL_inf = { DBL_INFINITY };
+# elif defined(DBL_INF)
+INFNAN_NV_U8_DECL PL_inf = { DBL_INF };
+# elif defined(INFINITY) /* C99 */
+INFNAN_NV_U8_DECL PL_inf = { (NV)INFINITY };
+# elif defined(INF)
+INFNAN_NV_U8_DECL PL_inf = { (NV)INF };
+# else
+INFNAN_NV_U8_DECL PL_inf = { 1.0/0.0 }; /* keep last */
+# endif
+# endif
+# endif
+
+# ifdef USE_QUADMATH
+/* Cannot use nanq("0") for PL_nan because not a compile-time
+ * constant. Also, the quadmath literals are anon structs which
+ * -Wc++-compat doesn't like. */
+GCC_DIAG_IGNORE(-Wc++-compat);
+INFNAN_NV_U8_DECL PL_nan = { 0.0Q/0.0Q };
+GCC_DIAG_RESTORE;
+# elif NVSIZE == LONG_DOUBLESIZE && defined(LONGDBLNANBYTES)
+INFNAN_U8_NV_DECL PL_nan = { { LONGDBLNANBYTES } };
+# elif NVSIZE == DOUBLESIZE && defined(DOUBLENANBYTES)
+INFNAN_U8_NV_DECL PL_nan = { { DOUBLENANBYTES } };
+# else
+# if NVSIZE == LONG_DOUBLESIZE && defined(USE_LONG_DOUBLE)
+# if defined(LDBL_NAN)
+INFNAN_NV_U8_DECL PL_nan = { LDBL_NAN };
+# elif defined(LDBL_QNAN)
+INFNAN_NV_U8_DECL PL_nan = { LDBL_QNAN };
+# elif defined(NAN)
+INFNAN_NV_U8_DECL PL_nan = { (NV)NAN };
+# else
+INFNAN_NV_U8_DECL PL_nan = { 0.0L/0.0L }; /* keep last */
+# endif
+# else
+# if defined(DBL_NAN)
+INFNAN_NV_U8_DECL PL_nan = { DBL_NAN };
+# elif defined(DBL_QNAN)
+INFNAN_NV_U8_DECL PL_nan = { DBL_QNAN };
+# elif defined(NAN) /* C99 */
+INFNAN_NV_U8_DECL PL_nan = { (NV)NAN };
+# else
+INFNAN_NV_U8_DECL PL_nan = { 0.0/0.0 }; /* keep last */
+# endif
+# endif
+# endif
+
+#else
+
+INFNAN_NV_U8_DECL PL_inf;
+INFNAN_NV_U8_DECL PL_nan;
+
+#endif
+
+/* If you have not defined NV_INF/NV_NAN (like for example win32/win32.h),
+ * we will define NV_INF/NV_NAN as the nv part of the global const
+ * PL_inf/PL_nan. Note, however, that the preexisting NV_INF/NV_NAN
+ * might not be a compile-time constant, in which case it cannot be
+ * used to initialize PL_inf/PL_nan above. */
+#ifndef NV_INF
+# define NV_INF PL_inf.nv
+#endif
+#ifndef NV_NAN
+# define NV_NAN PL_nan.nv
+#endif
/* if these never got defined, they need defaults */
#ifndef PERL_SET_CONTEXT
* this will so rarely be true, there is no point to optimize for
* time; instead it makes sense to minimize space used and do all the
* work in the rarely called function */
-# define _CHECK_AND_WARN_PROBLEMATIC_LOCALE \
- STMT_START { \
- if (UNLIKELY(PL_warn_locale)) { \
- _warn_problematic_locale(); \
- } \
- } STMT_END
+# ifdef USE_LOCALE_CTYPE
+# define _CHECK_AND_WARN_PROBLEMATIC_LOCALE \
+ STMT_START { \
+ if (UNLIKELY(PL_warn_locale)) { \
+ _warn_problematic_locale(); \
+ } \
+ } STMT_END
+# else
+# define _CHECK_AND_WARN_PROBLEMATIC_LOCALE
+# endif
/* These two internal macros are called when a warning should be raised,
* argument; the 2nd, is a pointer to the first byte of the UTF-8 encoded
* string, and an end position which it won't try to read past */
# define _CHECK_AND_OUTPUT_WIDE_LOCALE_CP_MSG(cp) \
- Perl_ck_warner(aTHX_ packWARN(WARN_LOCALE), \
- "Wide character (U+%"UVXf") in %s", (UV) cp, OP_DESC(PL_op));
+ STMT_START { \
+ if (! PL_in_utf8_CTYPE_locale && ckWARN(WARN_LOCALE)) { \
+ Perl_warner(aTHX_ packWARN(WARN_LOCALE), \
+ "Wide character (U+%"UVXf") in %s", \
+ (UV) cp, OP_DESC(PL_op)); \
+ } \
+ } STMT_END
# define _CHECK_AND_OUTPUT_WIDE_LOCALE_UTF8_MSG(s, send) \
STMT_START { /* Check if to warn before doing the conversion work */\
- if (ckWARN(WARN_LOCALE)) { \
+ if (! PL_in_utf8_CTYPE_locale && ckWARN(WARN_LOCALE)) { \
UV cp = utf8_to_uvchr_buf((U8 *) s, (U8 *) send, NULL); \
Perl_warner(aTHX_ packWARN(WARN_LOCALE), \
"Wide character (U+%"UVXf") in %s", \
#ifdef USE_LOCALE_NUMERIC
-/* These macros are for toggling between the underlying locale (LOCAL) and the
- * C locale. */
+/* These macros are for toggling between the underlying locale (UNDERLYING or
+ * 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
-/* The first set makes sure that the locale is set to C unless within a 'use
- * locale's scope; otherwise to the default locale. A function pointer is
- * used, which can be declared separately by
- * DECLARATION_FOR_STORE_LC_NUMERIC_SET_TO_NEEDED, followed by the actual
- * setting (using STORE_LC_NUMERIC_SET_TO_NEEDED()), or the two can be combined
- * into one call DECLARE_STORE_LC_NUMERIC_SET_TO_NEEDED().
- * RESTORE_LC_NUMERIC() in all cases restores the locale to what it was before
- * these were called */
+*/
#define _NOT_IN_NUMERIC_STANDARD (! PL_numeric_standard)
/* We can lock the category to stay in the C locale, making requests to the
- * contrary noops, in the dynamic scope by setting PL_numeric_standard to 2 */
-#define _NOT_IN_NUMERIC_LOCAL (! PL_numeric_local && PL_numeric_standard < 2)
-
-#define DECLARATION_FOR_STORE_LC_NUMERIC_SET_TO_NEEDED \
- void (*_restore_LC_NUMERIC_function)(pTHX) = NULL;
-
-#define STORE_LC_NUMERIC_SET_TO_NEEDED() \
- if (IN_LC(LC_NUMERIC)) { \
- if (_NOT_IN_NUMERIC_LOCAL) { \
- set_numeric_local(); \
- _restore_LC_NUMERIC_function = &Perl_set_numeric_standard; \
- } \
- } \
- else { \
- if (_NOT_IN_NUMERIC_STANDARD) { \
- SET_NUMERIC_STANDARD(); \
- _restore_LC_NUMERIC_function = &Perl_set_numeric_local; \
- } \
+ * contrary be noops, in the dynamic scope by setting PL_numeric_standard to 2.
+ * */
+#define _NOT_IN_NUMERIC_UNDERLYING \
+ (! PL_numeric_local && PL_numeric_standard < 2)
+
+#define DECLARATION_FOR_LC_NUMERIC_MANIPULATION \
+ void (*_restore_LC_NUMERIC_function)(pTHX) = NULL
+
+#define STORE_LC_NUMERIC_SET_TO_NEEDED() \
+ if (IN_LC(LC_NUMERIC)) { \
+ if (_NOT_IN_NUMERIC_UNDERLYING) { \
+ set_numeric_local(); \
+ _restore_LC_NUMERIC_function = &Perl_set_numeric_standard; \
+ } \
+ } \
+ else { \
+ if (_NOT_IN_NUMERIC_STANDARD) { \
+ SET_NUMERIC_STANDARD(); \
+ _restore_LC_NUMERIC_function = &Perl_set_numeric_local; \
+ } \
}
-#define DECLARE_STORE_LC_NUMERIC_SET_TO_NEEDED() \
- DECLARATION_FOR_STORE_LC_NUMERIC_SET_TO_NEEDED; \
- STORE_LC_NUMERIC_SET_TO_NEEDED();
-
-#define RESTORE_LC_NUMERIC() \
- if (_restore_LC_NUMERIC_function) { \
- _restore_LC_NUMERIC_function(aTHX); \
+#define RESTORE_LC_NUMERIC() \
+ if (_restore_LC_NUMERIC_function) { \
+ _restore_LC_NUMERIC_function(aTHX); \
}
/* The next two macros set unconditionally. These should be rarely used, and
STMT_START { if (_NOT_IN_NUMERIC_STANDARD) set_numeric_standard(); \
} STMT_END
-#define SET_NUMERIC_LOCAL() \
- STMT_START { if (_NOT_IN_NUMERIC_LOCAL) \
+#define SET_NUMERIC_UNDERLYING() \
+ STMT_START { if (_NOT_IN_NUMERIC_UNDERLYING) \
set_numeric_local(); } STMT_END
/* The rest of these LC_NUMERIC macros toggle to one or the other state, with
* the RESTORE_foo ones called to switch back, but only if need be */
-#define STORE_NUMERIC_LOCAL_SET_STANDARD() \
- bool _was_local = _NOT_IN_NUMERIC_STANDARD; \
+#define STORE_LC_NUMERIC_UNDERLYING_SET_STANDARD() \
+ bool _was_local = _NOT_IN_NUMERIC_STANDARD; \
if (_was_local) set_numeric_standard();
/* Doesn't change to underlying locale unless within the scope of some form of
* 'use locale'. This is the usual desired behavior. */
-#define STORE_NUMERIC_STANDARD_SET_LOCAL() \
- bool _was_standard = _NOT_IN_NUMERIC_LOCAL \
- && IN_LC(LC_NUMERIC); \
+#define STORE_LC_NUMERIC_STANDARD_SET_UNDERLYING() \
+ bool _was_standard = _NOT_IN_NUMERIC_UNDERLYING \
+ && IN_LC(LC_NUMERIC); \
if (_was_standard) set_numeric_local();
/* Rarely, we want to change to the underlying locale even outside of 'use
* locale'. This is principally in the POSIX:: functions */
-#define STORE_NUMERIC_STANDARD_FORCE_LOCAL() \
- bool _was_standard = _NOT_IN_NUMERIC_LOCAL; \
- if (_was_standard) set_numeric_local();
+#define STORE_LC_NUMERIC_FORCE_TO_UNDERLYING() \
+ if (_NOT_IN_NUMERIC_UNDERLYING) { \
+ set_numeric_local(); \
+ _restore_LC_NUMERIC_function = &Perl_set_numeric_standard; \
+ }
/* Lock to the C locale until unlock is called */
-#define LOCK_NUMERIC_STANDARD() \
- (__ASSERT_(PL_numeric_standard) \
+#define LOCK_LC_NUMERIC_STANDARD() \
+ (__ASSERT_(PL_numeric_standard) \
PL_numeric_standard = 2)
-#define UNLOCK_NUMERIC_STANDARD() \
- (__ASSERT_(PL_numeric_standard == 2) \
+#define UNLOCK_LC_NUMERIC_STANDARD() \
+ (__ASSERT_(PL_numeric_standard == 2) \
PL_numeric_standard = 1)
-#define RESTORE_NUMERIC_LOCAL() \
+#define RESTORE_LC_NUMERIC_UNDERLYING() \
if (_was_local) set_numeric_local();
-#define RESTORE_NUMERIC_STANDARD() \
- if (_was_standard) SET_NUMERIC_STANDARD();
-
-#define Atof my_atof
+#define RESTORE_LC_NUMERIC_STANDARD() \
+ if (_restore_LC_NUMERIC_function) { \
+ _restore_LC_NUMERIC_function(aTHX); \
+ }
#else /* !USE_LOCALE_NUMERIC */
-#define SET_NUMERIC_STANDARD() /**/
-#define SET_NUMERIC_LOCAL() /**/
+#define SET_NUMERIC_STANDARD()
+#define SET_NUMERIC_UNDERLYING()
#define IS_NUMERIC_RADIX(a, b) (0)
-#define STORE_NUMERIC_LOCAL_SET_STANDARD() /**/
-#define STORE_NUMERIC_STANDARD_SET_LOCAL() /**/
-#define STORE_NUMERIC_STANDARD_FORCE_LOCAL()
-#define RESTORE_NUMERIC_LOCAL() /**/
-#define RESTORE_NUMERIC_STANDARD() /**/
-#define DECLARATION_FOR_STORE_LC_NUMERIC_SET_TO_NEEDED
+#define STORE_LC_NUMERIC_UNDERLYING_SET_STANDARD()
+#define STORE_LC_NUMERIC_STANDARD_SET_UNDERLYING()
+#define STORE_LC_NUMERIC_FORCE_TO_UNDERLYING()
+#define RESTORE_LC_NUMERIC_UNDERLYING()
+#define RESTORE_LC_NUMERIC_STANDARD()
+#define DECLARATION_FOR_LC_NUMERIC_MANIPULATION
#define STORE_LC_NUMERIC_SET_TO_NEEDED()
-#define DECLARE_STORE_LC_NUMERIC_SET_TO_NEEDED()
#define RESTORE_LC_NUMERIC()
-#define LOCK_NUMERIC_STANDARD()
-#define UNLOCK_NUMERIC_STANDARD()
+#define LOCK_LC_NUMERIC_STANDARD()
+#define UNLOCK_LC_NUMERIC_STANDARD()
+
+#endif /* !USE_LOCALE_NUMERIC */
#define Atof my_atof
-#endif /* !USE_LOCALE_NUMERIC */
+/* Back-compat names */
+#define DECLARATION_FOR_STORE_LC_NUMERIC_SET_TO_NEEDED \
+ DECLARATION_FOR_LC_NUMERIC_MANIPULATION
+#define DECLARE_STORE_LC_NUMERIC_SET_TO_NEEDED() \
+ DECLARATION_FOR_STORE_LC_NUMERIC_SET_TO_NEEDED; \
+ STORE_LC_NUMERIC_SET_TO_NEEDED();
+#define LOCK_NUMERIC_STANDARD() LOCK_LC_NUMERIC_STANDARD()
+#define RESTORE_NUMERIC_LOCAL() RESTORE_LC_NUMERIC_UNDERLYING()
+#define RESTORE_NUMERIC_STANDARD() RESTORE_LC_NUMERIC_STANDARD()
+#define SET_NUMERIC_LOCAL() SET_NUMERIC_UNDERLYING()
+#define STORE_NUMERIC_LOCAL_SET_STANDARD() \
+ STORE_LC_NUMERIC_UNDERLYING_SET_STANDARD()
+#define STORE_NUMERIC_STANDARD_SET_LOCAL() \
+ STORE_LC_NUMERIC_STANDARD_SET_UNDERLYING()
+#define STORE_NUMERIC_STANDARD_FORCE_LOCAL() \
+ STORE_LC_NUMERIC_FORCE_TO_UNDERLYING()
+#define UNLOCK_NUMERIC_STANDARD() UNLOCK_LC_NUMERIC_STANDARD()
+
+
#ifdef USE_QUADMATH
# define Perl_strtod(s, e) strtoflt128(s, e)
#endif /* LONG_DOUBLEKIND */
-#if NVSIZE == DOUBLESIZE
+#ifdef USE_QUADMATH /* assume quadmath endianness == native double endianness */
+# if defined(DOUBLE_LITTLE_ENDIAN)
+# define NV_LITTLE_ENDIAN
+# elif defined(DOUBLE_BIG_ENDIAN)
+# define NV_BIG_ENDIAN
+# elif defined(DOUBLE_MIX_ENDIAN) /* stretch */
+# define NV_MIX_ENDIAN
+# endif
+#elif NVSIZE == DOUBLESIZE
# ifdef DOUBLE_LITTLE_ENDIAN
# define NV_LITTLE_ENDIAN
# endif
# endif
#endif
-/* The implicit bit platforms include the implicit bit
- * in the NV_MANT_DIG. The bit isn't really there, however,
- * so the real count of mantissa bits is one less. */
-#ifdef NV_IMPLICIT_BIT
-# define NV_MANT_REAL_DIG (NV_MANT_DIG - 1)
-#else
-# define NV_MANT_REAL_DIG (NV_MANT_DIG)
-#endif
-
/*
(KEEP THIS LAST IN perl.h!)
#endif /* Include guard */
/*
- * Local variables:
- * c-indentation-style: bsd
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- *
* ex: set ts=8 sts=4 sw=4 et:
*/