diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4 index 51a08bcc8b1d0..580832cdf7c36 100644 --- a/libstdc++-v3/acinclude.m4 +++ b/libstdc++-v3/acinclude.m4 @@ -2774,7 +2774,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|newlib|dragonfly|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 diff --git a/libstdc++-v3/config/locale/dragonfly/ctype_members.cc b/libstdc++-v3/config/locale/dragonfly/ctype_members.cc index 92b0e437ad337..8e20f74e6355a 100644 --- a/libstdc++-v3/config/locale/dragonfly/ctype_members.cc +++ b/libstdc++-v3/config/locale/dragonfly/ctype_members.cc @@ -135,6 +135,66 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __hi; } +/* + * Taken verbatim from config/locale/generic/ctype_members.cc. DragonFly + * implements these in config/os/bsd/dragonfly/ctype_inline.h. + */ +#if defined(__illumos__) + bool + ctype:: + do_is(mask __m, char_type __c) const + { + bool __ret = false; + // Generically, 15 (instead of 11) since we don't know the numerical + // encoding of the various categories in /usr/include/ctype.h. + const size_t __bitmasksize = 15; + 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) + { + // Generically, 15 (instead of 11) since we don't know the numerical + // encoding of the various categories in /usr/include/ctype.h. + const size_t __bitmasksize = 15; + 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/dragonfly/monetary_members.cc index 6e48e45b3e749..0aeb395c3a8b5 100644 --- a/libstdc++-v3/config/locale/dragonfly/monetary_members.cc +++ b/libstdc++-v3/config/locale/dragonfly/monetary_members.cc @@ -37,10 +37,36 @@ namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION + extern wchar_t lconv2wchar(char *conv, wchar_t def, locale_t __cloc); + extern char lconv2char(char *conv, char def); + // This file might be compiled twice, but we only want to define the members // of money_base once. #if ! _GLIBCXX_USE_CXX11_ABI + wchar_t lconv2wchar(char *conv, wchar_t def, locale_t __cloc) + { + wchar_t w = def; + const size_t tlen = strlen(conv); + if (tlen == 1) + w = (wchar_t) conv[0]; + + int clen = mbtowc_l(&w, conv, tlen, __cloc); + if (clen <= 0) + return def; + else + return w; + } + + char lconv2char(char *conv, char def) + { + wchar_t w = def; + const size_t tlen = strlen(conv); + if (tlen == 1) + w = (wchar_t) conv[0]; + return w; + } + // Construct and return valid pattern consisting of some combination of: // space none symbol sign value money_base::pattern @@ -283,7 +309,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } else { - _M_data->_M_thousands_sep = lc->mon_thousands_sep[0]; + _M_data->_M_thousands_sep = lconv2char(lc->mon_thousands_sep, ','); __len = strlen(__cgroup); if (__len) @@ -437,7 +463,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } else { - _M_data->_M_thousands_sep = lc->mon_thousands_sep[0]; + _M_data->_M_thousands_sep = lconv2char(lc->mon_thousands_sep, ','); __len = strlen(__cgroup); if (__len) @@ -624,8 +650,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } else { - _M_data->_M_thousands_sep = - (wchar_t)lc->mon_thousands_sep[0]; + _M_data->_M_thousands_sep = lconv2wchar(lc->mon_thousands_sep, L',', (locale_t)__cloc); __len = strlen(__cgroup); if (__len) { @@ -784,8 +809,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } else { - _M_data->_M_thousands_sep = - (wchar_t)lc->mon_thousands_sep[0]; + _M_data->_M_thousands_sep = lconv2wchar(lc->mon_thousands_sep, L',', (locale_t)__cloc); __len = strlen(__cgroup); if (__len) { diff --git a/libstdc++-v3/config/locale/dragonfly/numeric_members.cc b/libstdc++-v3/config/locale/dragonfly/numeric_members.cc index dc71ef4ed701f..06e6f044f8467 100644 --- a/libstdc++-v3/config/locale/dragonfly/numeric_members.cc +++ b/libstdc++-v3/config/locale/dragonfly/numeric_members.cc @@ -37,6 +37,9 @@ namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION + extern wchar_t lconv2wchar(char *conv, wchar_t def, locale_t __cloc); + extern char lconv2char(char *conv, char def); + template<> void numpunct::_M_initialize_numpunct(__c_locale __cloc) @@ -86,7 +89,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } else { - _M_data->_M_thousands_sep = lc->thousands_sep[0]; + _M_data->_M_thousands_sep = lconv2char(lc->thousands_sep, ','); const char* __src = lc->grouping; const size_t __len = strlen(__src); @@ -185,7 +188,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } else { - _M_data->_M_thousands_sep = (wchar_t)lc->thousands_sep[0]; + _M_data->_M_thousands_sep = lconv2wchar(lc->thousands_sep, L',', (locale_t)__cloc); const char* __src = lc->grouping; const size_t __len = strlen(__src); diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure index b6fc2d463061d..2e61081ac8468 100755 --- a/libstdc++-v3/configure +++ b/libstdc++-v3/configure @@ -16635,7 +16635,7 @@ $as_echo "stdio (with POSIX read/write)" >&6; } if test "${enable_clocale+set}" = set; then : enableval=$enable_clocale; case "$enableval" in - generic|gnu|ieee_1003.1-2001|newlib|yes|no|auto) ;; + generic|gnu|ieee_1003.1-2001|newlib|dragonfly|yes|no|auto) ;; *) as_fn_error $? "Unknown argument to enable/disable clocale" "$LINENO" 5 ;; esac