/* 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 \
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
RETVAL = newHV();
sv_2mortal((SV*)RETVAL);
+# 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();
+ 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 *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_utf8_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++;
}
integers++;
}
}
-
+# 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:
PREINIT:
char * retval;
CODE:
- retval = Perl_setlocale(category, locale);
- if (! retval) { /* Should never happen that a query would return an
- * error, but be sure */
+ retval = (char *) Perl_setlocale(category, locale);
+ if (! retval) {
XSRETURN_UNDEF;
}
- /* Make sure the returned copy gets cleaned up */
- SAVEFREEPV(retval);
-
RETVAL = retval;
OUTPUT:
RETVAL
void
abort()
+#ifdef I_WCHAR
+# include <wchar.h>
+#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)
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)
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);
else
PUSHs(&PL_sv_undef);
}
- RESTORE_LC_NUMERIC();
#ifdef HAS_STRTOLD
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);
else
PUSHs(&PL_sv_undef);
}
- RESTORE_LC_NUMERIC();
#endif