From a98e4e62c1c0c8570c7db321e3c8a2a7c2336c60 Mon Sep 17 00:00:00 2001 From: John Marino Date: Thu, 27 Aug 2015 12:12:41 +0000 Subject: [PATCH] Provide nearly complete std::locale support for DragonFly 2015-08-27 John Marino * acinclude.m4 (*-*-dragonfly*): Change 7 locale support files from generic to new DragonFly versions. * configure: Regenerate. * config/locale/dragonfly/c_locale.cc: Improve locale support. * config/locale/dragonfly/ctype_members.cc: Likewise. * config/os/bsd/dragonfly/ctype_configure_char.cc: Likewise. * config/os/bsd/dragonfly/os_defines.h: Define _GLIBCXX_USE_C99. * config/locale/dragonfly/c_locale.h: New. * config/locale/dragonfly/codecvt_members.cc: New. * config/locale/dragonfly/collate_members.cc: New. * config/locale/dragonfly/monetary_members.cc: New. * config/locale/dragonfly/numeric_members.cc: New. * config/locale/dragonfly/time_members.cc: New. * config/locale/dragonfly/time_members.h: New. From-SVN: r227257 --- libstdc++-v3/ChangeLog | 17 + libstdc++-v3/acinclude.m4 | 14 +- .../config/locale/dragonfly/c_locale.cc | 229 ++--- .../config/locale/dragonfly/c_locale.h | 82 ++ .../locale/dragonfly/codecvt_members.cc | 288 ++++++ .../locale/dragonfly/collate_members.cc | 74 ++ .../config/locale/dragonfly/ctype_members.cc | 95 +- .../locale/dragonfly/monetary_members.cc | 903 ++++++++++++++++++ .../locale/dragonfly/numeric_members.cc | 235 +++++ .../config/locale/dragonfly/time_members.cc | 404 ++++++++ .../config/locale/dragonfly/time_members.h | 95 ++ .../os/bsd/dragonfly/ctype_configure_char.cc | 66 +- .../config/os/bsd/dragonfly/os_defines.h | 1 + libstdc++-v3/configure | 14 +- 14 files changed, 2301 insertions(+), 216 deletions(-) create mode 100644 libstdc++-v3/config/locale/dragonfly/c_locale.h create mode 100644 libstdc++-v3/config/locale/dragonfly/codecvt_members.cc create mode 100644 libstdc++-v3/config/locale/dragonfly/collate_members.cc create mode 100644 libstdc++-v3/config/locale/dragonfly/monetary_members.cc create mode 100644 libstdc++-v3/config/locale/dragonfly/numeric_members.cc create mode 100644 libstdc++-v3/config/locale/dragonfly/time_members.cc create mode 100644 libstdc++-v3/config/locale/dragonfly/time_members.h diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index c07b0ea16ea..e74daf479a5 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,20 @@ +2015-08-27 John Marino + + * acinclude.m4 (*-*-dragonfly*): Change 7 locale support files + from generic to new DragonFly versions. + * configure: Regenerate. + * config/locale/dragonfly/c_locale.cc: Improve locale support. + * config/locale/dragonfly/ctype_members.cc: Likewise. + * config/os/bsd/dragonfly/ctype_configure_char.cc: Likewise. + * config/os/bsd/dragonfly/os_defines.h: Define _GLIBCXX_USE_C99. + * config/locale/dragonfly/c_locale.h: New. + * config/locale/dragonfly/codecvt_members.cc: New. + * config/locale/dragonfly/collate_members.cc: New. + * config/locale/dragonfly/monetary_members.cc: New. + * config/locale/dragonfly/numeric_members.cc: New. + * config/locale/dragonfly/time_members.cc: New. + * config/locale/dragonfly/time_members.h: New. + 2015-08-27 Jonathan Wakely * configure: Regenerate. diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4 index 78c1a8255fe..789bc5894a0 100644 --- a/libstdc++-v3/acinclude.m4 +++ b/libstdc++-v3/acinclude.m4 @@ -2087,17 +2087,17 @@ AC_DEFUN([GLIBCXX_ENABLE_CLOCALE], [ dragonfly) AC_MSG_RESULT(dragonfly) - CLOCALE_H=config/locale/generic/c_locale.h + CLOCALE_H=config/locale/dragonfly/c_locale.h CLOCALE_CC=config/locale/dragonfly/c_locale.cc - CCODECVT_CC=config/locale/generic/codecvt_members.cc - CCOLLATE_CC=config/locale/generic/collate_members.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/generic/monetary_members.cc - CNUMERIC_CC=config/locale/generic/numeric_members.cc - CTIME_H=config/locale/generic/time_members.h - CTIME_CC=config/locale/generic/time_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 ;; diff --git a/libstdc++-v3/config/locale/dragonfly/c_locale.cc b/libstdc++-v3/config/locale/dragonfly/c_locale.cc index dea7a391c76..500cf7e47ba 100644 --- a/libstdc++-v3/config/locale/dragonfly/c_locale.cc +++ b/libstdc++-v3/config/locale/dragonfly/c_locale.cc @@ -1,4 +1,4 @@ -// Wrapper for underlying C-language localization -*- C++ -*- +// localization implementation details, DragonFly version -*- C++ -*- // Copyright (C) 2014-2015 Free Software Foundation, Inc. // @@ -27,18 +27,14 @@ // // Written by Benjamin Kosnik +// Modified for DragonFly by John Marino -#include // For errno -#include // For isinf, finite, finitef, fabs -#include // For strof, strtold -#include -#include +#include #include +#include #include - -#ifdef _GLIBCXX_HAVE_IEEEFP_H -#include -#endif +#include +#include namespace std _GLIBCXX_VISIBILITY(default) { @@ -47,40 +43,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<> void __convert_to_v(const char* __s, float& __v, ios_base::iostate& __err, - const __c_locale&) throw() + const __c_locale& __cloc) throw() { - // Assumes __s formatted for "C" locale. - char* __old = setlocale(LC_ALL, 0); - const size_t __len = strlen(__old) + 1; - char* __sav = new char[__len]; - memcpy(__sav, __old, __len); - setlocale(LC_ALL, "C"); char* __sanity; - bool __overflow = false; - -#if !__FLT_HAS_INFINITY__ - errno = 0; -#endif - -#ifdef _GLIBCXX_HAVE_STRTOF - __v = strtof(__s, &__sanity); -#else - double __d = strtod(__s, &__sanity); - __v = static_cast(__d); -#ifdef _GLIBCXX_HAVE_FINITEF - if (!finitef (__v)) - __overflow = true; -#elif defined (_GLIBCXX_HAVE_FINITE) - if (!finite (static_cast (__v))) - __overflow = true; -#elif defined (_GLIBCXX_HAVE_ISINF) - if (isinf (static_cast (__v))) - __overflow = true; -#else - if (fabs(__d) > numeric_limits::max()) - __overflow = true; -#endif -#endif // _GLIBCXX_HAVE_STRTOF + __v = strtof_l(__s, &__sanity, (locale_t)__cloc); // _GLIBCXX_RESOLVE_LIB_DEFECTS // 23. Num_get overflow result. @@ -89,44 +55,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __v = 0.0f; __err = ios_base::failbit; } - else if (__overflow -#if __FLT_HAS_INFINITY__ - || __v == numeric_limits::infinity() - || __v == -numeric_limits::infinity() -#else - || ((__v > 1.0f || __v < -1.0f) && errno == ERANGE) -#endif - ) + else if (__v == numeric_limits::infinity()) { - if (__v > 0.0f) - __v = numeric_limits::max(); - else - __v = -numeric_limits::max(); + __v = numeric_limits::max(); + __err = ios_base::failbit; + } + else if (__v == -numeric_limits::infinity()) + { + __v = -numeric_limits::max(); __err = ios_base::failbit; } - - setlocale(LC_ALL, __sav); - delete [] __sav; } template<> void __convert_to_v(const char* __s, double& __v, ios_base::iostate& __err, - const __c_locale&) throw() + const __c_locale& __cloc) throw() { - // Assumes __s formatted for "C" locale. - char* __old = setlocale(LC_ALL, 0); - const size_t __len = strlen(__old) + 1; - char* __sav = new char[__len]; - memcpy(__sav, __old, __len); - setlocale(LC_ALL, "C"); char* __sanity; - -#if !__DBL_HAS_INFINITY__ - errno = 0; -#endif - - __v = strtod(__s, &__sanity); + __v = strtod_l(__s, &__sanity, (locale_t)__cloc); // _GLIBCXX_RESOLVE_LIB_DEFECTS // 23. Num_get overflow result. @@ -135,132 +82,86 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __v = 0.0; __err = ios_base::failbit; } - else if ( -#if __DBL_HAS_INFINITY__ - __v == numeric_limits::infinity() - || __v == -numeric_limits::infinity()) -#else - (__v > 1.0 || __v < -1.0) && errno == ERANGE) -#endif + else if (__v == numeric_limits::infinity()) { - if (__v > 0.0) - __v = numeric_limits::max(); - else - __v = -numeric_limits::max(); + __v = numeric_limits::max(); + __err = ios_base::failbit; + } + else if (__v == -numeric_limits::infinity()) + { + __v = -numeric_limits::max(); __err = ios_base::failbit; } - - setlocale(LC_ALL, __sav); - delete [] __sav; } template<> void - __convert_to_v(const char* __s, long double& __v, - ios_base::iostate& __err, const __c_locale&) throw() + __convert_to_v(const char* __s, long double& __v, ios_base::iostate& __err, + const __c_locale& __cloc) throw() { - // Assumes __s formatted for "C" locale. - char* __old = setlocale(LC_ALL, 0); - const size_t __len = strlen(__old) + 1; - char* __sav = new char[__len]; - memcpy(__sav, __old, __len); - setlocale(LC_ALL, "C"); - -#if !__LDBL_HAS_INFINITY__ - errno = 0; -#endif - -#if defined(_GLIBCXX_HAVE_STRTOLD) && !defined(_GLIBCXX_HAVE_BROKEN_STRTOLD) char* __sanity; - __v = strtold(__s, &__sanity); + __v = strtold_l(__s, &__sanity, (locale_t)__cloc); // _GLIBCXX_RESOLVE_LIB_DEFECTS // 23. Num_get overflow result. if (__sanity == __s || *__sanity != '\0') -#else - typedef char_traits::int_type int_type; - int __p = sscanf(__s, "%Lf", &__v); - - if (!__p || static_cast(__p) == char_traits::eof()) -#endif { __v = 0.0l; __err = ios_base::failbit; } - else if ( -#if __LDBL_HAS_INFINITY__ - __v == numeric_limits::infinity() - || __v == -numeric_limits::infinity()) -#else - (__v > 1.0l || __v < -1.0l) && errno == ERANGE) -#endif + else if (__v == numeric_limits::infinity()) { - if (__v > 0.0l) - __v = numeric_limits::max(); - else - __v = -numeric_limits::max(); + __v = numeric_limits::max(); + __err = ios_base::failbit; + } + else if (__v == -numeric_limits::infinity()) + { + __v = -numeric_limits::max(); __err = ios_base::failbit; } - - setlocale(LC_ALL, __sav); - delete [] __sav; } - - /* DragonFly's implementation of setlocale won't accept something like - "de_DE". According to nls manpage, the expected format is: - language[_territory][.codeset][@modifier], but it seems that both - the _territory and .codeset components are required. - - As an attempt to correct for this, we'll tack on ".UTF-8" if - a period is not detected in the locale string. - - There are no locales with modifiers on DragonFly so if found, they - will just be stripped off silently. e.g "de_DE@euro" will be reduced - to "de_DE". The UTF-8 default would be added after that. - */ - void locale::facet::_S_create_c_locale(__c_locale& __cloc, const char* __s, - __c_locale) + __c_locale __old) { - const size_t size__s = (__s == NULL) ? 1 : strlen (__s); - const char UTF8[] = ".UTF-8"; - char localspec[size__s + 6 + 1]; - - if (__s == NULL) { - localspec[0] = '\0'; - } else { - strcpy (localspec, __s); - char * pch = strchr (localspec, '@'); - if (pch != NULL) - *pch = 0; - - if ( (strchr (__s, '.') == NULL) - && (strcmp (__s, "C") != 0) - && (strcmp (__s, "POSIX") != 0)) - strncat (localspec, UTF8, 6); - } - - const char * result = std::setlocale(LC_ALL, localspec); - - if ((strcmp(result, "C") != 0) && (strcmp (result, localspec) != 0)) - __throw_runtime_error(__N("locale::facet::_S_create_c_locale " - "name not valid")); - __cloc = 0; + __cloc = (__c_locale)newlocale(LC_ALL_MASK, __s, (locale_t)__old); + if (!__cloc) + { + // This named locale is not supported by the underlying OS. + __throw_runtime_error(__N("locale::facet::_S_create_c_locale " + "name not valid")); + } } void locale::facet::_S_destroy_c_locale(__c_locale& __cloc) - { __cloc = 0; } + { + if (__cloc && _S_get_c_locale() != __cloc) + freelocale((locale_t)__cloc); + } __c_locale - locale::facet::_S_clone_c_locale(__c_locale&) throw() - { return __c_locale(); } + locale::facet::_S_clone_c_locale(__c_locale& __cloc) throw() + { return (__c_locale)duplocale((locale_t)__cloc); } __c_locale - locale::facet::_S_lc_ctype_c_locale(__c_locale, const char*) - { return __c_locale(); } + locale::facet::_S_lc_ctype_c_locale(__c_locale __cloc, const char* __s) + { + __c_locale __dup = (__c_locale)duplocale((locale_t)__cloc); + if (__dup == __c_locale(0)) + __throw_runtime_error(__N("locale::facet::_S_lc_ctype_c_locale " + "duplocale error")); + __c_locale __changed = (__c_locale)newlocale(LC_CTYPE_MASK, __s, + (locale_t)__dup); + if (__changed == __c_locale(0)) + { + freelocale((locale_t)__dup); + __throw_runtime_error(__N("locale::facet::_S_lc_ctype_c_locale " + "newlocale error")); + } + return __changed; + } _GLIBCXX_END_NAMESPACE_VERSION } // namespace @@ -295,5 +196,5 @@ _GLIBCXX_END_NAMESPACE_VERSION #ifdef _GLIBCXX_LONG_DOUBLE_COMPAT #define _GLIBCXX_LDBL_COMPAT(dbl, ldbl) \ extern "C" void ldbl (void) __attribute__ ((alias (#dbl))) -_GLIBCXX_LDBL_COMPAT(_ZSt14__convert_to_vIdEvPKcRT_RSt12_Ios_IostateRKPi, _ZSt14__convert_to_vIeEvPKcRT_RSt12_Ios_IostateRKPi); +_GLIBCXX_LDBL_COMPAT(_ZSt14__convert_to_vIdEvPKcRT_RSt12_Ios_IostateRKP15__locale_struct, _ZSt14__convert_to_vIeEvPKcRT_RSt12_Ios_IostateRKP15__locale_struct); #endif // _GLIBCXX_LONG_DOUBLE_COMPAT diff --git a/libstdc++-v3/config/locale/dragonfly/c_locale.h b/libstdc++-v3/config/locale/dragonfly/c_locale.h new file mode 100644 index 00000000000..5c17cfe10c3 --- /dev/null +++ b/libstdc++-v3/config/locale/dragonfly/c_locale.h @@ -0,0 +1,82 @@ +// localization implementation details, DragonFly version -*- C++ -*- + +// Copyright (C) 2001-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/c++locale.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{locale} + */ + +// +// ISO C++ 14882: 22.8 Standard locale categories. +// + +// Written by Benjamin Kosnik +// Modified for DragonFly by John Marino + +#ifndef _GLIBCXX_CXX_LOCALE_H +#define _GLIBCXX_CXX_LOCALE_H 1 + +#pragma GCC system_header + +#include +#include + +#define _GLIBCXX_NUM_CATEGORIES 0 + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + typedef int* __c_locale; + + // Convert numeric value of type double and long double to string and + // return length of string. If vsnprintf is available use it, otherwise + // fall back to the unsafe vsprintf which, in general, can be dangerous + // and should be avoided. + inline int + __convert_from_v(const __c_locale& __cloc, char* __out, + const int __size __attribute__ ((__unused__)), + const char* __fmt, ...) + { + __c_locale __old = (__c_locale)uselocale((locale_t)__cloc); + + __builtin_va_list __args; + __builtin_va_start(__args, __fmt); + +#ifdef _GLIBCXX_USE_C99 + const int __ret = __builtin_vsnprintf(__out, __size, __fmt, __args); +#else + const int __ret = __builtin_vsprintf(__out, __fmt, __args); +#endif + + __builtin_va_end(__args); + + uselocale((locale_t)__old); + return __ret; + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/libstdc++-v3/config/locale/dragonfly/codecvt_members.cc b/libstdc++-v3/config/locale/dragonfly/codecvt_members.cc new file mode 100644 index 00000000000..9aef8755638 --- /dev/null +++ b/libstdc++-v3/config/locale/dragonfly/codecvt_members.cc @@ -0,0 +1,288 @@ +// std::codecvt implementation details, DragonFly version -*- C++ -*- + +// Copyright (C) 2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +// +// ISO C++ 14882: 22.2.1.5 - Template class codecvt +// + +// Written by Benjamin Kosnik +// Modified for DragonFly by John Marino + +#include +#include +#include // For MB_CUR_MAX +#include // For MB_LEN_MAX + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Specializations. +#ifdef _GLIBCXX_USE_WCHAR_T + codecvt_base::result + codecvt:: + do_out(state_type& __state, const intern_type* __from, + const intern_type* __from_end, const intern_type*& __from_next, + extern_type* __to, extern_type* __to_end, + extern_type*& __to_next) const + { + result __ret = ok; + state_type __tmp_state(__state); + + __c_locale __old = (__c_locale)uselocale((locale_t)_M_c_locale_codecvt); + + // wcsnrtombs is *very* fast but stops if encounters NUL characters: + // in case we fall back to wcrtomb and then continue, in a loop. + // NB: wcsnrtombs is a GNU extension + for (__from_next = __from, __to_next = __to; + __from_next < __from_end && __to_next < __to_end + && __ret == ok;) + { + const intern_type* __from_chunk_end = wmemchr(__from_next, L'\0', + __from_end - __from_next); + if (!__from_chunk_end) + __from_chunk_end = __from_end; + + __from = __from_next; + const size_t __conv = wcsnrtombs(__to_next, &__from_next, + __from_chunk_end - __from_next, + __to_end - __to_next, &__state); + if (__conv == static_cast(-1)) + { + // In case of error, in order to stop at the exact place we + // have to start again from the beginning with a series of + // wcrtomb. + for (; __from < __from_next; ++__from) + __to_next += wcrtomb(__to_next, *__from, &__tmp_state); + __state = __tmp_state; + __ret = error; + } + else if (__from_next && __from_next < __from_chunk_end) + { + __to_next += __conv; + __ret = partial; + } + else + { + __from_next = __from_chunk_end; + __to_next += __conv; + } + + if (__from_next < __from_end && __ret == ok) + { + extern_type __buf[MB_LEN_MAX]; + __tmp_state = __state; + const size_t __conv2 = wcrtomb(__buf, *__from_next, &__tmp_state); + if (__conv2 > static_cast(__to_end - __to_next)) + __ret = partial; + else + { + memcpy(__to_next, __buf, __conv2); + __state = __tmp_state; + __to_next += __conv2; + ++__from_next; + } + } + } + + uselocale((locale_t)__old); + + return __ret; + } + + codecvt_base::result + codecvt:: + do_in(state_type& __state, const extern_type* __from, + const extern_type* __from_end, const extern_type*& __from_next, + intern_type* __to, intern_type* __to_end, + intern_type*& __to_next) const + { + result __ret = ok; + state_type __tmp_state(__state); + + __c_locale __old = (__c_locale)uselocale((locale_t)_M_c_locale_codecvt); + + // mbsnrtowcs is *very* fast but stops if encounters NUL characters: + // in case we store a L'\0' and then continue, in a loop. + // NB: mbsnrtowcs is a GNU extension + for (__from_next = __from, __to_next = __to; + __from_next < __from_end && __to_next < __to_end + && __ret == ok;) + { + const extern_type* __from_chunk_end; + __from_chunk_end = static_cast(memchr(__from_next, '\0', + __from_end + - __from_next)); + if (!__from_chunk_end) + __from_chunk_end = __from_end; + + __from = __from_next; + size_t __conv = mbsnrtowcs(__to_next, &__from_next, + __from_chunk_end - __from_next, + __to_end - __to_next, &__state); + if (__conv == static_cast(-1)) + { + // In case of error, in order to stop at the exact place we + // have to start again from the beginning with a series of + // mbrtowc. + for (;; ++__to_next, __from += __conv) + { + __conv = mbrtowc(__to_next, __from, __from_end - __from, + &__tmp_state); + if (__conv == static_cast(-1) + || __conv == static_cast(-2)) + break; + } + __from_next = __from; + __state = __tmp_state; + __ret = error; + } + else if (__from_next && __from_next < __from_chunk_end) + { + // It is unclear what to return in this case (see DR 382). + __to_next += __conv; + __ret = partial; + } + else + { + __from_next = __from_chunk_end; + __to_next += __conv; + } + + if (__from_next < __from_end && __ret == ok) + { + if (__to_next < __to_end) + { + // XXX Probably wrong for stateful encodings + __tmp_state = __state; + ++__from_next; + *__to_next++ = L'\0'; + } + else + __ret = partial; + } + } + + uselocale((locale_t)__old); + + return __ret; + } + + int + codecvt:: + do_encoding() const throw() + { + // XXX This implementation assumes that the encoding is + // stateless and is either single-byte or variable-width. + int __ret = 0; + __c_locale __old = (__c_locale)uselocale((locale_t)_M_c_locale_codecvt); + if (MB_CUR_MAX == 1) + __ret = 1; + uselocale((locale_t)__old); + return __ret; + } + + int + codecvt:: + do_max_length() const throw() + { + __c_locale __old = (__c_locale)uselocale((locale_t)_M_c_locale_codecvt); + // XXX Probably wrong for stateful encodings. + int __ret = MB_CUR_MAX; + uselocale((locale_t)__old); + return __ret; + } + + int + codecvt:: + do_length(state_type& __state, const extern_type* __from, + const extern_type* __end, size_t __max) const + { + int __ret = 0; + state_type __tmp_state(__state); + + __c_locale __old = (__c_locale)uselocale((locale_t)_M_c_locale_codecvt); + + // mbsnrtowcs is *very* fast but stops if encounters NUL characters: + // in case we advance past it and then continue, in a loop. + // NB: mbsnrtowcs is a GNU extension + + // A dummy internal buffer is needed in order for mbsnrtocws to consider + // its fourth parameter (it wouldn't with NULL as first parameter). + wchar_t* __to = static_cast(__builtin_alloca(sizeof(wchar_t) + * __max)); + while (__from < __end && __max) + { + const extern_type* __from_chunk_end; + __from_chunk_end = static_cast(memchr(__from, '\0', + __end + - __from)); + if (!__from_chunk_end) + __from_chunk_end = __end; + + const extern_type* __tmp_from = __from; + size_t __conv = mbsnrtowcs(__to, &__from, + __from_chunk_end - __from, + __max, &__state); + if (__conv == static_cast(-1)) + { + // In case of error, in order to stop at the exact place we + // have to start again from the beginning with a series of + // mbrtowc. + for (__from = __tmp_from;; __from += __conv) + { + __conv = mbrtowc(0, __from, __end - __from, + &__tmp_state); + if (__conv == static_cast(-1) + || __conv == static_cast(-2)) + break; + } + __state = __tmp_state; + __ret += __from - __tmp_from; + break; + } + if (!__from) + __from = __from_chunk_end; + + __ret += __from - __tmp_from; + __max -= __conv; + + if (__from < __end && __max) + { + // XXX Probably wrong for stateful encodings + __tmp_state = __state; + ++__from; + ++__ret; + --__max; + } + } + + uselocale((locale_t)__old); + + return __ret; + } +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace diff --git a/libstdc++-v3/config/locale/dragonfly/collate_members.cc b/libstdc++-v3/config/locale/dragonfly/collate_members.cc new file mode 100644 index 00000000000..7cd6c5baf19 --- /dev/null +++ b/libstdc++-v3/config/locale/dragonfly/collate_members.cc @@ -0,0 +1,74 @@ +// std::collate implementation details, DragonFly version -*- C++ -*- + +// Copyright (C) 2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +// +// ISO C++ 14882: 22.2.4.1.2 collate virtual functions +// + +// Written by Benjamin Kosnik +// Modified for DragonFly by John Marino + +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // These are basically extensions to char_traits, and perhaps should + // be put there instead of here. + template<> + int + collate::_M_compare(const char* __one, + const char* __two) const throw() + { + int __cmp = strcoll_l(__one, __two, (locale_t)_M_c_locale_collate); + return (__cmp >> (8 * sizeof (int) - 2)) | (__cmp != 0); + } + + template<> + size_t + collate::_M_transform(char* __to, const char* __from, + size_t __n) const throw() + { return strxfrm_l(__to, __from, __n, (locale_t)_M_c_locale_collate); } + +#ifdef _GLIBCXX_USE_WCHAR_T + template<> + int + collate::_M_compare(const wchar_t* __one, + const wchar_t* __two) const throw() + { + int __cmp = wcscoll_l(__one, __two, (locale_t)_M_c_locale_collate); + return (__cmp >> (8 * sizeof (int) - 2)) | (__cmp != 0); + } + + template<> + size_t + collate::_M_transform(wchar_t* __to, const wchar_t* __from, + size_t __n) const throw() + { return wcsxfrm_l(__to, __from, __n, (locale_t)_M_c_locale_collate); } +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace diff --git a/libstdc++-v3/config/locale/dragonfly/ctype_members.cc b/libstdc++-v3/config/locale/dragonfly/ctype_members.cc index a44b6170c7b..7b6b34f23a6 100644 --- a/libstdc++-v3/config/locale/dragonfly/ctype_members.cc +++ b/libstdc++-v3/config/locale/dragonfly/ctype_members.cc @@ -1,4 +1,4 @@ -// std::ctype implementation details, GNU version -*- C++ -*- +// std::ctype implementation details, DragonFly version -*- C++ -*- // Copyright (C) 2014-2015 Free Software Foundation, Inc. // @@ -27,18 +27,22 @@ // // Written by Benjamin Kosnik +// Modified for DragonFly by John Marino #include -#include -#include #include #include +#ifndef _ISbit +#define _ISbit(bit) ((bit) < 8 ? ((1 << (bit)) << 8) : ((1 << (bit)) >> 8)) +#endif + namespace std _GLIBCXX_VISIBILITY(default) { +_GLIBCXX_BEGIN_NAMESPACE_VERSION + // NB: The other ctype specializations are in src/locale.cc and // various /config/os/* files. - ctype_byname::ctype_byname(const char* __s, size_t __refs) : ctype(0, false, __refs) { @@ -54,24 +58,63 @@ namespace std _GLIBCXX_VISIBILITY(default) #ifdef _GLIBCXX_USE_WCHAR_T ctype::__wmask_type - ctype::_M_convert_to_wmask( - const mask __attribute__((__unused__)) __m) const throw() + ctype::_M_convert_to_wmask(const mask __m) const throw() { - // DragonFly uses the same codes for 'char' as 'wchar_t', so this routine - // never gets called. - return __wmask_type(); - }; + __wmask_type __ret; + switch (__m) + { + case space: + __ret = wctype_l("space", (locale_t)_M_c_locale_ctype); + break; + case print: + __ret = wctype_l("print", (locale_t)_M_c_locale_ctype); + break; + case cntrl: + __ret = wctype_l("cntrl", (locale_t)_M_c_locale_ctype); + break; + case upper: + __ret = wctype_l("upper", (locale_t)_M_c_locale_ctype); + break; + case lower: + __ret = wctype_l("lower", (locale_t)_M_c_locale_ctype); + break; + case alpha: + __ret = wctype_l("alpha", (locale_t)_M_c_locale_ctype); + break; + case digit: + __ret = wctype_l("digit", (locale_t)_M_c_locale_ctype); + break; + case punct: + __ret = wctype_l("punct", (locale_t)_M_c_locale_ctype); + break; + case xdigit: + __ret = wctype_l("xdigit", (locale_t)_M_c_locale_ctype); + break; + case alnum: + __ret = wctype_l("alnum", (locale_t)_M_c_locale_ctype); + break; + case graph: + __ret = wctype_l("graph", (locale_t)_M_c_locale_ctype); + break; + case blank: + __ret = wctype_l("blank", (locale_t)_M_c_locale_ctype); + break; + default: + __ret = __wmask_type(); + } + return __ret; + } wchar_t ctype::do_toupper(wchar_t __c) const - { return towupper(__c); } + { return towupper_l(__c, (locale_t)_M_c_locale_ctype); } const wchar_t* ctype::do_toupper(wchar_t* __lo, const wchar_t* __hi) const { while (__lo < __hi) { - *__lo = towupper(*__lo); + *__lo = towupper_l(*__lo, (locale_t)_M_c_locale_ctype); ++__lo; } return __hi; @@ -79,14 +122,14 @@ namespace std _GLIBCXX_VISIBILITY(default) wchar_t ctype::do_tolower(wchar_t __c) const - { return towlower(__c); } + { return towlower_l(__c, (locale_t)_M_c_locale_ctype); } const wchar_t* ctype::do_tolower(wchar_t* __lo, const wchar_t* __hi) const { while (__lo < __hi) { - *__lo = towlower(*__lo); + *__lo = towlower_l(*__lo, (locale_t)_M_c_locale_ctype); ++__lo; } return __hi; @@ -113,10 +156,12 @@ namespace std _GLIBCXX_VISIBILITY(default) char ctype:: do_narrow(wchar_t __wc, char __dfault) const - { + { if (__wc >= 0 && __wc < 128 && _M_narrow_ok) return _M_narrow[__wc]; + __c_locale __old = (__c_locale)uselocale((locale_t)_M_c_locale_ctype); const int __c = wctob(__wc); + uselocale((locale_t)__old); return (__c == EOF ? __dfault : static_cast(__c)); } @@ -125,6 +170,7 @@ namespace std _GLIBCXX_VISIBILITY(default) do_narrow(const wchar_t* __lo, const wchar_t* __hi, char __dfault, char* __dest) const { + __c_locale __old = (__c_locale)uselocale((locale_t)_M_c_locale_ctype); if (_M_narrow_ok) while (__lo < __hi) { @@ -146,12 +192,14 @@ namespace std _GLIBCXX_VISIBILITY(default) ++__lo; ++__dest; } + uselocale((locale_t)__old); return __hi; } void ctype::_M_initialize_ctype() throw() { + __c_locale __old = (__c_locale)uselocale((locale_t)_M_c_locale_ctype); wint_t __i; for (__i = 0; __i < 128; ++__i) { @@ -165,9 +213,18 @@ namespace std _GLIBCXX_VISIBILITY(default) _M_narrow_ok = true; else _M_narrow_ok = false; - for (size_t __i = 0; - __i < sizeof(_M_widen) / sizeof(wint_t); ++__i) - _M_widen[__i] = btowc(__i); + for (size_t __j = 0; + __j < sizeof(_M_widen) / sizeof(wint_t); ++__j) + _M_widen[__j] = btowc(__j); + + for (size_t __k = 0; __k <= 11; ++__k) + { + _M_bit[__k] = static_cast(_ISbit(__k)); + _M_wmask[__k] = _M_convert_to_wmask(_M_bit[__k]); + } + uselocale((locale_t)__old); } #endif // _GLIBCXX_USE_WCHAR_T -} + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace diff --git a/libstdc++-v3/config/locale/dragonfly/monetary_members.cc b/libstdc++-v3/config/locale/dragonfly/monetary_members.cc new file mode 100644 index 00000000000..5c07c7335b7 --- /dev/null +++ b/libstdc++-v3/config/locale/dragonfly/monetary_members.cc @@ -0,0 +1,903 @@ +// std::moneypunct implementation details, DragonFly version -*- C++ -*- + +// Copyright (C) 2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +// +// ISO C++ 14882: 22.2.6.3.2 moneypunct virtual functions +// + +// Written by Benjamin Kosnik +// Modified for DragonFly by John Marino + +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +// This file might be compiled twice, but we only want to define the members +// of money_base once. +#if ! _GLIBCXX_USE_CXX11_ABI + + // Construct and return valid pattern consisting of some combination of: + // space none symbol sign value + money_base::pattern + money_base::_S_construct_pattern(char __precedes, char __space, + char __posn) throw() + { + pattern __ret; + + // This insanely complicated routine attempts to construct a valid + // pattern for use with moneypunct. A couple of invariants: + + // if (__precedes) symbol -> value + // else value -> symbol + + // if (__space) space + // else none + + // none == never first + // space never first or last + + // Any elegant implementations of this are welcome. + switch (__posn) + { + case 0: + case 1: + // 1 The sign precedes the value and symbol. + __ret.field[0] = sign; + if (__space) + { + // Pattern starts with sign. + if (__precedes) + { + __ret.field[1] = symbol; + __ret.field[3] = value; + } + else + { + __ret.field[1] = value; + __ret.field[3] = symbol; + } + __ret.field[2] = space; + } + else + { + // Pattern starts with sign and ends with none. + if (__precedes) + { + __ret.field[1] = symbol; + __ret.field[2] = value; + } + else + { + __ret.field[1] = value; + __ret.field[2] = symbol; + } + __ret.field[3] = none; + } + break; + case 2: + // 2 The sign follows the value and symbol. + if (__space) + { + // Pattern either ends with sign. + if (__precedes) + { + __ret.field[0] = symbol; + __ret.field[2] = value; + } + else + { + __ret.field[0] = value; + __ret.field[2] = symbol; + } + __ret.field[1] = space; + __ret.field[3] = sign; + } + else + { + // Pattern ends with sign then none. + if (__precedes) + { + __ret.field[0] = symbol; + __ret.field[1] = value; + } + else + { + __ret.field[0] = value; + __ret.field[1] = symbol; + } + __ret.field[2] = sign; + __ret.field[3] = none; + } + break; + case 3: + // 3 The sign immediately precedes the symbol. + if (__precedes) + { + __ret.field[0] = sign; + __ret.field[1] = symbol; + if (__space) + { + __ret.field[2] = space; + __ret.field[3] = value; + } + else + { + __ret.field[2] = value; + __ret.field[3] = none; + } + } + else + { + __ret.field[0] = value; + if (__space) + { + __ret.field[1] = space; + __ret.field[2] = sign; + __ret.field[3] = symbol; + } + else + { + __ret.field[1] = sign; + __ret.field[2] = symbol; + __ret.field[3] = none; + } + } + break; + case 4: + // 4 The sign immediately follows the symbol. + if (__precedes) + { + __ret.field[0] = symbol; + __ret.field[1] = sign; + if (__space) + { + __ret.field[2] = space; + __ret.field[3] = value; + } + else + { + __ret.field[2] = value; + __ret.field[3] = none; + } + } + else + { + __ret.field[0] = value; + if (__space) + { + __ret.field[1] = space; + __ret.field[2] = symbol; + __ret.field[3] = sign; + } + else + { + __ret.field[1] = symbol; + __ret.field[2] = sign; + __ret.field[3] = none; + } + } + break; + default: + __ret = pattern(); + } + return __ret; + } +#endif + + template<> + void + moneypunct::_M_initialize_moneypunct(__c_locale __cloc, + const char*) + { + if (!_M_data) + _M_data = new __moneypunct_cache; + + if (!__cloc) + { + // "C" locale + _M_data->_M_decimal_point = '.'; + _M_data->_M_thousands_sep = ','; + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_curr_symbol = ""; + _M_data->_M_curr_symbol_size = 0; + _M_data->_M_positive_sign = ""; + _M_data->_M_positive_sign_size = 0; + _M_data->_M_negative_sign = ""; + _M_data->_M_negative_sign_size = 0; + _M_data->_M_frac_digits = 0; + _M_data->_M_pos_format = money_base::_S_default_pattern; + _M_data->_M_neg_format = money_base::_S_default_pattern; + + for (size_t __i = 0; __i < money_base::_S_end; ++__i) + _M_data->_M_atoms[__i] = money_base::_S_atoms[__i]; + } + else + { + // Named locale. + lconv* lc = localeconv_l((locale_t) __cloc); + + // Check for NULL, which implies no fractional digits. + if (lc->mon_decimal_point == NULL || + lc->mon_decimal_point[0] == '\0') + { + // Like in "C" locale. + _M_data->_M_frac_digits = 0; + _M_data->_M_decimal_point = '.'; + } + else + { + _M_data->_M_decimal_point = lc->mon_decimal_point[0]; + _M_data->_M_frac_digits = lc->int_frac_digits; + } + + const char* __cgroup = lc->mon_grouping; + const char* __cpossign = lc->positive_sign; + const char* __cnegsign = lc->negative_sign; + // _Intl == true + const char* __ccurr = lc->int_curr_symbol; + + char* __group = 0; + char* __ps = 0; + char* __ns = 0; + const char __nposn = lc->int_n_sign_posn; + __try + { + size_t __len; + + // Check for NULL, which implies no grouping. + if (lc->mon_thousands_sep == NULL || + lc->mon_thousands_sep[0] == '\0') + { + // Like in "C" locale. + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_thousands_sep = ','; + } + else + { + _M_data->_M_thousands_sep = lc->mon_thousands_sep[0]; + + __len = strlen(__cgroup); + if (__len) + { + __group = new char[__len + 1]; + memcpy(__group, __cgroup, __len + 1); + _M_data->_M_grouping = __group; + } + else + { + _M_data->_M_grouping = ""; + _M_data->_M_use_grouping = false; + } + _M_data->_M_grouping_size = __len; + } + + __len = strlen(__cpossign); + if (__len) + { + __ps = new char[__len + 1]; + memcpy(__ps, __cpossign, __len + 1); + _M_data->_M_positive_sign = __ps; + } + else + _M_data->_M_positive_sign = ""; + _M_data->_M_positive_sign_size = __len; + + if (!__nposn) + { + _M_data->_M_negative_sign = "()"; + _M_data->_M_negative_sign_size = 2; + } + else + { + __len = strlen(__cnegsign); + if (__len) + { + __ns = new char[__len + 1]; + memcpy(__ns, __cnegsign, __len + 1); + _M_data->_M_negative_sign = __ns; + } + else + _M_data->_M_negative_sign = ""; + _M_data->_M_negative_sign_size = __len; + } + + __len = strlen(__ccurr); + if (__len) + { + char* __curr = new char[__len + 1]; + memcpy(__curr, __ccurr, __len + 1); + _M_data->_M_curr_symbol = __curr; + } + else + _M_data->_M_curr_symbol = ""; + _M_data->_M_curr_symbol_size = __len; + } + __catch(...) + { + delete _M_data; + _M_data = 0; + delete [] __group; + delete [] __ps; + delete [] __ns; + __throw_exception_again; + } + + char __pprecedes = lc->int_p_cs_precedes; + char __pspace = lc->int_p_sep_by_space; + char __pposn = lc->int_p_sign_posn; + _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, + __pposn); + char __nprecedes = lc->int_n_cs_precedes; + char __nspace = lc->int_n_sep_by_space; + _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, + __nposn); + } + } + + template<> + void + moneypunct::_M_initialize_moneypunct(__c_locale __cloc, + const char*) + { + if (!_M_data) + _M_data = new __moneypunct_cache; + + if (!__cloc) + { + // "C" locale + _M_data->_M_decimal_point = '.'; + _M_data->_M_thousands_sep = ','; + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_curr_symbol = ""; + _M_data->_M_curr_symbol_size = 0; + _M_data->_M_positive_sign = ""; + _M_data->_M_positive_sign_size = 0; + _M_data->_M_negative_sign = ""; + _M_data->_M_negative_sign_size = 0; + _M_data->_M_frac_digits = 0; + _M_data->_M_pos_format = money_base::_S_default_pattern; + _M_data->_M_neg_format = money_base::_S_default_pattern; + + for (size_t __i = 0; __i < money_base::_S_end; ++__i) + _M_data->_M_atoms[__i] = money_base::_S_atoms[__i]; + } + else + { + // Named locale. + lconv* lc = localeconv_l((locale_t) __cloc); + + // Check for NULL, which implies no fractional digits. + if (lc->mon_decimal_point == NULL || + lc->mon_decimal_point[0] == '\0') + { + // Like in "C" locale. + _M_data->_M_frac_digits = 0; + _M_data->_M_decimal_point = '.'; + } + else + { + _M_data->_M_decimal_point = lc->mon_decimal_point[0]; + _M_data->_M_frac_digits = lc->frac_digits; + } + + const char* __cgroup = lc->mon_grouping; + const char* __cpossign = lc->positive_sign; + const char* __cnegsign = lc->negative_sign; + // _Intl == false + const char* __ccurr = lc->currency_symbol; + + char* __group = 0; + char* __ps = 0; + char* __ns = 0; + const char __nposn = lc->n_sign_posn; + __try + { + size_t __len; + + // Check for NULL, which implies no grouping. + if (lc->mon_thousands_sep == NULL || + lc->mon_thousands_sep[0] == '\0') + { + // Like in "C" locale. + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_thousands_sep = ','; + } + else + { + _M_data->_M_thousands_sep = lc->mon_thousands_sep[0]; + + __len = strlen(__cgroup); + if (__len) + { + __group = new char[__len + 1]; + memcpy(__group, __cgroup, __len + 1); + _M_data->_M_grouping = __group; + } + else + { + _M_data->_M_grouping = ""; + _M_data->_M_use_grouping = false; + } + _M_data->_M_grouping_size = __len; + } + + __len = strlen(__cpossign); + if (__len) + { + __ps = new char[__len + 1]; + memcpy(__ps, __cpossign, __len + 1); + _M_data->_M_positive_sign = __ps; + } + else + _M_data->_M_positive_sign = ""; + _M_data->_M_positive_sign_size = __len; + + if (!__nposn) + { + _M_data->_M_negative_sign = "()"; + _M_data->_M_negative_sign_size = 2; + } + else + { + __len = strlen(__cnegsign); + if (__len) + { + __ns = new char[__len + 1]; + memcpy(__ns, __cnegsign, __len + 1); + _M_data->_M_negative_sign = __ns; + } + else + _M_data->_M_negative_sign = ""; + _M_data->_M_negative_sign_size = __len; + } + + __len = strlen(__ccurr); + if (__len) + { + char* __curr = new char[__len + 1]; + memcpy(__curr, __ccurr, __len + 1); + _M_data->_M_curr_symbol = __curr; + } + else + _M_data->_M_curr_symbol = ""; + _M_data->_M_curr_symbol_size = __len; + } + __catch(...) + { + delete _M_data; + _M_data = 0; + delete [] __group; + delete [] __ps; + delete [] __ns; + __throw_exception_again; + } + + char __pprecedes = lc->p_cs_precedes; + char __pspace = lc->p_sep_by_space; + char __pposn = lc->p_sign_posn; + _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, + __pposn); + char __nprecedes = lc->n_cs_precedes; + char __nspace = lc->n_sep_by_space; + _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, + __nposn); + } + } + + template<> + moneypunct::~moneypunct() + { + if (_M_data->_M_grouping_size) + delete [] _M_data->_M_grouping; + if (_M_data->_M_positive_sign_size) + delete [] _M_data->_M_positive_sign; + if (_M_data->_M_negative_sign_size + && strcmp(_M_data->_M_negative_sign, "()") != 0) + delete [] _M_data->_M_negative_sign; + if (_M_data->_M_curr_symbol_size) + delete [] _M_data->_M_curr_symbol; + delete _M_data; + } + + template<> + moneypunct::~moneypunct() + { + if (_M_data->_M_grouping_size) + delete [] _M_data->_M_grouping; + if (_M_data->_M_positive_sign_size) + delete [] _M_data->_M_positive_sign; + if (_M_data->_M_negative_sign_size + && strcmp(_M_data->_M_negative_sign, "()") != 0) + delete [] _M_data->_M_negative_sign; + if (_M_data->_M_curr_symbol_size) + delete [] _M_data->_M_curr_symbol; + delete _M_data; + } + +#ifdef _GLIBCXX_USE_WCHAR_T + template<> + void + moneypunct::_M_initialize_moneypunct(__c_locale __cloc, + const char*) + { + if (!_M_data) + _M_data = new __moneypunct_cache; + + if (!__cloc) + { + // "C" locale + _M_data->_M_decimal_point = L'.'; + _M_data->_M_thousands_sep = L','; + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_curr_symbol = L""; + _M_data->_M_curr_symbol_size = 0; + _M_data->_M_positive_sign = L""; + _M_data->_M_positive_sign_size = 0; + _M_data->_M_negative_sign = L""; + _M_data->_M_negative_sign_size = 0; + _M_data->_M_frac_digits = 0; + _M_data->_M_pos_format = money_base::_S_default_pattern; + _M_data->_M_neg_format = money_base::_S_default_pattern; + + // Use ctype::widen code without the facet... + for (size_t __i = 0; __i < money_base::_S_end; ++__i) + _M_data->_M_atoms[__i] = + static_cast(money_base::_S_atoms[__i]); + } + else + { + __c_locale __old = (__c_locale)uselocale((locale_t)__cloc); + // Named locale. + lconv* lc = localeconv_l((locale_t) __cloc); + + // Check for NULL, which implies no fractional digits. + if (lc->mon_decimal_point == NULL || + lc->mon_decimal_point[0] == '\0') + { + // Like in "C" locale. + _M_data->_M_frac_digits = 0; + _M_data->_M_decimal_point = L'.'; + } + else + { + _M_data->_M_frac_digits = lc->int_frac_digits; + _M_data->_M_decimal_point = (wchar_t)lc->mon_decimal_point[0]; + } + + const char* __cgroup = lc->mon_grouping; + const char* __cpossign = lc->positive_sign; + const char* __cnegsign = lc->negative_sign; + const char* __ccurr = lc->int_curr_symbol; + + char* __group = 0; + wchar_t* __wcs_ps = 0; + wchar_t* __wcs_ns = 0; + const char __nposn = lc->int_n_sign_posn; + __try + { + size_t __len; + + // Check for NULL, which implies no grouping. + if (lc->mon_thousands_sep == NULL || + lc->mon_thousands_sep[0] == '\0') + { + // Like in "C" locale. + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_thousands_sep = L','; + } + else + { + _M_data->_M_thousands_sep = + (wchar_t)lc->mon_thousands_sep[0]; + __len = strlen(__cgroup); + if (__len) + { + __group = new char[__len + 1]; + memcpy(__group, __cgroup, __len + 1); + _M_data->_M_grouping = __group; + } + else + { + _M_data->_M_grouping = ""; + _M_data->_M_use_grouping = false; + } + _M_data->_M_grouping_size = __len; + } + + mbstate_t __state; + __len = strlen(__cpossign); + if (__len) + { + memset(&__state, 0, sizeof(mbstate_t)); + __wcs_ps = new wchar_t[__len + 1]; + mbsrtowcs(__wcs_ps, &__cpossign, __len + 1, &__state); + _M_data->_M_positive_sign = __wcs_ps; + } + else + _M_data->_M_positive_sign = L""; + _M_data->_M_positive_sign_size = + wcslen(_M_data->_M_positive_sign); + + __len = strlen(__cnegsign); + if (!__nposn) + _M_data->_M_negative_sign = L"()"; + else if (__len) + { + memset(&__state, 0, sizeof(mbstate_t)); + __wcs_ns = new wchar_t[__len + 1]; + mbsrtowcs(__wcs_ns, &__cnegsign, __len + 1, &__state); + _M_data->_M_negative_sign = __wcs_ns; + } + else + _M_data->_M_negative_sign = L""; + _M_data->_M_negative_sign_size = + wcslen(_M_data->_M_negative_sign); + + // _Intl == true. + __len = strlen(__ccurr); + if (__len) + { + memset(&__state, 0, sizeof(mbstate_t)); + wchar_t* __wcs = new wchar_t[__len + 1]; + mbsrtowcs(__wcs, &__ccurr, __len + 1, &__state); + _M_data->_M_curr_symbol = __wcs; + } + else + _M_data->_M_curr_symbol = L""; + _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol); + } + __catch(...) + { + delete _M_data; + _M_data = 0; + delete [] __group; + delete [] __wcs_ps; + delete [] __wcs_ns; + uselocale((locale_t)__old); + __throw_exception_again; + } + + char __pprecedes = lc->int_p_cs_precedes; + char __pspace = lc->int_p_sep_by_space; + char __pposn = lc->int_p_sign_posn; + _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, + __pposn); + char __nprecedes = lc->int_n_cs_precedes; + char __nspace = lc->int_n_sep_by_space; + _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, + __nposn); + + uselocale((locale_t)__old); + } + } + + template<> + void + moneypunct::_M_initialize_moneypunct(__c_locale __cloc, + const char*) + { + if (!_M_data) + _M_data = new __moneypunct_cache; + + if (!__cloc) + { + // "C" locale + _M_data->_M_decimal_point = L'.'; + _M_data->_M_thousands_sep = L','; + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_curr_symbol = L""; + _M_data->_M_curr_symbol_size = 0; + _M_data->_M_positive_sign = L""; + _M_data->_M_positive_sign_size = 0; + _M_data->_M_negative_sign = L""; + _M_data->_M_negative_sign_size = 0; + _M_data->_M_frac_digits = 0; + _M_data->_M_pos_format = money_base::_S_default_pattern; + _M_data->_M_neg_format = money_base::_S_default_pattern; + + // Use ctype::widen code without the facet... + for (size_t __i = 0; __i < money_base::_S_end; ++__i) + _M_data->_M_atoms[__i] = + static_cast(money_base::_S_atoms[__i]); + } + else + { + __c_locale __old = (__c_locale)uselocale((locale_t)__cloc); + // Named locale. + lconv* lc = localeconv_l((locale_t) __cloc); + + // Check for NULL, which implies no fractional digits. + if (lc->mon_decimal_point == NULL || + lc->mon_decimal_point[0] == '\0') + { + // Like in "C" locale. + _M_data->_M_frac_digits = 0; + _M_data->_M_decimal_point = L'.'; + } + else + { + _M_data->_M_frac_digits = lc->frac_digits; + _M_data->_M_decimal_point = (wchar_t)lc->mon_decimal_point[0]; + } + + const char* __cgroup = lc->mon_grouping; + const char* __cpossign = lc->positive_sign; + const char* __cnegsign = lc->negative_sign; + const char* __ccurr = lc->currency_symbol; + + char* __group = 0; + wchar_t* __wcs_ps = 0; + wchar_t* __wcs_ns = 0; + const char __nposn = lc->n_sign_posn; + __try + { + size_t __len; + + // Check for NULL, which implies no grouping. + if (lc->mon_thousands_sep == NULL || + lc->mon_thousands_sep[0] == '\0') + { + // Like in "C" locale. + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_thousands_sep = L','; + } + else + { + _M_data->_M_thousands_sep = + (wchar_t)lc->mon_thousands_sep[0]; + __len = strlen(__cgroup); + if (__len) + { + __group = new char[__len + 1]; + memcpy(__group, __cgroup, __len + 1); + _M_data->_M_grouping = __group; + } + else + { + _M_data->_M_grouping = ""; + _M_data->_M_use_grouping = false; + } + _M_data->_M_grouping_size = __len; + } + + mbstate_t __state; + __len = strlen(__cpossign); + if (__len) + { + memset(&__state, 0, sizeof(mbstate_t)); + __wcs_ps = new wchar_t[__len + 1]; + mbsrtowcs(__wcs_ps, &__cpossign, __len + 1, &__state); + _M_data->_M_positive_sign = __wcs_ps; + } + else + _M_data->_M_positive_sign = L""; + _M_data->_M_positive_sign_size = + wcslen(_M_data->_M_positive_sign); + + __len = strlen(__cnegsign); + if (!__nposn) + _M_data->_M_negative_sign = L"()"; + else if (__len) + { + memset(&__state, 0, sizeof(mbstate_t)); + __wcs_ns = new wchar_t[__len + 1]; + mbsrtowcs(__wcs_ns, &__cnegsign, __len + 1, &__state); + _M_data->_M_negative_sign = __wcs_ns; + } + else + _M_data->_M_negative_sign = L""; + _M_data->_M_negative_sign_size = + wcslen(_M_data->_M_negative_sign); + + // _Intl == true. + __len = strlen(__ccurr); + if (__len) + { + memset(&__state, 0, sizeof(mbstate_t)); + wchar_t* __wcs = new wchar_t[__len + 1]; + mbsrtowcs(__wcs, &__ccurr, __len + 1, &__state); + _M_data->_M_curr_symbol = __wcs; + } + else + _M_data->_M_curr_symbol = L""; + _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol); + } + __catch(...) + { + delete _M_data; + _M_data = 0; + delete [] __group; + delete [] __wcs_ps; + delete [] __wcs_ns; + uselocale((locale_t)__old); + __throw_exception_again; + } + + char __pprecedes = lc->p_cs_precedes; + char __pspace = lc->p_sep_by_space; + char __pposn = lc->p_sign_posn; + _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, + __pposn); + char __nprecedes = lc->n_cs_precedes; + char __nspace = lc->n_sep_by_space; + _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, + __nposn); + + uselocale((locale_t)__old); + } + } + + template<> + moneypunct::~moneypunct() + { + if (_M_data->_M_grouping_size) + delete [] _M_data->_M_grouping; + if (_M_data->_M_positive_sign_size) + delete [] _M_data->_M_positive_sign; + if (_M_data->_M_negative_sign_size + && wcscmp(_M_data->_M_negative_sign, L"()") != 0) + delete [] _M_data->_M_negative_sign; + if (_M_data->_M_curr_symbol_size) + delete [] _M_data->_M_curr_symbol; + delete _M_data; + } + + template<> + moneypunct::~moneypunct() + { + if (_M_data->_M_grouping_size) + delete [] _M_data->_M_grouping; + if (_M_data->_M_positive_sign_size) + delete [] _M_data->_M_positive_sign; + if (_M_data->_M_negative_sign_size + && wcscmp(_M_data->_M_negative_sign, L"()") != 0) + delete [] _M_data->_M_negative_sign; + if (_M_data->_M_curr_symbol_size) + delete [] _M_data->_M_curr_symbol; + delete _M_data; + } +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace diff --git a/libstdc++-v3/config/locale/dragonfly/numeric_members.cc b/libstdc++-v3/config/locale/dragonfly/numeric_members.cc new file mode 100644 index 00000000000..ba44045cd70 --- /dev/null +++ b/libstdc++-v3/config/locale/dragonfly/numeric_members.cc @@ -0,0 +1,235 @@ +// std::numpunct implementation details, DragonFly version -*- C++ -*- + +// Copyright (C) 2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +// +// ISO C++ 14882: 22.2.3.1.2 numpunct virtual functions +// + +// Written by Benjamin Kosnik +// Modified for DragonFly by John Marino + +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template<> + void + numpunct::_M_initialize_numpunct(__c_locale __cloc) + { + if (!_M_data) + _M_data = new __numpunct_cache; + + if (!__cloc) + { + // "C" locale + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + + _M_data->_M_decimal_point = '.'; + _M_data->_M_thousands_sep = ','; + + for (size_t __i = 0; __i < __num_base::_S_oend; ++__i) + _M_data->_M_atoms_out[__i] = __num_base::_S_atoms_out[__i]; + + for (size_t __j = 0; __j < __num_base::_S_iend; ++__j) + _M_data->_M_atoms_in[__j] = __num_base::_S_atoms_in[__j]; + } + else + { + // Named locale. + lconv* lc = localeconv_l((locale_t) __cloc); + + // Decimal point should always be defined, but check null anyway + if (lc->decimal_point == NULL) + { + // Not defined, so use "C" locale default + _M_data->_M_decimal_point = '.'; + } + else + { + _M_data->_M_decimal_point = lc->decimal_point[0]; + } + // Check for NULL, which implies no grouping. + if (lc->thousands_sep == NULL || lc->thousands_sep[0] == '\0') + { + // Like in "C" locale. + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_thousands_sep = ','; + } + else + { + _M_data->_M_thousands_sep = lc->thousands_sep[0]; + + const char* __src = lc->grouping; + const size_t __len = strlen(__src); + if (__len) + { + __try + { + char* __dst = new char[__len + 1]; + memcpy(__dst, __src, __len + 1); + _M_data->_M_grouping = __dst; + _M_data->_M_use_grouping = true; + } + __catch(...) + { + delete _M_data; + _M_data = 0; + __throw_exception_again; + } + } + else + { + _M_data->_M_grouping = ""; + _M_data->_M_use_grouping = false; + } + _M_data->_M_grouping_size = __len; + } + } + + // NB: There is no way to extact this info from posix locales. + // _M_truename = __nl_langinfo_l(YESSTR, __cloc); + _M_data->_M_truename = "true"; + _M_data->_M_truename_size = 4; + // _M_falsename = __nl_langinfo_l(NOSTR, __cloc); + _M_data->_M_falsename = "false"; + _M_data->_M_falsename_size = 5; + } + + template<> + numpunct::~numpunct() + { + if (_M_data->_M_grouping_size) + delete [] _M_data->_M_grouping; + delete _M_data; + } + +#ifdef _GLIBCXX_USE_WCHAR_T + template<> + void + numpunct::_M_initialize_numpunct(__c_locale __cloc) + { + if (!_M_data) + _M_data = new __numpunct_cache; + + if (!__cloc) + { + // "C" locale + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + + _M_data->_M_decimal_point = L'.'; + _M_data->_M_thousands_sep = L','; + + // Use ctype::widen code without the facet... + for (size_t __i = 0; __i < __num_base::_S_oend; ++__i) + _M_data->_M_atoms_out[__i] = + static_cast(__num_base::_S_atoms_out[__i]); + + for (size_t __j = 0; __j < __num_base::_S_iend; ++__j) + _M_data->_M_atoms_in[__j] = + static_cast(__num_base::_S_atoms_in[__j]); + } + else + { + // Named locale. + lconv* lc = localeconv_l((locale_t) __cloc); + + // Decimal point should always be defined, but check null anyway + if (lc->decimal_point == NULL) + { + // Not defined, so use "C" locale default + _M_data->_M_decimal_point = L'.'; + } + else + { + _M_data->_M_decimal_point = (wchar_t)lc->decimal_point[0]; + } + // Check for NULL, which implies no grouping. + if (lc->thousands_sep == NULL || lc->thousands_sep[0] == '\0') + { + // Like in "C" locale. + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_thousands_sep = L','; + } + else + { + _M_data->_M_thousands_sep = (wchar_t)lc->thousands_sep[0]; + + const char* __src = lc->grouping; + const size_t __len = strlen(__src); + if (__len) + { + __try + { + char* __dst = new char[__len + 1]; + memcpy(__dst, __src, __len + 1); + _M_data->_M_grouping = __dst; + } + __catch(...) + { + delete _M_data; + _M_data = 0; + __throw_exception_again; + } + } + else + { + _M_data->_M_grouping = ""; + _M_data->_M_use_grouping = false; + } + _M_data->_M_grouping_size = __len; + } + } + + // NB: There is no way to extact this info from posix locales. + // _M_truename = __nl_langinfo_l(YESSTR, __cloc); + _M_data->_M_truename = L"true"; + _M_data->_M_truename_size = 4; + // _M_falsename = __nl_langinfo_l(NOSTR, __cloc); + _M_data->_M_falsename = L"false"; + _M_data->_M_falsename_size = 5; + } + + template<> + numpunct::~numpunct() + { + if (_M_data->_M_grouping_size) + delete [] _M_data->_M_grouping; + delete _M_data; + } + #endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace diff --git a/libstdc++-v3/config/locale/dragonfly/time_members.cc b/libstdc++-v3/config/locale/dragonfly/time_members.cc new file mode 100644 index 00000000000..1812e50b5be --- /dev/null +++ b/libstdc++-v3/config/locale/dragonfly/time_members.cc @@ -0,0 +1,404 @@ +// std::time_get, std::time_put implementation, DragonFly version -*- C++ -*- + +// Copyright (C) 2001-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +// +// ISO C++ 14882: 22.2.5.1.2 - time_get virtual functions +// ISO C++ 14882: 22.2.5.3.2 - time_put virtual functions +// + +// Written by Benjamin Kosnik +// Modified for DragonFly by John Marino + +#include +#include +#include +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template<> + void + __timepunct:: + _M_put(char* __s, size_t __maxlen, const char* __format, + const tm* __tm) const throw() + { + const size_t __len = strftime_l(__s, __maxlen, __format, __tm, + (locale_t)_M_c_locale_timepunct); + // Make sure __s is null terminated. + if (__len == 0) + __s[0] = '\0'; + } + + template<> + void + __timepunct::_M_initialize_timepunct(__c_locale __cloc) + { + if (!_M_data) + _M_data = new __timepunct_cache; + + if (!__cloc) + { + // "C" locale + _M_c_locale_timepunct = _S_get_c_locale(); + + _M_data->_M_date_format = "%m/%d/%y"; + _M_data->_M_date_era_format = "%m/%d/%y"; + _M_data->_M_time_format = "%H:%M:%S"; + _M_data->_M_time_era_format = "%H:%M:%S"; + _M_data->_M_date_time_format = ""; + _M_data->_M_date_time_era_format = ""; + _M_data->_M_am = "AM"; + _M_data->_M_pm = "PM"; + _M_data->_M_am_pm_format = ""; + + // Day names, starting with "C"'s Sunday. + _M_data->_M_day1 = "Sunday"; + _M_data->_M_day2 = "Monday"; + _M_data->_M_day3 = "Tuesday"; + _M_data->_M_day4 = "Wednesday"; + _M_data->_M_day5 = "Thursday"; + _M_data->_M_day6 = "Friday"; + _M_data->_M_day7 = "Saturday"; + + // Abbreviated day names, starting with "C"'s Sun. + _M_data->_M_aday1 = "Sun"; + _M_data->_M_aday2 = "Mon"; + _M_data->_M_aday3 = "Tue"; + _M_data->_M_aday4 = "Wed"; + _M_data->_M_aday5 = "Thu"; + _M_data->_M_aday6 = "Fri"; + _M_data->_M_aday7 = "Sat"; + + // Month names, starting with "C"'s January. + _M_data->_M_month01 = "January"; + _M_data->_M_month02 = "February"; + _M_data->_M_month03 = "March"; + _M_data->_M_month04 = "April"; + _M_data->_M_month05 = "May"; + _M_data->_M_month06 = "June"; + _M_data->_M_month07 = "July"; + _M_data->_M_month08 = "August"; + _M_data->_M_month09 = "September"; + _M_data->_M_month10 = "October"; + _M_data->_M_month11 = "November"; + _M_data->_M_month12 = "December"; + + // Abbreviated month names, starting with "C"'s Jan. + _M_data->_M_amonth01 = "Jan"; + _M_data->_M_amonth02 = "Feb"; + _M_data->_M_amonth03 = "Mar"; + _M_data->_M_amonth04 = "Apr"; + _M_data->_M_amonth05 = "May"; + _M_data->_M_amonth06 = "Jun"; + _M_data->_M_amonth07 = "Jul"; + _M_data->_M_amonth08 = "Aug"; + _M_data->_M_amonth09 = "Sep"; + _M_data->_M_amonth10 = "Oct"; + _M_data->_M_amonth11 = "Nov"; + _M_data->_M_amonth12 = "Dec"; + } + else + { + _M_c_locale_timepunct = _S_clone_c_locale(__cloc); + + _M_data->_M_date_format = nl_langinfo_l(D_FMT, (locale_t)__cloc); + _M_data->_M_date_era_format = nl_langinfo_l(ERA_D_FMT, + (locale_t)__cloc); + _M_data->_M_time_format = nl_langinfo_l(T_FMT, (locale_t)__cloc); + _M_data->_M_time_era_format = nl_langinfo_l(ERA_T_FMT, + (locale_t)__cloc); + _M_data->_M_date_time_format = nl_langinfo_l(D_T_FMT, + (locale_t)__cloc); + _M_data->_M_date_time_era_format = nl_langinfo_l(ERA_D_T_FMT, + (locale_t)__cloc); + _M_data->_M_am = nl_langinfo_l(AM_STR, (locale_t)__cloc); + _M_data->_M_pm = nl_langinfo_l(PM_STR, (locale_t)__cloc); + _M_data->_M_am_pm_format = nl_langinfo_l(T_FMT_AMPM, + (locale_t)__cloc); + + // Day names, starting with "C"'s Sunday. + _M_data->_M_day1 = nl_langinfo_l(DAY_1, (locale_t)__cloc); + _M_data->_M_day2 = nl_langinfo_l(DAY_2, (locale_t)__cloc); + _M_data->_M_day3 = nl_langinfo_l(DAY_3, (locale_t)__cloc); + _M_data->_M_day4 = nl_langinfo_l(DAY_4, (locale_t)__cloc); + _M_data->_M_day5 = nl_langinfo_l(DAY_5, (locale_t)__cloc); + _M_data->_M_day6 = nl_langinfo_l(DAY_6, (locale_t)__cloc); + _M_data->_M_day7 = nl_langinfo_l(DAY_7, (locale_t)__cloc); + + // Abbreviated day names, starting with "C"'s Sun. + _M_data->_M_aday1 = nl_langinfo_l(ABDAY_1, (locale_t)__cloc); + _M_data->_M_aday2 = nl_langinfo_l(ABDAY_2, (locale_t)__cloc); + _M_data->_M_aday3 = nl_langinfo_l(ABDAY_3, (locale_t)__cloc); + _M_data->_M_aday4 = nl_langinfo_l(ABDAY_4, (locale_t)__cloc); + _M_data->_M_aday5 = nl_langinfo_l(ABDAY_5, (locale_t)__cloc); + _M_data->_M_aday6 = nl_langinfo_l(ABDAY_6, (locale_t)__cloc); + _M_data->_M_aday7 = nl_langinfo_l(ABDAY_7, (locale_t)__cloc); + + // Month names, starting with "C"'s January. + _M_data->_M_month01 = nl_langinfo_l(MON_1, (locale_t)__cloc); + _M_data->_M_month02 = nl_langinfo_l(MON_2, (locale_t)__cloc); + _M_data->_M_month03 = nl_langinfo_l(MON_3, (locale_t)__cloc); + _M_data->_M_month04 = nl_langinfo_l(MON_4, (locale_t)__cloc); + _M_data->_M_month05 = nl_langinfo_l(MON_5, (locale_t)__cloc); + _M_data->_M_month06 = nl_langinfo_l(MON_6, (locale_t)__cloc); + _M_data->_M_month07 = nl_langinfo_l(MON_7, (locale_t)__cloc); + _M_data->_M_month08 = nl_langinfo_l(MON_8, (locale_t)__cloc); + _M_data->_M_month09 = nl_langinfo_l(MON_9, (locale_t)__cloc); + _M_data->_M_month10 = nl_langinfo_l(MON_10, (locale_t)__cloc); + _M_data->_M_month11 = nl_langinfo_l(MON_11, (locale_t)__cloc); + _M_data->_M_month12 = nl_langinfo_l(MON_12, (locale_t)__cloc); + + // Abbreviated month names, starting with "C"'s Jan. + _M_data->_M_amonth01 = nl_langinfo_l(ABMON_1, (locale_t)__cloc); + _M_data->_M_amonth02 = nl_langinfo_l(ABMON_2, (locale_t)__cloc); + _M_data->_M_amonth03 = nl_langinfo_l(ABMON_3, (locale_t)__cloc); + _M_data->_M_amonth04 = nl_langinfo_l(ABMON_4, (locale_t)__cloc); + _M_data->_M_amonth05 = nl_langinfo_l(ABMON_5, (locale_t)__cloc); + _M_data->_M_amonth06 = nl_langinfo_l(ABMON_6, (locale_t)__cloc); + _M_data->_M_amonth07 = nl_langinfo_l(ABMON_7, (locale_t)__cloc); + _M_data->_M_amonth08 = nl_langinfo_l(ABMON_8, (locale_t)__cloc); + _M_data->_M_amonth09 = nl_langinfo_l(ABMON_9, (locale_t)__cloc); + _M_data->_M_amonth10 = nl_langinfo_l(ABMON_10, (locale_t)__cloc); + _M_data->_M_amonth11 = nl_langinfo_l(ABMON_11, (locale_t)__cloc); + _M_data->_M_amonth12 = nl_langinfo_l(ABMON_12, (locale_t)__cloc); + } + } + +#ifdef _GLIBCXX_USE_WCHAR_T + template<> + void + __timepunct:: + _M_put(wchar_t* __s, size_t __maxlen, const wchar_t* __format, + const tm* __tm) const throw() + { + const size_t __len = wcsftime_l(__s, __maxlen, __format, __tm, + (locale_t)_M_c_locale_timepunct); + // Make sure __s is null terminated. + if (__len == 0) + __s[0] = L'\0'; + } + +#define WIDE_LANGINFO(M,FMT) \ + 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); \ + langstring[fmtlen] = L'\0'; \ + _M_data->M = langstring; + + template<> + void + __timepunct::_M_initialize_timepunct(__c_locale __cloc) + { + if (!_M_data) + _M_data = new __timepunct_cache; + + if (!__cloc) + { + // "C" locale + _M_c_locale_timepunct = _S_get_c_locale(); + + _M_data->_M_date_format = L"%m/%d/%y"; + _M_data->_M_date_era_format = L"%m/%d/%y"; + _M_data->_M_time_format = L"%H:%M:%S"; + _M_data->_M_time_era_format = L"%H:%M:%S"; + _M_data->_M_date_time_format = L""; + _M_data->_M_date_time_era_format = L""; + _M_data->_M_am = L"AM"; + _M_data->_M_pm = L"PM"; + _M_data->_M_am_pm_format = L""; + + // Day names, starting with "C"'s Sunday. + _M_data->_M_day1 = L"Sunday"; + _M_data->_M_day2 = L"Monday"; + _M_data->_M_day3 = L"Tuesday"; + _M_data->_M_day4 = L"Wednesday"; + _M_data->_M_day5 = L"Thursday"; + _M_data->_M_day6 = L"Friday"; + _M_data->_M_day7 = L"Saturday"; + + // Abbreviated day names, starting with "C"'s Sun. + _M_data->_M_aday1 = L"Sun"; + _M_data->_M_aday2 = L"Mon"; + _M_data->_M_aday3 = L"Tue"; + _M_data->_M_aday4 = L"Wed"; + _M_data->_M_aday5 = L"Thu"; + _M_data->_M_aday6 = L"Fri"; + _M_data->_M_aday7 = L"Sat"; + + // Month names, starting with "C"'s January. + _M_data->_M_month01 = L"January"; + _M_data->_M_month02 = L"February"; + _M_data->_M_month03 = L"March"; + _M_data->_M_month04 = L"April"; + _M_data->_M_month05 = L"May"; + _M_data->_M_month06 = L"June"; + _M_data->_M_month07 = L"July"; + _M_data->_M_month08 = L"August"; + _M_data->_M_month09 = L"September"; + _M_data->_M_month10 = L"October"; + _M_data->_M_month11 = L"November"; + _M_data->_M_month12 = L"December"; + + // Abbreviated month names, starting with "C"'s Jan. + _M_data->_M_amonth01 = L"Jan"; + _M_data->_M_amonth02 = L"Feb"; + _M_data->_M_amonth03 = L"Mar"; + _M_data->_M_amonth04 = L"Apr"; + _M_data->_M_amonth05 = L"May"; + _M_data->_M_amonth06 = L"Jun"; + _M_data->_M_amonth07 = L"Jul"; + _M_data->_M_amonth08 = L"Aug"; + _M_data->_M_amonth09 = L"Sep"; + _M_data->_M_amonth10 = L"Oct"; + _M_data->_M_amonth11 = L"Nov"; + _M_data->_M_amonth12 = L"Dec"; + } + else + { + wchar_t *langstring = 0; + wchar_t holder[128]; + size_t fmtlen; + + _M_c_locale_timepunct = _S_clone_c_locale(__cloc); + + WIDE_LANGINFO(_M_date_format, D_FMT) + WIDE_LANGINFO(_M_date_era_format, ERA_D_FMT) + WIDE_LANGINFO(_M_time_format, T_FMT) + WIDE_LANGINFO(_M_time_era_format, ERA_T_FMT) + WIDE_LANGINFO(_M_date_time_format, D_T_FMT) + WIDE_LANGINFO(_M_date_time_era_format, ERA_D_T_FMT) + WIDE_LANGINFO(_M_am, AM_STR) + WIDE_LANGINFO(_M_pm, PM_STR) + WIDE_LANGINFO(_M_am_pm_format, T_FMT_AMPM) + + // Day names, starting with "C"'s Sunday. + WIDE_LANGINFO(_M_day1, DAY_1) + WIDE_LANGINFO(_M_day2, DAY_2) + WIDE_LANGINFO(_M_day3, DAY_3) + WIDE_LANGINFO(_M_day4, DAY_4) + WIDE_LANGINFO(_M_day5, DAY_5) + WIDE_LANGINFO(_M_day6, DAY_6) + WIDE_LANGINFO(_M_day7, DAY_7) + + // Abbreviated day names, starting with "C"'s Sun. + WIDE_LANGINFO(_M_aday1, ABDAY_1) + WIDE_LANGINFO(_M_aday2, ABDAY_2) + WIDE_LANGINFO(_M_aday3, ABDAY_3) + WIDE_LANGINFO(_M_aday4, ABDAY_4) + WIDE_LANGINFO(_M_aday5, ABDAY_5) + WIDE_LANGINFO(_M_aday6, ABDAY_6) + WIDE_LANGINFO(_M_aday7, ABDAY_7) + + // Month names, starting with "C"'s January. + WIDE_LANGINFO(_M_month01, MON_1) + WIDE_LANGINFO(_M_month02, MON_2) + WIDE_LANGINFO(_M_month03, MON_3) + WIDE_LANGINFO(_M_month04, MON_4) + WIDE_LANGINFO(_M_month05, MON_5) + WIDE_LANGINFO(_M_month06, MON_6) + WIDE_LANGINFO(_M_month07, MON_7) + WIDE_LANGINFO(_M_month08, MON_8) + WIDE_LANGINFO(_M_month09, MON_9) + WIDE_LANGINFO(_M_month10, MON_10) + WIDE_LANGINFO(_M_month11, MON_11) + WIDE_LANGINFO(_M_month12, MON_12) + + // Abbreviated month names, starting with "C"'s Jan. + WIDE_LANGINFO(_M_amonth01, ABMON_1) + WIDE_LANGINFO(_M_amonth02, ABMON_2) + WIDE_LANGINFO(_M_amonth03, ABMON_3) + WIDE_LANGINFO(_M_amonth04, ABMON_4) + WIDE_LANGINFO(_M_amonth05, ABMON_5) + WIDE_LANGINFO(_M_amonth06, ABMON_6) + WIDE_LANGINFO(_M_amonth07, ABMON_7) + WIDE_LANGINFO(_M_amonth08, ABMON_8) + WIDE_LANGINFO(_M_amonth09, ABMON_9) + WIDE_LANGINFO(_M_amonth10, ABMON_10) + WIDE_LANGINFO(_M_amonth11, ABMON_11) + WIDE_LANGINFO(_M_amonth12, ABMON_12) + } + } + + template<> + __timepunct::~__timepunct() + { + delete [] _M_data->_M_date_format; + delete [] _M_data->_M_date_era_format; + delete [] _M_data->_M_time_format; + delete [] _M_data->_M_time_era_format; + delete [] _M_data->_M_date_time_format; + delete [] _M_data->_M_date_time_era_format; + delete [] _M_data->_M_am; + delete [] _M_data->_M_pm; + delete [] _M_data->_M_am_pm_format; + delete [] _M_data->_M_day1; + delete [] _M_data->_M_day2; + delete [] _M_data->_M_day3; + delete [] _M_data->_M_day4; + delete [] _M_data->_M_day5; + delete [] _M_data->_M_day6; + delete [] _M_data->_M_day7; + delete [] _M_data->_M_aday1; + delete [] _M_data->_M_aday2; + delete [] _M_data->_M_aday3; + delete [] _M_data->_M_aday4; + delete [] _M_data->_M_aday5; + delete [] _M_data->_M_aday6; + delete [] _M_data->_M_aday7; + delete [] _M_data->_M_month01; + delete [] _M_data->_M_month02; + delete [] _M_data->_M_month03; + delete [] _M_data->_M_month04; + delete [] _M_data->_M_month05; + delete [] _M_data->_M_month06; + delete [] _M_data->_M_month07; + delete [] _M_data->_M_month08; + delete [] _M_data->_M_month09; + delete [] _M_data->_M_month10; + delete [] _M_data->_M_month11; + delete [] _M_data->_M_month12; + delete [] _M_data->_M_amonth01; + delete [] _M_data->_M_amonth02; + delete [] _M_data->_M_amonth03; + delete [] _M_data->_M_amonth04; + delete [] _M_data->_M_amonth05; + delete [] _M_data->_M_amonth06; + delete [] _M_data->_M_amonth07; + delete [] _M_data->_M_amonth08; + delete [] _M_data->_M_amonth09; + delete [] _M_data->_M_amonth10; + delete [] _M_data->_M_amonth11; + delete [] _M_data->_M_amonth12; + delete _M_data; + } + +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace diff --git a/libstdc++-v3/config/locale/dragonfly/time_members.h b/libstdc++-v3/config/locale/dragonfly/time_members.h new file mode 100644 index 00000000000..fb78bc6e45f --- /dev/null +++ b/libstdc++-v3/config/locale/dragonfly/time_members.h @@ -0,0 +1,95 @@ +// std::time_get, std::time_put implementation, DragonFly version -*- C++ -*- + +// Copyright (C) 2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/time_members.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{locale} + */ + +// +// ISO C++ 14882: 22.2.5.1.2 - time_get functions +// ISO C++ 14882: 22.2.5.3.2 - time_put functions +// + +// Written by Benjamin Kosnik +// Modified for DragonFly by John Marino + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template + __timepunct<_CharT>::__timepunct(size_t __refs) + : facet(__refs), _M_data(0), _M_c_locale_timepunct(0), + _M_name_timepunct(_S_get_c_name()) + { _M_initialize_timepunct(); } + + template + __timepunct<_CharT>::__timepunct(__cache_type* __cache, size_t __refs) + : facet(__refs), _M_data(__cache), _M_c_locale_timepunct(0), + _M_name_timepunct(_S_get_c_name()) + { _M_initialize_timepunct(); } + + template + __timepunct<_CharT>::__timepunct(__c_locale __cloc, const char* __s, + size_t __refs) + : facet(__refs), _M_data(0), _M_c_locale_timepunct(0), + _M_name_timepunct(0) + { + if (__builtin_strcmp(__s, _S_get_c_name()) != 0) + { + const size_t __len = __builtin_strlen(__s) + 1; + char* __tmp = new char[__len]; + __builtin_memcpy(__tmp, __s, __len); + _M_name_timepunct = __tmp; + } + else + _M_name_timepunct = _S_get_c_name(); + + __try + { _M_initialize_timepunct(__cloc); } + __catch(...) + { + if (_M_name_timepunct != _S_get_c_name()) + delete [] _M_name_timepunct; + __throw_exception_again; + } + } + + template + __timepunct<_CharT>::~__timepunct() + { + if (_M_name_timepunct != _S_get_c_name()) + delete [] _M_name_timepunct; + delete _M_data; + _S_destroy_c_locale(_M_c_locale_timepunct); + } + + // specialization + template<> + __timepunct::~__timepunct(); + + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace diff --git a/libstdc++-v3/config/os/bsd/dragonfly/ctype_configure_char.cc b/libstdc++-v3/config/os/bsd/dragonfly/ctype_configure_char.cc index 043d1365b39..b1c24a2e1a5 100644 --- a/libstdc++-v3/config/os/bsd/dragonfly/ctype_configure_char.cc +++ b/libstdc++-v3/config/os/bsd/dragonfly/ctype_configure_char.cc @@ -37,32 +37,60 @@ namespace std _GLIBCXX_VISIBILITY(default) _GLIBCXX_BEGIN_NAMESPACE_VERSION // Information as gleaned from /usr/include/ctype.h - + const ctype_base::mask* ctype::classic_table() throw() - { return 0; } - - ctype::ctype(__c_locale, const mask* __table, bool __del, - size_t __refs) - : facet(__refs), _M_del(__table != 0 && __del), - _M_toupper(NULL), _M_tolower(NULL), - _M_table(__table ? __table : classic_table()) - { + { return NULL; } + + ctype::ctype(__c_locale, const mask* __table, bool __del, + size_t __refs) + : facet(__refs), _M_c_locale_ctype(_S_get_c_locale()), + _M_del(__table != 0 && __del), _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"); + } + _M_toupper = NULL; + _M_tolower = NULL; + _M_table = __table ? __table : classic_table(); + 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), - _M_toupper(NULL), _M_tolower(NULL), - _M_table(__table ? __table : classic_table()) - { + ctype::ctype(const mask* __table, bool __del, size_t __refs) + : facet(__refs), _M_c_locale_ctype(_S_get_c_locale()), + _M_del(__table != 0 && __del), _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"); + } + _M_toupper = NULL; + _M_tolower = NULL; + _M_table = __table ? __table : classic_table(); + 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 @@ -84,7 +112,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ctype::do_tolower(char __c) const { return ::tolower((int) __c); } - const char* + const char* ctype::do_tolower(char* __low, const char* __high) const { while (__low < __high) diff --git a/libstdc++-v3/config/os/bsd/dragonfly/os_defines.h b/libstdc++-v3/config/os/bsd/dragonfly/os_defines.h index 5e11c451ec2..2209129145a 100644 --- a/libstdc++-v3/config/os/bsd/dragonfly/os_defines.h +++ b/libstdc++-v3/config/os/bsd/dragonfly/os_defines.h @@ -29,6 +29,7 @@ // System-specific #define, typedefs, corrections, etc, go here. This // file will come before all others. +#define _GLIBCXX_USE_C99 1 #define _GLIBCXX_USE_C99_CHECK 1 #define _GLIBCXX_USE_C99_DYNAMIC (!(__ISO_C_VISIBLE >= 1999)) #define _GLIBCXX_USE_C99_LONG_LONG_CHECK 1 diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure index 59ad827e6f6..8646465fbbe 100755 --- a/libstdc++-v3/configure +++ b/libstdc++-v3/configure @@ -15986,17 +15986,17 @@ $as_echo "darwin or freebsd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: dragonfly" >&5 $as_echo "dragonfly" >&6; } - CLOCALE_H=config/locale/generic/c_locale.h + CLOCALE_H=config/locale/dragonfly/c_locale.h CLOCALE_CC=config/locale/dragonfly/c_locale.cc - CCODECVT_CC=config/locale/generic/codecvt_members.cc - CCOLLATE_CC=config/locale/generic/collate_members.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/generic/monetary_members.cc - CNUMERIC_CC=config/locale/generic/numeric_members.cc - CTIME_H=config/locale/generic/time_members.h - CTIME_CC=config/locale/generic/time_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 ;; -- 2.30.2