X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/f33b12f351ef63991bb640a426dc78b081a602d1..8fc14efc8e8ce14fba31220281badcf4cfa4ce42:/ext/POSIX/POSIX.xs diff --git a/ext/POSIX/POSIX.xs b/ext/POSIX/POSIX.xs index 12da49f..2d3e69f 100644 --- a/ext/POSIX/POSIX.xs +++ b/ext/POSIX/POSIX.xs @@ -1,4 +1,5 @@ #define PERL_EXT_POSIX +#define PERL_EXT #ifdef NETWARE #define _POSIX_ @@ -17,6 +18,9 @@ #define PERLIO_NOT_STDIO 1 #include "perl.h" #include "XSUB.h" + +static int not_here(const char *s); + #if defined(PERL_IMPLICIT_SYS) # undef signal # undef open @@ -31,15 +35,13 @@ #ifdef WIN32 #include #endif -#ifdef I_FLOAT #include -#endif #ifdef I_FENV +#if !(defined(__vax__) && defined(__NetBSD__)) #include #endif -#ifdef I_LIMITS -#include #endif +#include #include #include #ifdef I_PWD @@ -48,15 +50,20 @@ #include #include #include - -#ifdef I_STDDEF #include -#endif #ifdef I_UNISTD #include #endif +#ifdef I_SYS_TIME +# include +#endif + +#ifdef I_SYS_RESOURCE +# include +#endif + #if defined(USE_QUADMATH) && defined(I_QUADMATH) # undef M_E @@ -704,7 +711,11 @@ static NV my_expm1(NV x) #ifndef c99_fdim static NV my_fdim(NV x, NV y) { +#ifdef NV_NAN return (Perl_isnan(x) || Perl_isnan(y)) ? NV_NAN : (x > y ? x - y : 0); +#else + return (x > y ? x - y : 0); +#endif } # define c99_fdim my_fdim #endif @@ -720,11 +731,13 @@ static NV my_fma(NV x, NV y, NV z) #ifndef c99_fmax static NV my_fmax(NV x, NV y) { +#ifdef NV_NAN if (Perl_isnan(x)) { return Perl_isnan(y) ? NV_NAN : y; } else if (Perl_isnan(y)) { return x; } +#endif return x > y ? x : y; } # define c99_fmax my_fmax @@ -733,11 +746,13 @@ static NV my_fmax(NV x, NV y) #ifndef c99_fmin static NV my_fmin(NV x, NV y) { +#ifdef NV_NAN if (Perl_isnan(x)) { return Perl_isnan(y) ? NV_NAN : y; } else if (Perl_isnan(y)) { return x; } +#endif return x < y ? x : y; } # define c99_fmin my_fmin @@ -768,8 +783,10 @@ static NV my_hypot(NV x, NV y) x = PERL_ABS(x); /* Take absolute values. */ if (y == 0) return x; +#ifdef NV_INF if (Perl_isnan(y)) return NV_INF; +#endif y = PERL_ABS(y); if (x < y) { /* Swap so that y is less. */ t = x; @@ -816,10 +833,18 @@ static NV my_lgamma(NV x); static NV my_tgamma(NV x) { const NV gamma = 0.577215664901532860606512090; /* Euler's gamma constant. */ +#ifdef NV_NAN if (Perl_isnan(x) || x < 0.0) return NV_NAN; +#endif +#ifdef NV_INF if (x == 0.0 || x == NV_INF) +#ifdef DOUBLE_IS_IEEE_FORMAT return x == -0.0 ? -NV_INF : NV_INF; +#else + return NV_INF; +#endif +#endif /* The function domain is split into three intervals: * (0, 0.001), [0.001, 12), and (12, infinity) */ @@ -891,6 +916,7 @@ static NV my_tgamma(NV x) return result; } +#ifdef NV_INF /* Third interval: [12, +Inf) */ #if LDBL_MANT_DIG == 113 /* IEEE quad prec */ if (x > 1755.548) { @@ -901,6 +927,7 @@ static NV my_tgamma(NV x) return NV_INF; } #endif +#endif return Perl_exp(c99_lgamma(x)); } @@ -909,10 +936,14 @@ static NV my_tgamma(NV x) #ifdef USE_MY_LGAMMA static NV my_lgamma(NV x) { +#ifdef NV_NAN if (Perl_isnan(x)) return NV_NAN; +#endif +#ifdef NV_INF if (x <= 0 || x == NV_INF) return NV_INF; +#endif if (x == 1.0 || x == 2.0) return 0; if (x < 12.0) @@ -953,10 +984,14 @@ static NV my_log1p(NV x) { /* http://www.johndcook.com/cpp_log_one_plus_x.html -- public domain. * Taylor series, the first four terms (the last term quartic). */ +#ifdef NV_NAN if (x < -1.0) return NV_NAN; +#endif +#ifdef NV_INF if (x == -1.0) return -NV_INF; +#endif if (PERL_ABS(x) > 1e-4) return Perl_log(1.0 + x); else @@ -1032,7 +1067,7 @@ static NV my_rint(NV x) case FE_TOWARDZERO: return MY_ROUND_TRUNC(x); case FE_DOWNWARD: return MY_ROUND_DOWN(x); case FE_UPWARD: return MY_ROUND_UP(x); - default: return NV_NAN; + default: break; } #elif defined(HAS_FPGETROUND) switch (fpgetround()) { @@ -1040,11 +1075,10 @@ static NV my_rint(NV x) case FP_RZ: return MY_ROUND_TRUNC(x); case FP_RM: return MY_ROUND_DOWN(x); case FE_RP: return MY_ROUND_UP(x); - default: return NV_NAN; + default: break; } -#else - return NV_NAN; #endif + not_here("rint"); } #endif @@ -1118,6 +1152,8 @@ static NV my_trunc(NV x) # define c99_trunc my_trunc #endif +#ifdef NV_NAN + #undef NV_PAYLOAD_DEBUG /* NOTE: the NaN payload API implementation is hand-rolled, since the @@ -1153,10 +1189,12 @@ static NV my_trunc(NV x) # define NV_PAYLOAD_TYPE NV #endif -#ifdef LONGDOUBLE_DOUBLEDOUBLE -# define NV_PAYLOAD_SIZEOF_ASSERT(a) assert(sizeof(a) == NVSIZE / 2) +#if defined(USE_LONG_DOUBLE) && defined(LONGDOUBLE_DOUBLEDOUBLE) +# define NV_PAYLOAD_SIZEOF_ASSERT(a) \ + STATIC_ASSERT_STMT(sizeof(a) == NVSIZE / 2) #else -# define NV_PAYLOAD_SIZEOF_ASSERT(a) assert(sizeof(a) == NVSIZE) +# define NV_PAYLOAD_SIZEOF_ASSERT(a) \ + STATIC_ASSERT_STMT(sizeof(a) == NVSIZE) #endif static void S_setpayload(NV* nvp, NV_PAYLOAD_TYPE payload, bool signaling) @@ -1178,7 +1216,7 @@ static void S_setpayload(NV* nvp, NV_PAYLOAD_TYPE payload, bool signaling) { NV t1 = c99_trunc(payload); /* towards zero (drop fractional) */ #ifdef NV_PAYLOAD_DEBUG - Perl_warn(aTHX_ "t1 = %"NVgf" (payload %"NVgf")\n", t1, payload); + Perl_warn(aTHX_ "t1 = %" NVgf " (payload %" NVgf ")\n", t1, payload); #endif if (t1 <= UV_MAX) { a[0] = (UV)t1; /* Fast path, also avoids rounding errors (right?) */ @@ -1208,7 +1246,7 @@ static void S_setpayload(NV* nvp, NV_PAYLOAD_TYPE payload, bool signaling) #endif #ifdef NV_PAYLOAD_DEBUG for (i = 0; i < (int)C_ARRAY_LENGTH(a); i++) { - Perl_warn(aTHX_ "a[%d] = 0x%"UVxf"\n", i, a[i]); + Perl_warn(aTHX_ "a[%d] = 0x%" UVxf "\n", i, a[i]); } #endif for (i = 0; i < (int)sizeof(p); i++) { @@ -1219,7 +1257,9 @@ static void S_setpayload(NV* nvp, NV_PAYLOAD_TYPE payload, bool signaling) ((U8 *)(nvp))[i] &= ~m[i]; /* For NaNs with non-zero payload bits. */ ((U8 *)(nvp))[i] |= b; #ifdef NV_PAYLOAD_DEBUG - Perl_warn(aTHX_ "set p[%2d] = %02x (i = %d, m = %02x, s = %2d, b = %02x, u = %08"UVxf")\n", i, ((U8 *)(nvp))[i], i, m[i], s, b, u); + Perl_warn(aTHX_ + "set p[%2d] = %02x (i = %d, m = %02x, s = %2d, b = %02x, u = %08" + UVxf ")\n", i, ((U8 *)(nvp))[i], i, m[i], s, b, u); #endif a[p[i] / UVSIZE] &= ~u; } @@ -1236,7 +1276,7 @@ static void S_setpayload(NV* nvp, NV_PAYLOAD_TYPE payload, bool signaling) #endif for (i = 0; i < (int)C_ARRAY_LENGTH(a); i++) { if (a[i]) { - Perl_warn(aTHX_ "payload lost bits (%"UVxf")", a[i]); + Perl_warn(aTHX_ "payload lost bits (%" UVxf ")", a[i]); break; } } @@ -1267,7 +1307,7 @@ static NV_PAYLOAD_TYPE S_getpayload(NV nv) } for (i = (int)C_ARRAY_LENGTH(a) - 1; i >= 0; i--) { #ifdef NV_PAYLOAD_DEBUG - Perl_warn(aTHX_ "a[%d] = %"UVxf"\n", i, a[i]); + Perl_warn(aTHX_ "a[%d] = %" UVxf "\n", i, a[i]); #endif payload *= UV_MAX; payload += a[i]; @@ -1281,6 +1321,8 @@ static NV_PAYLOAD_TYPE S_getpayload(NV nv) return payload; } +#endif /* #ifdef NV_NAN */ + /* XXX This comment is just to make I_TERMIO and I_SGTTY visible to metaconfig for future extension writers. We don't use them in POSIX. (This is really sneaky :-) --AD @@ -1288,9 +1330,7 @@ static NV_PAYLOAD_TYPE S_getpayload(NV nv) #if defined(I_TERMIOS) #include #endif -#ifdef I_STDLIB #include -#endif #ifndef __ultrix__ #include #endif @@ -1558,8 +1598,8 @@ static const struct lconv_offset lconv_strings[] = { /* The Linux man pages say these are the field names for the structure * components that are LC_NUMERIC; the rest being LC_MONETARY */ -# define isLC_NUMERIC_STRING(name) (strEQ(name, "decimal_point") \ - || strEQ(name, "thousands_sep") \ +# define isLC_NUMERIC_STRING(name) ( strEQ(name, "decimal_point") \ + || strEQ(name, "thousands_sep") \ \ /* There should be no harm done \ * checking for this, even if \ @@ -1663,6 +1703,11 @@ allocate_struct(pTHX_ SV *rv, const STRLEN size, const char *packname) { SV *const t = newSVrv(rv, packname); void *const p = sv_grow(t, size + 1); + /* Ensure at least one use of not_here() to avoid "defined but not + * used" warning. This is not at all related to allocate_struct(); I + * just needed somewhere to dump it - DAPM */ + if (0) { not_here(""); } + SvCUR_set(t, size); SvPOK_on(t); return p; @@ -1747,7 +1792,7 @@ fix_win32_tzenv(void) perl_tz_env = ""; if (crt_tz_env == NULL) crt_tz_env = ""; - if (strcmp(perl_tz_env, crt_tz_env) != 0) { + if (strNE(perl_tz_env, crt_tz_env)) { newenv = (char*)malloc((strlen(perl_tz_env) + 4) * sizeof(char)); if (newenv != NULL) { sprintf(newenv, "TZ=%s", perl_tz_env); @@ -1778,102 +1823,6 @@ my_tzset(pTHX) tzset(); } -typedef int (*isfunc_t)(int); -typedef void (*any_dptr_t)(void *); - -/* This needs to be ALIASed in a custom way, hence can't easily be defined as - a regular XSUB. */ -static XSPROTO(is_common); /* prototype to pass -Wmissing-prototypes */ -static XSPROTO(is_common) -{ - dXSARGS; - - if (items != 1) - croak_xs_usage(cv, "charstring"); - - { - dXSTARG; - STRLEN len; - /*int RETVAL = 0; YYY means uncomment this to return false on an - * empty string input */ - int RETVAL; - unsigned char *s = (unsigned char *) SvPV(ST(0), len); - unsigned char *e = s + len; - isfunc_t isfunc = (isfunc_t) XSANY.any_dptr; - - if (ckWARN_d(WARN_DEPRECATED)) { - - /* Warn exactly once for each lexical place this function is - * called. See thread at - * http://markmail.org/thread/jhqcag5njmx7jpyu */ - - HV *warned = get_hv("POSIX::_warned", GV_ADD | GV_ADDMULTI); - if (! hv_exists(warned, (const char *)&PL_op, sizeof(PL_op))) { - Perl_warner(aTHX_ packWARN(WARN_DEPRECATED), - "Calling POSIX::%"HEKf"() is deprecated", - HEKfARG(GvNAME_HEK(CvGV(cv)))); - (void)hv_store(warned, (const char *)&PL_op, sizeof(PL_op), &PL_sv_yes, 0); - } - } - - /*if (e > s) { YYY */ - for (RETVAL = 1; RETVAL && s < e; s++) - if (!isfunc(*s)) - RETVAL = 0; - /*} YYY */ - XSprePUSH; - PUSHi((IV)RETVAL); - } - XSRETURN(1); -} - -MODULE = POSIX PACKAGE = POSIX - -BOOT: -{ - CV *cv; - - - /* silence compiler warning about not_here() defined but not used */ - if (0) not_here(""); - - /* Ensure we get the function, not a macro implementation. Like the C89 - standard says we can... */ -#undef isalnum - cv = newXS_deffile("POSIX::isalnum", is_common); - XSANY.any_dptr = (any_dptr_t) &isalnum; -#undef isalpha - cv = newXS_deffile("POSIX::isalpha", is_common); - XSANY.any_dptr = (any_dptr_t) &isalpha; -#undef iscntrl - cv = newXS_deffile("POSIX::iscntrl", is_common); - XSANY.any_dptr = (any_dptr_t) &iscntrl; -#undef isdigit - cv = newXS_deffile("POSIX::isdigit", is_common); - XSANY.any_dptr = (any_dptr_t) &isdigit; -#undef isgraph - cv = newXS_deffile("POSIX::isgraph", is_common); - XSANY.any_dptr = (any_dptr_t) &isgraph; -#undef islower - cv = newXS_deffile("POSIX::islower", is_common); - XSANY.any_dptr = (any_dptr_t) &islower; -#undef isprint - cv = newXS_deffile("POSIX::isprint", is_common); - XSANY.any_dptr = (any_dptr_t) &isprint; -#undef ispunct - cv = newXS_deffile("POSIX::ispunct", is_common); - XSANY.any_dptr = (any_dptr_t) &ispunct; -#undef isspace - cv = newXS_deffile("POSIX::isspace", is_common); - XSANY.any_dptr = (any_dptr_t) &isspace; -#undef isupper - cv = newXS_deffile("POSIX::isupper", is_common); - XSANY.any_dptr = (any_dptr_t) &isupper; -#undef isxdigit - cv = newXS_deffile("POSIX::isxdigit", is_common); - XSANY.any_dptr = (any_dptr_t) &isxdigit; -} - MODULE = SigSet PACKAGE = POSIX::SigSet PREFIX = sig void @@ -2175,15 +2124,49 @@ localeconv() localeconv(); /* A stub to call not_here(). */ #else struct lconv *lcbuf; +# if defined(USE_ITHREADS) \ + && defined(HAS_POSIX_2008_LOCALE) \ + && defined(HAS_LOCALECONV_L) /* Prefer this thread-safe version */ + bool do_free = FALSE; + locale_t cur; +# endif + DECLARATION_FOR_LC_NUMERIC_MANIPULATION; /* localeconv() deals with both LC_NUMERIC and LC_MONETARY, but * LC_MONETARY is already in the correct locale */ - DECLARATION_FOR_LC_NUMERIC_MANIPULATION; +# ifdef USE_LOCALE_MONETARY + + const bool is_monetary_utf8 = _is_cur_LC_category_utf8(LC_MONETARY); +# endif +# ifdef USE_LOCALE_NUMERIC + + bool is_numeric_utf8; + STORE_LC_NUMERIC_FORCE_TO_UNDERLYING(); + is_numeric_utf8 = _is_cur_LC_category_utf8(LC_NUMERIC); +# endif + RETVAL = newHV(); sv_2mortal((SV*)RETVAL); - if ((lcbuf = localeconv())) { +# if defined(USE_ITHREADS) \ + && defined(HAS_POSIX_2008_LOCALE) \ + && defined(HAS_LOCALECONV_L) + + cur = uselocale((locale_t) 0); + if (cur == LC_GLOBAL_LOCALE) { + cur = duplocale(LC_GLOBAL_LOCALE); + do_free = TRUE; + } + + lcbuf = localeconv_l(cur); +# else + LOCALE_LOCK; /* Prevent interference with other threads using + localeconv() */ + + lcbuf = localeconv(); +# endif + if (lcbuf) { const struct lconv_offset *strings = lconv_strings; const struct lconv_offset *integers = lconv_integers; const char *ptr = (const char *) lcbuf; @@ -2191,35 +2174,36 @@ localeconv() while (strings->name) { /* This string may be controlled by either LC_NUMERIC, or * LC_MONETARY */ - bool is_utf8_locale -#if defined(USE_LOCALE_NUMERIC) && defined(USE_LOCALE_MONETARY) - = _is_cur_LC_category_utf8((isLC_NUMERIC_STRING(strings->name)) - ? LC_NUMERIC - : LC_MONETARY); -#elif defined(USE_LOCALE_NUMERIC) - = _is_cur_LC_category_utf8(LC_NUMERIC); -#elif defined(USE_LOCALE_MONETARY) - = _is_cur_LC_category_utf8(LC_MONETARY); -#else - = FALSE; -#endif + const bool is_utf8_locale = +# if defined(USE_LOCALE_NUMERIC) && defined(USE_LOCALE_MONETARY) + (isLC_NUMERIC_STRING(strings->name)) + ? is_numeric_utf8 + : is_monetary_utf8; +# elif defined(USE_LOCALE_NUMERIC) + is_numeric_utf8; +# elif defined(USE_LOCALE_MONETARY) + is_monetary_utf8; +# else + FALSE; +# endif const char *value = *((const char **)(ptr + strings->offset)); if (value && *value) { + const STRLEN value_len = strlen(value); + + /* We mark it as UTF-8 if a utf8 locale and is valid and + * variant under UTF-8 */ + const bool is_utf8 = is_utf8_locale + && is_utf8_non_invariant_string( + (U8*) value, + value_len); (void) hv_store(RETVAL, - strings->name, - strlen(strings->name), - newSVpvn_utf8(value, - strlen(value), - - /* We mark it as UTF-8 if a utf8 locale - * and is valid and variant under UTF-8 */ - is_utf8_locale - && ! is_invariant_string((U8 *) value, 0) - && is_utf8_string((U8 *) value, 0)), - 0); - } + strings->name, + strlen(strings->name), + newSVpvn_utf8(value, value_len, is_utf8), + 0); + } strings++; } @@ -2232,7 +2216,16 @@ localeconv() integers++; } } - RESTORE_LC_NUMERIC_STANDARD(); +# if defined(USE_ITHREADS) \ + && defined(HAS_POSIX_2008_LOCALE) \ + && defined(HAS_LOCALECONV_L) + if (do_free) { + freelocale(cur); + } +# else + LOCALE_UNLOCK; +# endif + RESTORE_LC_NUMERIC(); #endif /* HAS_LOCALECONV */ OUTPUT: RETVAL @@ -2244,119 +2237,18 @@ setlocale(category, locale = 0) PREINIT: char * retval; CODE: -#ifdef USE_LOCALE_NUMERIC - /* A 0 (or NULL) locale means only query what the current one is. We - * have the LC_NUMERIC name saved, because we are normally switched - * into the C locale for it. Switch back so an LC_ALL query will yield - * the correct results; all other categories don't require special - * handling */ - if (locale == 0) { - if (category == LC_NUMERIC) { - XSRETURN_PV(PL_numeric_name); - } -# ifdef LC_ALL - else if (category == LC_ALL) { - SET_NUMERIC_UNDERLYING(); - } -# endif - } -#endif -#ifdef WIN32 /* Use wrapper on Windows */ - retval = Perl_my_setlocale(aTHX_ category, locale); -#else - retval = setlocale(category, locale); -#endif - DEBUG_L(PerlIO_printf(Perl_debug_log, - "%s:%d: %s\n", __FILE__, __LINE__, - _setlocale_debug_string(category, locale, retval))); - if (! retval) { - /* Should never happen that a query would return an error, but be - * sure and reset to C locale */ - if (locale == 0) { - SET_NUMERIC_STANDARD(); - } + retval = Perl_setlocale(category, locale); + if (! retval) { /* Should never happen that a query would return an + * error, but be sure */ XSRETURN_UNDEF; } - /* Save retval since subsequent setlocale() calls may overwrite it. */ - retval = savepv(retval); + /* Make sure the returned copy gets cleaned up */ + SAVEFREEPV(retval); - /* For locale == 0, we may have switched to NUMERIC_UNDERLYING. Switch - * back */ - if (locale == 0) { - SET_NUMERIC_STANDARD(); - XSRETURN_PV(retval); - } - else { - RETVAL = retval; -#ifdef USE_LOCALE_CTYPE - if (category == LC_CTYPE -#ifdef LC_ALL - || category == LC_ALL -#endif - ) - { - char *newctype; -#ifdef LC_ALL - if (category == LC_ALL) { - newctype = setlocale(LC_CTYPE, NULL); - DEBUG_Lv(PerlIO_printf(Perl_debug_log, - "%s:%d: %s\n", __FILE__, __LINE__, - _setlocale_debug_string(LC_CTYPE, NULL, newctype))); - } - else -#endif - newctype = RETVAL; - new_ctype(newctype); - } -#endif /* USE_LOCALE_CTYPE */ -#ifdef USE_LOCALE_COLLATE - if (category == LC_COLLATE -#ifdef LC_ALL - || category == LC_ALL -#endif - ) - { - char *newcoll; -#ifdef LC_ALL - if (category == LC_ALL) { - newcoll = setlocale(LC_COLLATE, NULL); - DEBUG_Lv(PerlIO_printf(Perl_debug_log, - "%s:%d: %s\n", __FILE__, __LINE__, - _setlocale_debug_string(LC_COLLATE, NULL, newcoll))); - } - else -#endif - newcoll = RETVAL; - new_collate(newcoll); - } -#endif /* USE_LOCALE_COLLATE */ -#ifdef USE_LOCALE_NUMERIC - if (category == LC_NUMERIC -#ifdef LC_ALL - || category == LC_ALL -#endif - ) - { - char *newnum; -#ifdef LC_ALL - if (category == LC_ALL) { - newnum = setlocale(LC_NUMERIC, NULL); - DEBUG_Lv(PerlIO_printf(Perl_debug_log, - "%s:%d: %s\n", __FILE__, __LINE__, - _setlocale_debug_string(LC_NUMERIC, NULL, newnum))); - } - else -#endif - newnum = RETVAL; - new_numeric(newnum); - } -#endif /* USE_LOCALE_NUMERIC */ - } + RETVAL = retval; OUTPUT: RETVAL - CLEANUP: - Safefree(RETVAL); NV acos(x) @@ -2394,7 +2286,11 @@ acos(x) y1 = 30 CODE: PERL_UNUSED_VAR(x); +#ifdef NV_NAN RETVAL = NV_NAN; +#else + RETVAL = 0; +#endif switch (ix) { case 0: RETVAL = Perl_acos(x); /* C89 math */ @@ -2689,7 +2585,12 @@ fpclassify(x) #ifdef Perl_signbit RETVAL = Perl_signbit(x); #else - RETVAL = (x < 0) || (x == -0.0); + RETVAL = (x < 0); +#ifdef DOUBLE_IS_IEEE_FORMAT + if (x == -0.0) { + RETVAL = TRUE; + } +#endif #endif break; } @@ -2700,7 +2601,13 @@ NV getpayload(nv) NV nv CODE: +#ifdef DOUBLE_HAS_NAN RETVAL = S_getpayload(nv); +#else + PERL_UNUSED_VAR(nv); + RETVAL = 0.0; + not_here("getpayload"); +#endif OUTPUT: RETVAL @@ -2709,7 +2616,13 @@ setpayload(nv, payload) NV nv NV payload CODE: +#ifdef DOUBLE_HAS_NAN S_setpayload(&nv, payload, FALSE); +#else + PERL_UNUSED_VAR(nv); + PERL_UNUSED_VAR(payload); + not_here("setpayload"); +#endif OUTPUT: nv @@ -2718,8 +2631,14 @@ setpayloadsig(nv, payload) NV nv NV payload CODE: +#ifdef DOUBLE_HAS_NAN nv = NV_NAN; S_setpayload(&nv, payload, TRUE); +#else + PERL_UNUSED_VAR(nv); + PERL_UNUSED_VAR(payload); + not_here("setpayloadsig"); +#endif OUTPUT: nv @@ -2727,7 +2646,13 @@ int issignaling(nv) NV nv CODE: +#ifdef DOUBLE_HAS_NAN RETVAL = Perl_isnan(nv) && NV_NAN_IS_SIGNALING(&nv); +#else + PERL_UNUSED_VAR(nv); + RETVAL = 0.0; + not_here("issignaling"); +#endif OUTPUT: RETVAL @@ -2753,7 +2678,11 @@ copysign(x,y) CODE: PERL_UNUSED_VAR(x); PERL_UNUSED_VAR(y); +#ifdef NV_NAN RETVAL = NV_NAN; +#else + RETVAL = 0; +#endif switch (ix) { case 0: #ifdef c99_copysign @@ -2947,9 +2876,14 @@ nan(payload = 0) } #elif defined(c99_nan) { - STRLEN elen = my_snprintf(PL_efloatbuf, PL_efloatsize, "%g", nv); + STRLEN elen = my_snprintf(PL_efloatbuf, PL_efloatsize, "%g", payload); if ((IV)elen == -1) { +#ifdef NV_NAN RETVAL = NV_NAN; +#else + RETVAL = 0.0; + not_here("nan"); +#endif } else { RETVAL = c99_nan(PL_efloatbuf); } @@ -2967,7 +2901,11 @@ jn(x,y) ALIAS: yn = 1 CODE: +#ifdef NV_NAN RETVAL = NV_NAN; +#else + RETVAL = 0; +#endif switch (ix) { case 0: #ifdef bessel_jn @@ -3025,7 +2963,7 @@ sigaction(sig, optaction, oldaction = 0) const char *s = SvPVX_const(ST(0)); int i = whichsig(s); - if (i < 0 && memEQ(s, "SIG", 3)) + if (i < 0 && memBEGINs(s, SvCUR(ST(0)), "SIG")) i = whichsig(s + 3); if (i < 0) { if (ckWARN(WARN_SIGNAL)) @@ -3338,39 +3276,30 @@ write(fd, buffer, nbytes) char * buffer size_t nbytes -SV * -tmpnam() - PREINIT: - STRLEN i; - int len; - CODE: - RETVAL = newSVpvs(""); - SvGROW(RETVAL, L_tmpnam); - /* Yes, we know tmpnam() is bad. So bad that some compilers - * and linkers warn against using it. But it is here for - * completeness. POSIX.pod warns against using it. - * - * Then again, maybe this should be removed at some point. - * No point in enabling dangerous interfaces. */ - if (ckWARN_d(WARN_DEPRECATED)) { - HV *warned = get_hv("POSIX::_warned", GV_ADD | GV_ADDMULTI); - if (! hv_exists(warned, (const char *)&PL_op, sizeof(PL_op))) { - Perl_warner(aTHX_ packWARN(WARN_DEPRECATED), "Calling POSIX::tmpnam() is deprecated"); - (void)hv_store(warned, (const char *)&PL_op, sizeof(PL_op), &PL_sv_yes, 0); - } - } - len = strlen(tmpnam(SvPV(RETVAL, i))); - SvCUR_set(RETVAL, len); - OUTPUT: - RETVAL - void abort() +#ifdef I_WCHAR +# include +#endif + int mblen(s, n) char * s size_t n + PREINIT: +#if defined(USE_ITHREADS) && defined(HAS_MBRLEN) + mbstate_t ps; +#endif + CODE: +#if defined(USE_ITHREADS) && defined(HAS_MBRLEN) + PERL_UNUSED_RESULT(mbrlen(NULL, 0, &ps)); /* Initialize state */ + RETVAL = mbrlen(s, n, &ps); /* Prefer reentrant version */ +#else + RETVAL = mblen(s, n); +#endif + OUTPUT: + RETVAL size_t mbstowcs(s, pwcs, n) @@ -3383,6 +3312,21 @@ mbtowc(pwc, s, n) wchar_t * pwc char * s size_t n + PREINIT: +#if defined(USE_ITHREADS) && defined(HAS_MBRTOWC) + mbstate_t ps; +#endif + CODE: +#if defined(USE_ITHREADS) && defined(HAS_MBRTOWC) + memset(&ps, 0, sizeof(ps));; + PERL_UNUSED_RESULT(mbrtowc(pwc, NULL, 0, &ps));/* Reset any shift state */ + errno = 0; + RETVAL = mbrtowc(pwc, s, n, &ps); /* Prefer reentrant version */ +#else + RETVAL = mbtowc(pwc, s, n); +#endif + OUTPUT: + RETVAL int wcstombs(s, pwcs, n) @@ -3410,6 +3354,7 @@ strtod(str) DECLARATION_FOR_LC_NUMERIC_MANIPULATION; STORE_LC_NUMERIC_FORCE_TO_UNDERLYING(); num = strtod(str, &unparsed); + RESTORE_LC_NUMERIC(); PUSHs(sv_2mortal(newSVnv(num))); if (GIMME_V == G_ARRAY) { EXTEND(SP, 1); @@ -3418,7 +3363,6 @@ strtod(str) else PUSHs(&PL_sv_undef); } - RESTORE_LC_NUMERIC_STANDARD(); #ifdef HAS_STRTOLD @@ -3432,6 +3376,7 @@ strtold(str) DECLARATION_FOR_LC_NUMERIC_MANIPULATION; STORE_LC_NUMERIC_FORCE_TO_UNDERLYING(); num = strtold(str, &unparsed); + RESTORE_LC_NUMERIC(); PUSHs(sv_2mortal(newSVnv(num))); if (GIMME_V == G_ARRAY) { EXTEND(SP, 1); @@ -3440,7 +3385,6 @@ strtold(str) else PUSHs(&PL_sv_undef); } - RESTORE_LC_NUMERIC_STANDARD(); #endif @@ -3482,7 +3426,7 @@ strtoul(str, base = 0) int base PREINIT: unsigned long num; - char *unparsed; + char *unparsed = NULL; PPCODE: PERL_UNUSED_VAR(str); PERL_UNUSED_VAR(base); @@ -3617,7 +3561,7 @@ asctime(sec, min, hour, mday, mon, year, wday = 0, yday = 0, isdst = -1) if (result == (time_t)-1) SvOK_off(TARG); else if (result == 0) - sv_setpvn(TARG, "0 but true", 10); + sv_setpvs(TARG, "0 but true"); else sv_setiv(TARG, (IV)result); } else { @@ -3675,18 +3619,23 @@ strftime(fmt, sec, min, hour, mday, mon, year, wday = -1, yday = -1, isdst = -1) /* allowing user-supplied (rather than literal) formats * is normally frowned upon as a potential security risk; * but this is part of the API so we have to allow it */ - GCC_DIAG_IGNORE(-Wformat-nonliteral); + GCC_DIAG_IGNORE_STMT(-Wformat-nonliteral); buf = my_strftime(SvPV_nolen(fmt), sec, min, hour, mday, mon, year, wday, yday, isdst); - GCC_DIAG_RESTORE; + GCC_DIAG_RESTORE_STMT; sv = sv_newmortal(); if (buf) { STRLEN len = strlen(buf); sv_usepvn_flags(sv, buf, len, SV_HAS_TRAILING_NUL); - if (SvUTF8(fmt) - || (! is_invariant_string((U8*) buf, len) - && is_utf8_string((U8*) buf, len) + if ( SvUTF8(fmt) + || ( is_utf8_non_invariant_string((U8*) buf, len) #ifdef USE_LOCALE_TIME && _is_cur_LC_category_utf8(LC_TIME) +#else /* If can't check directly, at least can see if script is consistent, + under UTF-8, which gives us an extra measure of confidence. */ + + && isSCRIPT_RUN((const U8 *) buf, buf + len, + TRUE, /* Means assume UTF-8 */ + NULL) #endif )) { SvUTF8_on(sv);