From d36a04c7d4eb390817d711dc59ad0e0759bccdce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Chigot?= Date: Tue, 29 Dec 2020 11:08:33 +0100 Subject: [PATCH] libstdc++: implement locale support for POSIX 2008 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The implementation is based on dragonfly one. It also adds support for AIX with a few tweaks. As of now, a few locale functions are missing on AIX. For strftime_l, localeconv_l, mbstowcs_l and wcsftime_l, uselocale must be set prior to use the version without _l. For strtof_l, strtod_l, strtold_l, a wrapper simply calls the default version. libstdc++-v3/ChangeLog: 2021-01-12 Clément Chigot * acinclude.m4: Add ieee_1003.1-2008 locale model. * configure: Regenerate. * config/os/aix/ctype_configure_char.cc: Enable locale support. * testsuite/lib/libstdc++.exp (check_v3_target_namedlocale): Handle AIX locale names. * testsuite/util/testsuite_hooks.h: Likewise. * config/locale/dragonfly/c_locale.cc: Removed. * config/locale/dragonfly/c_locale.h: Removed. * config/locale/dragonfly/codecvt_members.cc: Removed. * config/locale/dragonfly/collate_members.cc: Removed. * config/locale/dragonfly/ctype_members.cc: Removed. * config/locale/dragonfly/monetary_members.cc: Removed. * config/locale/dragonfly/numeric_members.cc: Removed. * config/locale/dragonfly/time_members.cc: Removed. * config/locale/dragonfly/time_members.h: Removed. * config/locale/ieee_1003.1-2008/c_locale.cc: New file. * config/locale/ieee_1003.1-2008/c_locale.h: New file. * config/locale/ieee_1003.1-2008/codecvt_members.cc: New file. * config/locale/ieee_1003.1-2008/collate_members.cc: New file. * config/locale/ieee_1003.1-2008/ctype_members.cc: New file. * config/locale/ieee_1003.1-2008/monetary_members.cc: New file. * config/locale/ieee_1003.1-2008/numeric_members.cc: New file. * config/locale/ieee_1003.1-2008/time_members.cc: New file. * config/locale/ieee_1003.1-2008/time_members.h: New file. --- libstdc++-v3/acinclude.m4 | 41 ++++++------- .../c_locale.cc | 3 + .../c_locale.h | 31 ++++++++++ .../codecvt_members.cc | 0 .../collate_members.cc | 0 .../ctype_members.cc | 58 +++++++++++++++++++ .../monetary_members.cc | 39 ++++++++++++- .../numeric_members.cc | 27 +++++++++ .../time_members.cc | 32 +++++++++- .../time_members.h | 0 .../config/os/aix/ctype_configure_char.cc | 44 +++++++++++--- libstdc++-v3/testsuite/lib/libstdc++.exp | 5 ++ libstdc++-v3/testsuite/util/testsuite_hooks.h | 3 + 13 files changed, 252 insertions(+), 31 deletions(-) rename libstdc++-v3/config/locale/{dragonfly => ieee_1003.1-2008}/c_locale.cc (99%) rename libstdc++-v3/config/locale/{dragonfly => ieee_1003.1-2008}/c_locale.h (80%) rename libstdc++-v3/config/locale/{dragonfly => ieee_1003.1-2008}/codecvt_members.cc (100%) rename libstdc++-v3/config/locale/{dragonfly => ieee_1003.1-2008}/collate_members.cc (100%) rename libstdc++-v3/config/locale/{dragonfly => ieee_1003.1-2008}/ctype_members.cc (82%) rename libstdc++-v3/config/locale/{dragonfly => ieee_1003.1-2008}/monetary_members.cc (97%) rename libstdc++-v3/config/locale/{dragonfly => ieee_1003.1-2008}/numeric_members.cc (93%) rename libstdc++-v3/config/locale/{dragonfly => ieee_1003.1-2008}/time_members.cc (94%) rename libstdc++-v3/config/locale/{dragonfly => ieee_1003.1-2008}/time_members.h (100%) diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4 index e4175ea3e64..64a91b72359 100644 --- a/libstdc++-v3/acinclude.m4 +++ b/libstdc++-v3/acinclude.m4 @@ -2421,7 +2421,7 @@ dnl AC_DEFUN([GLIBCXX_ENABLE_CLOCALE], [ GLIBCXX_ENABLE(clocale,auto,[[[=MODEL]]], [use MODEL for target locale package], - [permit generic|gnu|ieee_1003.1-2001|newlib|yes|no|auto]) + [permit generic|gnu|ieee_1003.1-2001|ieee_1003.1-2008|newlib|yes|no|auto]) # Deal with gettext issues. Default to not using it (=no) until we detect # support for it later. Let the user turn it off via --e/d, but let that @@ -2448,8 +2448,8 @@ AC_DEFUN([GLIBCXX_ENABLE_CLOCALE], [ darwin*) enable_clocale_flag=darwin ;; - dragonfly* | freebsd*) - enable_clocale_flag=dragonfly + aix* | dragonfly* | freebsd*) + enable_clocale_flag=ieee_1003.1-2008 ;; openbsd*) enable_clocale_flag=newlib @@ -2543,23 +2543,6 @@ AC_DEFUN([GLIBCXX_ENABLE_CLOCALE], [ CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h ;; - dragonfly) - AC_MSG_RESULT(dragonfly or freebsd) - - CLOCALE_H=config/locale/dragonfly/c_locale.h - CLOCALE_CC=config/locale/dragonfly/c_locale.cc - CCODECVT_CC=config/locale/dragonfly/codecvt_members.cc - CCOLLATE_CC=config/locale/dragonfly/collate_members.cc - CCTYPE_CC=config/locale/dragonfly/ctype_members.cc - CMESSAGES_H=config/locale/generic/messages_members.h - CMESSAGES_CC=config/locale/generic/messages_members.cc - CMONEY_CC=config/locale/dragonfly/monetary_members.cc - CNUMERIC_CC=config/locale/dragonfly/numeric_members.cc - CTIME_H=config/locale/dragonfly/time_members.h - CTIME_CC=config/locale/dragonfly/time_members.cc - CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h - ;; - gnu) AC_MSG_RESULT(gnu) @@ -2610,6 +2593,24 @@ AC_DEFUN([GLIBCXX_ENABLE_CLOCALE], [ CTIME_CC=config/locale/generic/time_members.cc CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h ;; + + ieee_1003.1-2008) + AC_MSG_RESULT(ieee_1003.1-2008) + + CLOCALE_H=config/locale/ieee_1003.1-2008/c_locale.h + CLOCALE_CC=config/locale/ieee_1003.1-2008/c_locale.cc + CCODECVT_CC=config/locale/ieee_1003.1-2008/codecvt_members.cc + CCOLLATE_CC=config/locale/ieee_1003.1-2008/collate_members.cc + CCTYPE_CC=config/locale/ieee_1003.1-2008/ctype_members.cc + CMESSAGES_H=config/locale/generic/messages_members.h + CMESSAGES_CC=config/locale/generic/messages_members.cc + CMONEY_CC=config/locale/ieee_1003.1-2008/monetary_members.cc + CNUMERIC_CC=config/locale/ieee_1003.1-2008/numeric_members.cc + CTIME_H=config/locale/ieee_1003.1-2008/time_members.h + CTIME_CC=config/locale/ieee_1003.1-2008/time_members.cc + CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h + ;; + newlib) AC_MSG_RESULT(newlib) diff --git a/libstdc++-v3/config/locale/dragonfly/c_locale.cc b/libstdc++-v3/config/locale/ieee_1003.1-2008/c_locale.cc similarity index 99% rename from libstdc++-v3/config/locale/dragonfly/c_locale.cc rename to libstdc++-v3/config/locale/ieee_1003.1-2008/c_locale.cc index 02df4605bb5..988f34ab6ed 100644 --- a/libstdc++-v3/config/locale/dragonfly/c_locale.cc +++ b/libstdc++-v3/config/locale/ieee_1003.1-2008/c_locale.cc @@ -33,8 +33,11 @@ #include #include #include + +#ifdef __DragonFly__ #include #include +#endif namespace std _GLIBCXX_VISIBILITY(default) { diff --git a/libstdc++-v3/config/locale/dragonfly/c_locale.h b/libstdc++-v3/config/locale/ieee_1003.1-2008/c_locale.h similarity index 80% rename from libstdc++-v3/config/locale/dragonfly/c_locale.h rename to libstdc++-v3/config/locale/ieee_1003.1-2008/c_locale.h index cf4281cebbf..f77f815c61b 100644 --- a/libstdc++-v3/config/locale/dragonfly/c_locale.h +++ b/libstdc++-v3/config/locale/ieee_1003.1-2008/c_locale.h @@ -40,7 +40,34 @@ #pragma GCC system_header #include +#ifdef __DragonFly__ #include +#endif + +#ifdef _AIX +// The following are not POSIX routines. These are quick-and-dirty hacks +// to make things pretend to work +extern "C" inline +float strtof_l (const char *__nptr, char **__endptr, + locale_t locale) +{ + return strtof(__nptr, __endptr); +} + +extern "C" inline +double strtod_l (const char *__nptr, char **__endptr, + locale_t locale) +{ + return strtod(__nptr, __endptr); +} + +extern "C" inline +long double strtold_l (const char *__nptr, char **__endptr, + locale_t locale) +{ + return strtold(__nptr, __endptr); +} +#endif #define _GLIBCXX_NUM_CATEGORIES 0 @@ -48,7 +75,11 @@ namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION +#ifdef __DragonFly__ typedef int* __c_locale; +#else + typedef locale_t __c_locale; +#endif // Convert numeric value of type double and long double to string and // return length of string. If vsnprintf is available use it, otherwise diff --git a/libstdc++-v3/config/locale/dragonfly/codecvt_members.cc b/libstdc++-v3/config/locale/ieee_1003.1-2008/codecvt_members.cc similarity index 100% rename from libstdc++-v3/config/locale/dragonfly/codecvt_members.cc rename to libstdc++-v3/config/locale/ieee_1003.1-2008/codecvt_members.cc diff --git a/libstdc++-v3/config/locale/dragonfly/collate_members.cc b/libstdc++-v3/config/locale/ieee_1003.1-2008/collate_members.cc similarity index 100% rename from libstdc++-v3/config/locale/dragonfly/collate_members.cc rename to libstdc++-v3/config/locale/ieee_1003.1-2008/collate_members.cc diff --git a/libstdc++-v3/config/locale/dragonfly/ctype_members.cc b/libstdc++-v3/config/locale/ieee_1003.1-2008/ctype_members.cc similarity index 82% rename from libstdc++-v3/config/locale/dragonfly/ctype_members.cc rename to libstdc++-v3/config/locale/ieee_1003.1-2008/ctype_members.cc index 420cb51e07a..ad9d3a4709b 100644 --- a/libstdc++-v3/config/locale/dragonfly/ctype_members.cc +++ b/libstdc++-v3/config/locale/ieee_1003.1-2008/ctype_members.cc @@ -34,7 +34,11 @@ #include #ifndef _ISbit +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #define _ISbit(bit) ((bit) < 8 ? ((1 << (bit)) << 8) : ((1 << (bit)) >> 8)) +#else +#define _ISbit(bit) (1 << bit) +#endif #endif namespace std _GLIBCXX_VISIBILITY(default) @@ -135,6 +139,60 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __hi; } +#ifndef __DragonFly__ + bool + ctype:: + do_is(mask __m, char_type __c) const + { + bool __ret = false; + // Highest bitmask in ctype_base == 11 + const size_t __bitmasksize = 11; + for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur) + if (__m & _M_bit[__bitcur] + && iswctype(__c, _M_wmask[__bitcur])) + { + __ret = true; + break; + } + return __ret; + } + + const wchar_t* + ctype:: + do_is(const wchar_t* __lo, const wchar_t* __hi, mask* __vec) const + { + for (;__lo < __hi; ++__vec, ++__lo) + { + // Highest bitmask in ctype_base == 11 + const size_t __bitmasksize = 11; + mask __m = 0; + for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur) + if (iswctype(*__lo, _M_wmask[__bitcur])) + __m |= _M_bit[__bitcur]; + *__vec = __m; + } + return __hi; + } + + const wchar_t* + ctype:: + do_scan_is(mask __m, const wchar_t* __lo, const wchar_t* __hi) const + { + while (__lo < __hi && !this->do_is(__m, *__lo)) + ++__lo; + return __lo; + } + + const wchar_t* + ctype:: + do_scan_not(mask __m, const char_type* __lo, const char_type* __hi) const + { + while (__lo < __hi && this->do_is(__m, *__lo) != 0) + ++__lo; + return __lo; + } +#endif + wchar_t ctype:: do_widen(char __c) const diff --git a/libstdc++-v3/config/locale/dragonfly/monetary_members.cc b/libstdc++-v3/config/locale/ieee_1003.1-2008/monetary_members.cc similarity index 97% rename from libstdc++-v3/config/locale/dragonfly/monetary_members.cc rename to libstdc++-v3/config/locale/ieee_1003.1-2008/monetary_members.cc index e1decc61cbf..7680a1a3916 100644 --- a/libstdc++-v3/config/locale/dragonfly/monetary_members.cc +++ b/libstdc++-v3/config/locale/ieee_1003.1-2008/monetary_members.cc @@ -31,7 +31,10 @@ #include #include + +#ifdef __DragonFly__ #include +#endif namespace std _GLIBCXX_VISIBILITY(default) { @@ -241,7 +244,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION else { // Named locale. +#ifdef _AIX + __c_locale __old = uselocale(__cloc); + lconv* lc = localeconv(); +#else lconv* lc = localeconv_l((locale_t) __cloc); +#endif // Check for NULL, which implies no fractional digits. if (lc->mon_decimal_point == NULL || @@ -348,6 +356,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION delete [] __group; delete [] __ps; delete [] __ns; +#ifdef _AIX + uselocale(__old); +#endif __throw_exception_again; } @@ -360,6 +371,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION char __nspace = lc->int_n_sep_by_space; _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, __nposn); +#ifdef _AIX + uselocale(__old); +#endif } } @@ -395,7 +409,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION else { // Named locale. +#ifdef _AIX + __c_locale __old = uselocale(__cloc); + lconv* lc = localeconv(); +#else lconv* lc = localeconv_l((locale_t) __cloc); +#endif // Check for NULL, which implies no fractional digits. if (lc->mon_decimal_point == NULL || @@ -502,6 +521,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION delete [] __group; delete [] __ps; delete [] __ns; +#ifdef _AIX + uselocale(__old); +#endif __throw_exception_again; } @@ -514,6 +536,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION char __nspace = lc->n_sep_by_space; _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, __nposn); +#ifdef _AIX + uselocale(__old); +#endif } } @@ -581,9 +606,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } else { - __c_locale __old = (__c_locale)uselocale((locale_t)__cloc); // Named locale. + // uselocale is needed for mbsrtowcs + __c_locale __old = (__c_locale)uselocale((locale_t)__cloc); +#ifdef _AIX + lconv* lc = localeconv(); +#else lconv* lc = localeconv_l((locale_t) __cloc); +#endif // Check for NULL, which implies no fractional digits. if (lc->mon_decimal_point == NULL || @@ -741,9 +771,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } else { - __c_locale __old = (__c_locale)uselocale((locale_t)__cloc); // Named locale. + // uselocale is needed for mbsrtowcs + __c_locale __old = (__c_locale)uselocale((locale_t)__cloc); +#ifdef _AIX + lconv* lc = localeconv(); +#else lconv* lc = localeconv_l((locale_t) __cloc); +#endif // Check for NULL, which implies no fractional digits. if (lc->mon_decimal_point == NULL || diff --git a/libstdc++-v3/config/locale/dragonfly/numeric_members.cc b/libstdc++-v3/config/locale/ieee_1003.1-2008/numeric_members.cc similarity index 93% rename from libstdc++-v3/config/locale/dragonfly/numeric_members.cc rename to libstdc++-v3/config/locale/ieee_1003.1-2008/numeric_members.cc index cac6fe8c710..eb460c94088 100644 --- a/libstdc++-v3/config/locale/dragonfly/numeric_members.cc +++ b/libstdc++-v3/config/locale/ieee_1003.1-2008/numeric_members.cc @@ -31,7 +31,10 @@ #include #include + +#ifdef __DragonFly__ #include +#endif namespace std _GLIBCXX_VISIBILITY(default) { @@ -63,7 +66,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION else { // Named locale. +#ifdef _AIX + // uselocale is needed for localeconv + __c_locale __old = uselocale(__cloc); + lconv* lc = localeconv(); +#else lconv* lc = localeconv_l((locale_t) __cloc); +#endif // Decimal point should always be defined, but check null anyway if (lc->decimal_point == NULL) @@ -103,6 +112,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { delete _M_data; _M_data = 0; +#ifdef _AIX + uselocale(__old); +#endif __throw_exception_again; } } @@ -113,6 +125,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } _M_data->_M_grouping_size = __len; } +#ifdef _AIX + uselocale(__old); +#endif } // NB: There is no way to extact this info from posix locales. @@ -162,7 +177,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION else { // Named locale. +#ifdef _AIX + // uselocale is needed for localeconv + __c_locale __old = uselocale(__cloc); + lconv* lc = localeconv(); +#else lconv* lc = localeconv_l((locale_t) __cloc); +#endif // Decimal point should always be defined, but check null anyway if (lc->decimal_point == NULL) @@ -201,6 +222,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { delete _M_data; _M_data = 0; +#ifdef _AIX + uselocale(__old); +#endif __throw_exception_again; } } @@ -211,6 +235,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } _M_data->_M_grouping_size = __len; } +#ifdef _AIX + uselocale(__old); +#endif } // NB: There is no way to extact this info from posix locales. diff --git a/libstdc++-v3/config/locale/dragonfly/time_members.cc b/libstdc++-v3/config/locale/ieee_1003.1-2008/time_members.cc similarity index 94% rename from libstdc++-v3/config/locale/dragonfly/time_members.cc rename to libstdc++-v3/config/locale/ieee_1003.1-2008/time_members.cc index c8b621a323f..660fc26de1a 100644 --- a/libstdc++-v3/config/locale/dragonfly/time_members.cc +++ b/libstdc++-v3/config/locale/ieee_1003.1-2008/time_members.cc @@ -35,7 +35,10 @@ #include #include #include + +#ifdef __DragonFly__ #include +#endif namespace std _GLIBCXX_VISIBILITY(default) { @@ -47,8 +50,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_put(char* __s, size_t __maxlen, const char* __format, const tm* __tm) const throw() { +#ifdef _AIX + __c_locale __old = uselocale(_M_c_locale_timepunct); + const size_t __len = strftime(__s, __maxlen, __format, __tm); + uselocale(__old); +#else const size_t __len = strftime_l(__s, __maxlen, __format, __tm, (locale_t)_M_c_locale_timepunct); +#endif // Make sure __s is null terminated. if (__len == 0) __s[0] = '\0'; @@ -196,15 +205,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_put(wchar_t* __s, size_t __maxlen, const wchar_t* __format, const tm* __tm) const throw() { +#ifdef _AIX + __c_locale __old = uselocale(_M_c_locale_timepunct); + const size_t __len = wcsftime(__s, __maxlen, __format, __tm); + uselocale(__old); +#else const size_t __len = wcsftime_l(__s, __maxlen, __format, __tm, (locale_t)_M_c_locale_timepunct); +#endif // Make sure __s is null terminated. if (__len == 0) __s[0] = L'\0'; } +#ifdef _AIX + // mbstowcs_l deosn't exist on AIX. "uselocale" must + // be called before using this macro. +#define MBSTOWCS_L(WCSTRING, STRING, NUMBER, LOCALE) \ + mbstowcs (WCSTRING, STRING, NUMBER); +#else +#define MBSTOWCS_L(WCSTRING, STRING, NUMBER, LOCALE) \ + mbstowcs_l (WCSTRING, STRING, NUMBER, LOCALE); +#endif #define WIDE_LANGINFO(M,FMT) \ - fmtlen = mbstowcs_l (holder, nl_langinfo_l(FMT, (locale_t)__cloc), \ + fmtlen = MBSTOWCS_L (holder, nl_langinfo_l(FMT, (locale_t)__cloc), \ 128, (locale_t)__cloc); \ langstring = new wchar_t[fmtlen + 1]; \ wcsncpy (langstring, holder, fmtlen); \ @@ -281,6 +305,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } else { +#ifdef _AIX + __c_locale __old = uselocale(__cloc); +#endif wchar_t *langstring = 0; wchar_t holder[128]; size_t fmtlen; @@ -342,6 +369,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION WIDE_LANGINFO(_M_amonth10, ABMON_10) WIDE_LANGINFO(_M_amonth11, ABMON_11) WIDE_LANGINFO(_M_amonth12, ABMON_12) +#ifdef _AIX + uselocale(__old); +#endif } } diff --git a/libstdc++-v3/config/locale/dragonfly/time_members.h b/libstdc++-v3/config/locale/ieee_1003.1-2008/time_members.h similarity index 100% rename from libstdc++-v3/config/locale/dragonfly/time_members.h rename to libstdc++-v3/config/locale/ieee_1003.1-2008/time_members.h diff --git a/libstdc++-v3/config/os/aix/ctype_configure_char.cc b/libstdc++-v3/config/os/aix/ctype_configure_char.cc index b12c0bd435c..3af3457ef41 100644 --- a/libstdc++-v3/config/os/aix/ctype_configure_char.cc +++ b/libstdc++-v3/config/os/aix/ctype_configure_char.cc @@ -44,25 +44,53 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ctype::ctype(__c_locale, const mask* __table, bool __del, size_t __refs) - : facet(__refs), _M_del(__table != 0 && __del), + : facet(__refs), _M_c_locale_ctype(_S_get_c_locale()), + _M_del(__table != 0 && __del), _M_toupper(NULL), _M_tolower(NULL), - _M_table(__table ? __table : classic_table()) + _M_table(__table ? __table : classic_table()), + _M_widen_ok(0), _M_narrow_ok(0) { + char* __old = setlocale(LC_CTYPE, NULL); + char* __sav = NULL; + if (strcmp(__old, "C")) + { + const size_t __len = strlen(__old) + 1; + __sav = new char[__len]; + memcpy(__sav, __old, __len); + setlocale(LC_CTYPE, "C"); + } + if (__sav) + { + setlocale(LC_CTYPE, __sav); + delete [] __sav; + } memset(_M_widen, 0, sizeof(_M_widen)); - _M_widen_ok = 0; memset(_M_narrow, 0, sizeof(_M_narrow)); - _M_narrow_ok = 0; } ctype::ctype(const mask* __table, bool __del, size_t __refs) - : facet(__refs), _M_del(__table != 0 && __del), + : facet(__refs), _M_c_locale_ctype(_S_get_c_locale()), + _M_del(__table != 0 && __del), _M_toupper(NULL), _M_tolower(NULL), - _M_table(__table ? __table : classic_table()) + _M_table(__table ? __table : classic_table()), + _M_widen_ok(0), _M_narrow_ok(0) { + char* __old = setlocale(LC_CTYPE, NULL); + char* __sav = NULL; + if (strcmp(__old, "C")) + { + const size_t __len = strlen(__old) + 1; + __sav = new char[__len]; + memcpy(__sav, __old, __len); + setlocale(LC_CTYPE, "C"); + } + if (__sav) + { + setlocale(LC_CTYPE, __sav); + delete [] __sav; + } memset(_M_widen, 0, sizeof(_M_widen)); - _M_widen_ok = 0; memset(_M_narrow, 0, sizeof(_M_narrow)); - _M_narrow_ok = 0; } char diff --git a/libstdc++-v3/testsuite/lib/libstdc++.exp b/libstdc++-v3/testsuite/lib/libstdc++.exp index 30a4345b14f..200602d003e 100644 --- a/libstdc++-v3/testsuite/lib/libstdc++.exp +++ b/libstdc++-v3/testsuite/lib/libstdc++.exp @@ -904,6 +904,11 @@ proc check_v3_target_namedlocale { args } { puts $f " strcpy(result, name);" puts $f "#if defined __FreeBSD__ || defined __DragonFly__ || defined __NetBSD__" puts $f " /* fall-through */" + puts $f "#elif defined _AIX" + puts $f " char *p = strstr(result, \"ISO8859-15\");" + puts $f " if (p) {" + puts $f " strcpy(p, \"8859-15\");" + puts $f " }" puts $f "#else" puts $f " if (strstr(result, \"ISO8859-15\")) {" puts $f " strcat(result, \"@euro\");" diff --git a/libstdc++-v3/testsuite/util/testsuite_hooks.h b/libstdc++-v3/testsuite/util/testsuite_hooks.h index b5e0767211a..a632f5f31f8 100644 --- a/libstdc++-v3/testsuite/util/testsuite_hooks.h +++ b/libstdc++-v3/testsuite/util/testsuite_hooks.h @@ -77,6 +77,9 @@ #if defined __FreeBSD__ || defined __DragonFly__ || defined __NetBSD__ # define ISO_8859(part,langTERR) #langTERR ".ISO8859-" #part +#elif defined _AIX +# define ISO_8859(part,langTERR) ((part) == 15 ?\ + #langTERR ".8859-" #part : #langTERR ".ISO8859-" #part) #else # define ISO_8859(part,langTERR) ((part) == 15 ?\ #langTERR ".ISO8859-" #part "@euro" : #langTERR ".ISO8859-" #part) -- 2.25.0