Do we want something like this for GCC 15? Tested x86_64-freebsd and sparc-solaris (although not for a few months).
-- >8 -- libstdc++-v3/ChangeLog: PR libstdc++/57585 * acinclude.m4 (GLIBCXX_ENABLE_CLOCALE): Add ieee_1003.1-2008 as new value. Add posix-2001 and posix-2008 as aliases. * configure: Regenerate. * config/locale/ieee_1003.1-2001/messages_members.h: Define constructors. Call _S_delete_c_locale in destructor. * config/locale/ieee_1003.1-2001/messages_members.cc: Fix code that doesn't even compile. * include/bits/locale_facets_nonio.h (messages_base::catalog): Allow type to be customized by clocale model. * 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. * config/os/bsd/freebsd/ctype_inline.h (_GLIBCXX_CTYPE_INLINE_WCHAR_MEMBERS): Define new macro. --- libstdc++-v3/acinclude.m4 | 26 +- .../ieee_1003.1-2001/messages_members.cc | 3 +- .../ieee_1003.1-2001/messages_members.h | 25 +- .../locale/ieee_1003.1-2008/c_locale.cc | 217 +++++ .../config/locale/ieee_1003.1-2008/c_locale.h | 90 ++ .../ieee_1003.1-2008/codecvt_members.cc | 289 ++++++ .../ieee_1003.1-2008/collate_members.cc | 75 ++ .../locale/ieee_1003.1-2008/ctype_members.cc | 287 ++++++ .../ieee_1003.1-2008/monetary_members.cc | 916 ++++++++++++++++++ .../ieee_1003.1-2008/numeric_members.cc | 227 +++++ .../locale/ieee_1003.1-2008/time_members.cc | 384 ++++++++ .../locale/ieee_1003.1-2008/time_members.h | 89 ++ .../config/os/bsd/freebsd/ctype_inline.h | 1 + libstdc++-v3/configure | 29 +- .../include/bits/locale_facets_nonio.h | 9 +- 15 files changed, 2659 insertions(+), 8 deletions(-) create mode 100644 libstdc++-v3/config/locale/ieee_1003.1-2008/c_locale.cc create mode 100644 libstdc++-v3/config/locale/ieee_1003.1-2008/c_locale.h create mode 100644 libstdc++-v3/config/locale/ieee_1003.1-2008/codecvt_members.cc create mode 100644 libstdc++-v3/config/locale/ieee_1003.1-2008/collate_members.cc create mode 100644 libstdc++-v3/config/locale/ieee_1003.1-2008/ctype_members.cc create mode 100644 libstdc++-v3/config/locale/ieee_1003.1-2008/monetary_members.cc create mode 100644 libstdc++-v3/config/locale/ieee_1003.1-2008/numeric_members.cc create mode 100644 libstdc++-v3/config/locale/ieee_1003.1-2008/time_members.cc create mode 100644 libstdc++-v3/config/locale/ieee_1003.1-2008/time_members.h diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4 index b3423d7957a..e915b01bbaa 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|ieee_1003.1-2008|posix-2001|posix-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 @@ -2788,6 +2788,10 @@ AC_DEFUN([GLIBCXX_ENABLE_CLOCALE], [ # Either a known package, or "auto" if test $enable_clocale = no || test $enable_clocale = yes; then enable_clocale=auto + elif test $enable_clocale = posix-2001; then + enable_clocale=ieee_1003.1-2001 + elif test $enable_clocale = posix-2008; then + enable_clocale=ieee_1003.1-2008 fi enable_clocale_flag=$enable_clocale @@ -2966,7 +2970,7 @@ AC_DEFUN([GLIBCXX_ENABLE_CLOCALE], [ CLOCALE_INTERNAL_H=config/locale/gnu/c++locale_internal.h ;; ieee_1003.1-2001) - AC_MSG_RESULT(IEEE 1003.1) + AC_MSG_RESULT(IEEE 1003.1-2001) CLOCALE_H=config/locale/ieee_1003.1-2001/c_locale.h CLOCALE_CC=config/locale/ieee_1003.1-2001/c_locale.cc @@ -2981,6 +2985,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/ieee_1003.1-2001/messages_members.h + CMESSAGES_CC=config/locale/ieee_1003.1-2001/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/ieee_1003.1-2001/messages_members.cc b/libstdc++-v3/config/locale/ieee_1003.1-2001/messages_members.cc index 3b94689d34f..c8f215ca7d9 100644 --- a/libstdc++-v3/config/locale/ieee_1003.1-2001/messages_members.cc +++ b/libstdc++-v3/config/locale/ieee_1003.1-2001/messages_members.cc @@ -45,7 +45,8 @@ namespace std _GLIBCXX_VISIBILITY(default) #ifdef _GLIBCXX_USE_WCHAR_T template<> wstring - messages<wchar_t>::do_get(catalog, int, int, const wstring& __dfault) const + messages<wchar_t>::do_get(catalog __c, int __setid, int __msgid, + const wstring& __dfault) const { nl_catd __nlc = reinterpret_cast<nl_catd>(__c); char* __msg = catgets(__nlc, __setid, __msgid, diff --git a/libstdc++-v3/config/locale/ieee_1003.1-2001/messages_members.h b/libstdc++-v3/config/locale/ieee_1003.1-2001/messages_members.h index e6772b35aa9..7810f2ae432 100644 --- a/libstdc++-v3/config/locale/ieee_1003.1-2001/messages_members.h +++ b/libstdc++-v3/config/locale/ieee_1003.1-2001/messages_members.h @@ -38,6 +38,16 @@ namespace std _GLIBCXX_VISIBILITY(default) _GLIBCXX_BEGIN_NAMESPACE_VERSION // Non-virtual member functions. + template<typename _CharT> + messages<_CharT>::messages(size_t __refs) + : facet(__refs), _M_c_locale_messages(_S_get_c_locale()) + { } + + template<typename _CharT> + messages<_CharT>::messages(__c_locale, const char*, size_t __refs) + : facet(__refs), _M_c_locale_messages(_S_get_c_locale()) + { } + template<typename _CharT> typename messages<_CharT>::catalog messages<_CharT>::open(const basic_string<char>& __s, const locale& __loc, @@ -47,7 +57,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Virtual member functions. template<typename _CharT> messages<_CharT>::~messages() - { } + { this->_S_destroy_c_locale(_M_c_locale_messages); } template<typename _CharT> typename messages<_CharT>::catalog @@ -71,5 +81,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION messages<_CharT>::do_close(catalog __c) const { catclose(reinterpret_cast<nl_catd>(__c)); } + // messages_byname + template<typename _CharT> + messages_byname<_CharT>::messages_byname(const char* __s, size_t __refs) + : messages<_CharT>(__refs) + { + if (__builtin_strcmp(__s, "C") != 0 + && __builtin_strcmp(__s, "POSIX") != 0) + { + this->_S_destroy_c_locale(this->_M_c_locale_messages); + this->_S_create_c_locale(this->_M_c_locale_messages, __s); + } + } + _GLIBCXX_END_NAMESPACE_VERSION } // namespace diff --git a/libstdc++-v3/config/locale/ieee_1003.1-2008/c_locale.cc b/libstdc++-v3/config/locale/ieee_1003.1-2008/c_locale.cc new file mode 100644 index 00000000000..1733f0be031 --- /dev/null +++ b/libstdc++-v3/config/locale/ieee_1003.1-2008/c_locale.cc @@ -0,0 +1,217 @@ +// Wrapper for underlying C-language localization -*- C++ -*- + +// Copyright (C) 2001-2024 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 +// <http://www.gnu.org/licenses/>. + +// +// ISO C++ 14882: 22.8 Standard locale categories. +// + +// Written by Benjamin Kosnik <b...@redhat.com> + +#define _POSIX_C_SOURCE 200809L + +#include <locale> +#include <stdexcept> +#include <limits> +#include <algorithm> +#include <clocale> +#include <langinfo.h> + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +namespace +{ + struct auto_locale + { + // Use uselocale to change the current thread's locale. + locale_t orig; + + explicit + auto_locale(locale_t loc) : orig(::uselocale(loc)) { } + + ~auto_locale() { if (orig) ::uselocale(orig); } + + private: + auto_locale(const auto_locale&); + auto_locale& operator=(const auto_locale&); + }; +} // namespace + + template<> + void + __convert_to_v(const char* __s, float& __v, ios_base::iostate& __err, + const __c_locale& __cloc) throw() + { + auto_locale l(__cloc); + + char* __sanity; + __v = strtof(__s, &__sanity); + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 23. Num_get overflow result. + if (__sanity == __s || *__sanity != '\0') + { + __v = 0.0f; + __err = ios_base::failbit; + } + else if (__v == numeric_limits<float>::infinity()) + { + __v = numeric_limits<float>::max(); + __err = ios_base::failbit; + } + else if (__v == -numeric_limits<float>::infinity()) + { + __v = -numeric_limits<float>::max(); + __err = ios_base::failbit; + } + } + + template<> + void + __convert_to_v(const char* __s, double& __v, ios_base::iostate& __err, + const __c_locale& __cloc) throw() + { + auto_locale l(__cloc); + + char* __sanity; + __v = strtod(__s, &__sanity); + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 23. Num_get overflow result. + if (__sanity == __s || *__sanity != '\0') + { + __v = 0.0; + __err = ios_base::failbit; + } + else if (__v == numeric_limits<double>::infinity()) + { + __v = numeric_limits<double>::max(); + __err = ios_base::failbit; + } + else if (__v == -numeric_limits<double>::infinity()) + { + __v = -numeric_limits<double>::max(); + __err = ios_base::failbit; + } + } + + template<> + void + __convert_to_v(const char* __s, long double& __v, ios_base::iostate& __err, + const __c_locale& __cloc) throw() + { + auto_locale l(__cloc); + + char* __sanity; + __v = strtold(__s, &__sanity); + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 23. Num_get overflow result. + if (__sanity == __s || *__sanity != '\0') + { + __v = 0.0l; + __err = ios_base::failbit; + } + else if (__v == numeric_limits<long double>::infinity()) + { + __v = numeric_limits<long double>::max(); + __err = ios_base::failbit; + } + else if (__v == -numeric_limits<long double>::infinity()) + { + __v = -numeric_limits<long double>::max(); + __err = ios_base::failbit; + } + } + + void + locale::facet::_S_create_c_locale(__c_locale& __cloc, const char* __s, + __c_locale __old) + { + __cloc = ::newlocale(LC_ALL_MASK, __s, __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) + { + if (__cloc && _S_get_c_locale() != __cloc) + ::freelocale(__cloc); + } + + __c_locale + locale::facet::_S_clone_c_locale(__c_locale& __cloc) throw() + { return ::duplocale(__cloc); } + + __c_locale + locale::facet::_S_lc_ctype_c_locale(__c_locale __cloc, const char* __s) + { + __c_locale __dup = ::duplocale(__cloc); + if (__dup == __c_locale(0)) + __throw_runtime_error(__N("locale::facet::_S_lc_ctype_c_locale " + "duplocale error")); + __c_locale __changed = ::newlocale(LC_CTYPE_MASK, __s, __dup); + if (__changed == __c_locale(0)) + { + ::freelocale(__dup); + __throw_runtime_error(__N("locale::facet::_S_lc_ctype_c_locale " + "newlocale error")); + } + return __changed; + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + const char* const category_names[6 + _GLIBCXX_NUM_CATEGORIES] = + { + "LC_CTYPE", + "LC_NUMERIC", + "LC_TIME", + "LC_COLLATE", + "LC_MONETARY", + "LC_MESSAGES", + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + const char* const* const locale::_S_categories = __gnu_cxx::category_names; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace diff --git a/libstdc++-v3/config/locale/ieee_1003.1-2008/c_locale.h b/libstdc++-v3/config/locale/ieee_1003.1-2008/c_locale.h new file mode 100644 index 00000000000..67c9dce5728 --- /dev/null +++ b/libstdc++-v3/config/locale/ieee_1003.1-2008/c_locale.h @@ -0,0 +1,90 @@ +// Wrapper for underlying C-language localization -*- C++ -*- + +// Copyright (C) 2001-2024 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 +// <http://www.gnu.org/licenses/>. + +/** @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 <b...@redhat.com> + +#ifndef _GLIBCXX_CXX_LOCALE_H +#define _GLIBCXX_CXX_LOCALE_H 1 + +#pragma GCC system_header + +#include <clocale> +#include <nl_types.h> // For nl_catd, catopen, catclose, catgets + +#define _GLIBCXX_C_LOCALE_POSIX2008 1 + +#define _GLIBCXX_NUM_CATEGORIES 0 + +#define _GLIBCXX_MESSAGES_BASE_CATALOG_TYPE nl_catd + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + typedef locale_t __c_locale; + +#if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \ + && defined __LONG_DOUBLE_IEEE128__ +namespace __gnu_cxx_ieee128 { +#endif + + // 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, const char* __fmt, ...) + { + __c_locale __old = uselocale(__cloc); + + __builtin_va_list __args; + __builtin_va_start(__args, __fmt); + + const int __ret = __builtin_vsnprintf(__out, __size, __fmt, __args); + + __builtin_va_end(__args); + + uselocale(__old); + return __ret; + } + +#if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \ + && defined __LONG_DOUBLE_IEEE128__ +} // namespace __gnu_cxx_ieee128 +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/libstdc++-v3/config/locale/ieee_1003.1-2008/codecvt_members.cc b/libstdc++-v3/config/locale/ieee_1003.1-2008/codecvt_members.cc new file mode 100644 index 00000000000..f6cf77fffe3 --- /dev/null +++ b/libstdc++-v3/config/locale/ieee_1003.1-2008/codecvt_members.cc @@ -0,0 +1,289 @@ +// std::codecvt implementation details, POSIX-2008 version -*- C++ -*- + +// Copyright (C) 2002-2024 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 +// <http://www.gnu.org/licenses/>. + +// +// ISO C++ 14882: 22.2.1.5 - Template class codecvt +// + +// Written by Benjamin Kosnik <b...@redhat.com> + +#define _POSIX_C_SOURCE 200809L + +#include <locale> +#include <cstring> // For memcpy, memchr +#include <cstdlib> // For MB_CUR_MAX +#include <climits> // For MB_LEN_MAX + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Specializations. +#ifdef _GLIBCXX_USE_WCHAR_T + codecvt_base::result + codecvt<wchar_t, char, mbstate_t>:: + 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 = uselocale(_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<size_t>(-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<size_t>(__to_end - __to_next)) + __ret = partial; + else + { + memcpy(__to_next, __buf, __conv2); + __state = __tmp_state; + __to_next += __conv2; + ++__from_next; + } + } + } + + uselocale(__old); + + return __ret; + } + + codecvt_base::result + codecvt<wchar_t, char, mbstate_t>:: + 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 = uselocale(_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<const extern_type*>(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<size_t>(-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<size_t>(-1) + || __conv == static_cast<size_t>(-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(__old); + + return __ret; + } + + int + codecvt<wchar_t, char, mbstate_t>:: + 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 = uselocale(_M_c_locale_codecvt); + if (MB_CUR_MAX == 1) + __ret = 1; + uselocale(__old); + return __ret; + } + + int + codecvt<wchar_t, char, mbstate_t>:: + do_max_length() const throw() + { + __c_locale __old = uselocale(_M_c_locale_codecvt); + // XXX Probably wrong for stateful encodings. + int __ret = MB_CUR_MAX; + uselocale(__old); + return __ret; + } + + int + codecvt<wchar_t, char, mbstate_t>:: + 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 = uselocale(_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<wchar_t*>(__builtin_alloca(sizeof(wchar_t) + * __max)); + while (__from < __end && __max) + { + const extern_type* __from_chunk_end; + __from_chunk_end = static_cast<const extern_type*>(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<size_t>(-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<size_t>(-1) + || __conv == static_cast<size_t>(-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(__old); + + return __ret; + } +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace diff --git a/libstdc++-v3/config/locale/ieee_1003.1-2008/collate_members.cc b/libstdc++-v3/config/locale/ieee_1003.1-2008/collate_members.cc new file mode 100644 index 00000000000..ea2c70056e6 --- /dev/null +++ b/libstdc++-v3/config/locale/ieee_1003.1-2008/collate_members.cc @@ -0,0 +1,75 @@ +// std::collate implementation details, POSIX-2008 version -*- C++ -*- + +// Copyright (C) 2001-2024 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 +// <http://www.gnu.org/licenses/>. + +// +// ISO C++ 14882: 22.2.4.1.2 collate virtual functions +// + +// Written by Benjamin Kosnik <b...@redhat.com> + +#define _POSIX_C_SOURCE 200809L + +#include <locale> +#include <cstring> + +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<char>::_M_compare(const char* __one, + const char* __two) const throw() + { + int __cmp = strcoll_l(__one, __two, _M_c_locale_collate); + return (__cmp >> (8 * sizeof (int) - 2)) | (__cmp != 0); + } + + template<> + size_t + collate<char>::_M_transform(char* __to, const char* __from, + size_t __n) const throw() + { return strxfrm_l(__to, __from, __n, _M_c_locale_collate); } + +#ifdef _GLIBCXX_USE_WCHAR_T + template<> + int + collate<wchar_t>::_M_compare(const wchar_t* __one, + const wchar_t* __two) const throw() + { + int __cmp = wcscoll_l(__one, __two, _M_c_locale_collate); + return (__cmp >> (8 * sizeof (int) - 2)) | (__cmp != 0); + } + + template<> + size_t + collate<wchar_t>::_M_transform(wchar_t* __to, const wchar_t* __from, + size_t __n) const throw() + { return wcsxfrm_l(__to, __from, __n, _M_c_locale_collate); } +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace diff --git a/libstdc++-v3/config/locale/ieee_1003.1-2008/ctype_members.cc b/libstdc++-v3/config/locale/ieee_1003.1-2008/ctype_members.cc new file mode 100644 index 00000000000..efe88f88292 --- /dev/null +++ b/libstdc++-v3/config/locale/ieee_1003.1-2008/ctype_members.cc @@ -0,0 +1,287 @@ +// std::ctype implementation details, POSIX-2008 version -*- C++ -*- + +// Copyright (C) 2001-2024 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 +// <http://www.gnu.org/licenses/>. + +// +// ISO C++ 14882: 22.2.1.1.2 ctype virtual functions. +// + +// Written by Benjamin Kosnik <b...@redhat.com> + +#define _POSIX_C_SOURCE 200809L + +#include <locale> +#include <clocale> +#include <cstring> +#include <cwctype> +#include <cstdio> // For EOF + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // NB: The other ctype<char> specializations are in src/locale.cc and + // various /config/os/* files. + ctype_byname<char>::ctype_byname(const char* __s, size_t __refs) + : ctype<char>(0, false, __refs) + { + if (std::strcmp(__s, "C") != 0 && std::strcmp(__s, "POSIX") != 0) + { + this->_S_destroy_c_locale(this->_M_c_locale_ctype); + this->_S_create_c_locale(this->_M_c_locale_ctype, __s); + } + } + + ctype_byname<char>::~ctype_byname() + { } + +#ifdef _GLIBCXX_USE_WCHAR_T + ctype<wchar_t>::__wmask_type + ctype<wchar_t>::_M_convert_to_wmask(const mask __m) const throw() + { + __wmask_type __ret; + switch (__m) + { + case space: + __ret = wctype_l("space", _M_c_locale_ctype); + break; + case print: + __ret = wctype_l("print", _M_c_locale_ctype); + break; + case cntrl: + __ret = wctype_l("cntrl", _M_c_locale_ctype); + break; + case upper: + __ret = wctype_l("upper", _M_c_locale_ctype); + break; + case lower: + __ret = wctype_l("lower", _M_c_locale_ctype); + break; + case alpha: + __ret = wctype_l("alpha", _M_c_locale_ctype); + break; + case digit: + __ret = wctype_l("digit", _M_c_locale_ctype); + break; + case punct: + __ret = wctype_l("punct", _M_c_locale_ctype); + break; + case xdigit: + __ret = wctype_l("xdigit", _M_c_locale_ctype); + break; + case alnum: + __ret = wctype_l("alnum", _M_c_locale_ctype); + break; + case graph: + __ret = wctype_l("graph", _M_c_locale_ctype); + break; + default: + // For some targets ctype_base::blank == ctype_base::space so check + // here to avoid a duplicate case error. + if (__m == blank) + __ret = wctype_l("blank", _M_c_locale_ctype); + else + __ret = __wmask_type(); + } + return __ret; + } + + wchar_t + ctype<wchar_t>::do_toupper(wchar_t __c) const + { return towupper_l(__c, _M_c_locale_ctype); } + + const wchar_t* + ctype<wchar_t>::do_toupper(wchar_t* __lo, const wchar_t* __hi) const + { + while (__lo < __hi) + { + *__lo = towupper_l(*__lo, _M_c_locale_ctype); + ++__lo; + } + return __hi; + } + + wchar_t + ctype<wchar_t>::do_tolower(wchar_t __c) const + { return towlower_l(__c, _M_c_locale_ctype); } + + const wchar_t* + ctype<wchar_t>::do_tolower(wchar_t* __lo, const wchar_t* __hi) const + { + while (__lo < __hi) + { + *__lo = towlower_l(*__lo, _M_c_locale_ctype); + ++__lo; + } + return __hi; + } + +#ifndef _GLIBCXX_CTYPE_INLINE_WCHAR_MEMBERS + bool + ctype<wchar_t>:: + do_is(mask __m, wchar_t __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<wchar_t>:: + 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_l(*__lo, _M_wmask[__bitcur], _M_c_locale_ctype)) + __m |= _M_bit[__bitcur]; + *__vec = __m; + } + return __hi; + } + + const wchar_t* + ctype<wchar_t>:: + 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<wchar_t>:: + 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<wchar_t>:: + do_widen(char __c) const + { return _M_widen[static_cast<unsigned char>(__c)]; } + + const char* + ctype<wchar_t>:: + do_widen(const char* __lo, const char* __hi, wchar_t* __dest) const + { + while (__lo < __hi) + { + *__dest = _M_widen[static_cast<unsigned char>(*__lo)]; + ++__lo; + ++__dest; + } + return __hi; + } + + char + ctype<wchar_t>:: + do_narrow(wchar_t __wc, char __dfault) const + { + if (__wc >= 0 && __wc < 128 && _M_narrow_ok) + return _M_narrow[__wc]; + __c_locale __old = uselocale(_M_c_locale_ctype); + const int __c = wctob(__wc); + uselocale(__old); + return (__c == EOF ? __dfault : static_cast<char>(__c)); + } + + const wchar_t* + ctype<wchar_t>:: + do_narrow(const wchar_t* __lo, const wchar_t* __hi, char __dfault, + char* __dest) const + { + __c_locale __old = uselocale(_M_c_locale_ctype); + if (_M_narrow_ok) + while (__lo < __hi) + { + if (*__lo >= 0 && *__lo < 128) + *__dest = _M_narrow[*__lo]; + else + { + const int __c = wctob(*__lo); + *__dest = (__c == EOF ? __dfault : static_cast<char>(__c)); + } + ++__lo; + ++__dest; + } + else + while (__lo < __hi) + { + const int __c = wctob(*__lo); + *__dest = (__c == EOF ? __dfault : static_cast<char>(__c)); + ++__lo; + ++__dest; + } + uselocale(__old); + return __hi; + } + + void + ctype<wchar_t>::_M_initialize_ctype() throw() + { + __c_locale __old = uselocale(_M_c_locale_ctype); + wint_t __i; + for (__i = 0; __i < 128; ++__i) + { + const int __c = wctob(__i); + if (__c == EOF) + break; + else + _M_narrow[__i] = static_cast<char>(__c); + } + if (__i == 128) + _M_narrow_ok = true; + else + _M_narrow_ok = false; + for (size_t __j = 0; + __j < sizeof(_M_widen) / sizeof(wint_t); ++__j) + _M_widen[__j] = btowc(__j); + + for (size_t __k = 0; __k <= 15; ++__k) + { + _M_bit[__k] = static_cast<mask>(1 << __k); + _M_wmask[__k] = _M_convert_to_wmask(_M_bit[__k]); + } + uselocale(__old); + } +#endif // _GLIBCXX_USE_WCHAR_T + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace diff --git a/libstdc++-v3/config/locale/ieee_1003.1-2008/monetary_members.cc b/libstdc++-v3/config/locale/ieee_1003.1-2008/monetary_members.cc new file mode 100644 index 00000000000..a9c7b7c89d4 --- /dev/null +++ b/libstdc++-v3/config/locale/ieee_1003.1-2008/monetary_members.cc @@ -0,0 +1,916 @@ +// std::moneypunct implementation details, GNU version -*- C++ -*- + +// Copyright (C) 2001-2024 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 +// <http://www.gnu.org/licenses/>. + +// +// ISO C++ 14882: 22.2.6.3.2 moneypunct virtual functions +// + +// Written by Benjamin Kosnik <b...@redhat.com> + +#define _POSIX_C_SOURCE 200809L +// Solaris needs this to define the C99 / POSIX.1-2001 members of struct lconv: +#define _LCONV_C99 1 + +#include <locale> +#include <cstring> +#include <langinfo.h> + +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 monyepunct. 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 + + extern char __narrow_multibyte_chars(const char* s, locale_t cloc); + + template<> + void + moneypunct<char, true>::_M_initialize_moneypunct(__c_locale __cloc, + const char*) + { + if (!_M_data) + _M_data = new __moneypunct_cache<char, true>; + + 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. + locale_t orig = ::uselocale(__cloc); // FIXME: use RAII + const lconv* lc = ::localeconv(); + _M_data->_M_decimal_point = *lc->mon_decimal_point; + const char* thousands_sep = lc->mon_thousands_sep; + if (thousands_sep[0] != '\0' && thousands_sep[1] != '\0') + _M_data->_M_thousands_sep = __narrow_multibyte_chars(thousands_sep, + __cloc); + else + _M_data->_M_thousands_sep = *thousands_sep; + + // Check for NULL, which implies no fractional digits. + if (_M_data->_M_decimal_point == '\0') + { + // Like in "C" locale. + _M_data->_M_frac_digits = 0; + _M_data->_M_decimal_point = '.'; + } + else + _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 (_M_data->_M_thousands_sep == '\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 + { + __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); + ::uselocale(orig); + } + } + + template<> + void + moneypunct<char, false>::_M_initialize_moneypunct(__c_locale __cloc, + const char*) + { + if (!_M_data) + _M_data = new __moneypunct_cache<char, false>; + + // 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]; + } + // FIXME: use localeconv() not internal glibc NL items. +#if 0 + else + { + // Named locale. + _M_data->_M_decimal_point = *(nl_langinfo_l(__MON_DECIMAL_POINT, + __cloc)); + _M_data->_M_thousands_sep = *(nl_langinfo_l(__MON_THOUSANDS_SEP, + __cloc)); + + // Check for NULL, which implies no fractional digits. + if (_M_data->_M_decimal_point == '\0') + { + // Like in "C" locale. + _M_data->_M_frac_digits = 0; + _M_data->_M_decimal_point = '.'; + } + else + _M_data->_M_frac_digits = *(nl_langinfo_l(__FRAC_DIGITS, + __cloc)); + + const char* __cgroup = nl_langinfo_l(__MON_GROUPING, __cloc); + const char* __cpossign = nl_langinfo_l(__POSITIVE_SIGN, __cloc); + const char* __cnegsign = nl_langinfo_l(__NEGATIVE_SIGN, __cloc); + // _Intl == false + const char* __ccurr = nl_langinfo_l(__CURRENCY_SYMBOL, __cloc); + + char* __group = 0; + char* __ps = 0; + char* __ns = 0; + const char __nposn = *(nl_langinfo_l(__N_SIGN_POSN, __cloc)); + __try + { + size_t __len; + + // Check for NULL, which implies no grouping. + if (_M_data->_M_thousands_sep == '\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 + { + __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 = *(nl_langinfo_l(__P_CS_PRECEDES, __cloc)); + char __pspace = *(nl_langinfo_l(__P_SEP_BY_SPACE, __cloc)); + char __pposn = *(nl_langinfo_l(__P_SIGN_POSN, __cloc)); + _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, + __pposn); + char __nprecedes = *(nl_langinfo_l(__N_CS_PRECEDES, __cloc)); + char __nspace = *(nl_langinfo_l(__N_SEP_BY_SPACE, __cloc)); + _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, + __nposn); + } +#endif + } + + template<> + moneypunct<char, true>::~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<char, false>::~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<wchar_t, true>::_M_initialize_moneypunct(__c_locale __cloc, + const char*) + { + if (!_M_data) + _M_data = new __moneypunct_cache<wchar_t, true>; + + // 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<wchar_t>(money_base::_S_atoms[__i]); + } + // FIXME: use localeconv() not internal glibc _NL_xxx items. +#if 0 + else + { + // Named locale. + __c_locale __old = ::uselocale(__cloc); // FIXME: use RAII + + union { char *__s; wchar_t __w; } __u; + __u.__s = nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC, __cloc); + _M_data->_M_decimal_point = __u.__w; + + __u.__s = nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc); + _M_data->_M_thousands_sep = __u.__w; + + // Check for NULL, which implies no fractional digits. + if (_M_data->_M_decimal_point == L'\0') + { + // Like in "C" locale. + _M_data->_M_frac_digits = 0; + _M_data->_M_decimal_point = L'.'; + } + else + _M_data->_M_frac_digits = *(nl_langinfo_l(__INT_FRAC_DIGITS, + __cloc)); + + const char* __cgroup = nl_langinfo_l(__MON_GROUPING, __cloc); + const char* __cpossign = nl_langinfo_l(__POSITIVE_SIGN, __cloc); + const char* __cnegsign = nl_langinfo_l(__NEGATIVE_SIGN, __cloc); + const char* __ccurr = nl_langinfo_l(__INT_CURR_SYMBOL, __cloc); + + char* __group = 0; + wchar_t* __wcs_ps = 0; + wchar_t* __wcs_ns = 0; + const char __nposn = *(nl_langinfo_l(__INT_N_SIGN_POSN, __cloc)); + __try + { + size_t __len; + + // Check for NULL, which implies no grouping. + if (_M_data->_M_thousands_sep == L'\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 + { + __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(__old); + __throw_exception_again; + } + + char __pprecedes = *(nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc)); + char __pspace = *(nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc)); + char __pposn = *(nl_langinfo_l(__INT_P_SIGN_POSN, __cloc)); + _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, + __pposn); + char __nprecedes = *(nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc)); + char __nspace = *(nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc)); + _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, + __nposn); + + ::uselocale(__old); + } +#endif + } + + template<> + void + moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc, + const char*) + { + if (!_M_data) + _M_data = new __moneypunct_cache<wchar_t, false>; + + // 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<wchar_t>(money_base::_S_atoms[__i]); + } + // FIXME: use localeconv() not internal glibc _NL_xxx items. +#if 0 + else + { + // Named locale. + __c_locale __old = ::uselocale(__cloc); // FIXME: use RAII + + union { char *__s; wchar_t __w; } __u; + __u.__s = nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC, __cloc); + _M_data->_M_decimal_point = __u.__w; + + __u.__s = nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc); + _M_data->_M_thousands_sep = __u.__w; + + // Check for NULL, which implies no fractional digits. + if (_M_data->_M_decimal_point == L'\0') + { + // Like in "C" locale. + _M_data->_M_frac_digits = 0; + _M_data->_M_decimal_point = L'.'; + } + else + _M_data->_M_frac_digits = *(nl_langinfo_l(__FRAC_DIGITS, + __cloc)); + + const char* __cgroup = nl_langinfo_l(__MON_GROUPING, __cloc); + const char* __cpossign = nl_langinfo_l(__POSITIVE_SIGN, __cloc); + const char* __cnegsign = nl_langinfo_l(__NEGATIVE_SIGN, __cloc); + const char* __ccurr = nl_langinfo_l(__CURRENCY_SYMBOL, __cloc); + + char* __group = 0; + wchar_t* __wcs_ps = 0; + wchar_t* __wcs_ns = 0; + const char __nposn = *(nl_langinfo_l(__N_SIGN_POSN, __cloc)); + __try + { + size_t __len; + + // Check for NULL, which implies no grouping. + if (_M_data->_M_thousands_sep == L'\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 + { + __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(__old); + __throw_exception_again; + } + + char __pprecedes = *(nl_langinfo_l(__P_CS_PRECEDES, __cloc)); + char __pspace = *(nl_langinfo_l(__P_SEP_BY_SPACE, __cloc)); + char __pposn = *(nl_langinfo_l(__P_SIGN_POSN, __cloc)); + _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, + __pposn); + char __nprecedes = *(nl_langinfo_l(__N_CS_PRECEDES, __cloc)); + char __nspace = *(nl_langinfo_l(__N_SEP_BY_SPACE, __cloc)); + _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, + __nposn); + + ::uselocale(__old); + } +#endif + } + + template<> + moneypunct<wchar_t, true>::~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<wchar_t, false>::~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/ieee_1003.1-2008/numeric_members.cc b/libstdc++-v3/config/locale/ieee_1003.1-2008/numeric_members.cc new file mode 100644 index 00000000000..35af3fc2d5f --- /dev/null +++ b/libstdc++-v3/config/locale/ieee_1003.1-2008/numeric_members.cc @@ -0,0 +1,227 @@ +// std::numpunct implementation details, GNU version -*- C++ -*- + +// Copyright (C) 2001-2024 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 +// <http://www.gnu.org/licenses/>. + +// +// ISO C++ 14882: 22.2.3.1.2 numpunct virtual functions +// + +// Written by Benjamin Kosnik <b...@redhat.com> + +#define _POSIX_C_SOURCE 200809L + +#include <locale> +#include <cstring> +#include <langinfo.h> +#include <iconv.h> + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + extern char __narrow_multibyte_chars(const char* s, locale_t cloc); + +// This file might be compiled twice, but we only want to define this once. +#if ! _GLIBCXX_USE_CXX11_ABI + char + __narrow_multibyte_chars(const char* s, locale_t cloc) + { + const char* codeset = nl_langinfo_l(CODESET, cloc); + if (!strcmp(codeset, "UTF-8")) + { + // optimize for some known cases + if (!strcmp(s, "\u202F")) // NARROW NO-BREAK SPACE + return ' '; + if (!strcmp(s, "\u2019")) // RIGHT SINGLE QUOTATION MARK + return '\''; + if (!strcmp(s, "\u066C")) // ARABIC THOUSANDS SEPARATOR + return '\''; + } + + iconv_t cd = iconv_open("US-ASCII", codeset); + if (cd != (iconv_t)-1) + { + char c1; + size_t inbytesleft = strlen(s); + size_t outbytesleft = 1; + char* inbuf = const_cast<char*>(s); + char* outbuf = &c1; + size_t n = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft); + iconv_close(cd); + if (n != (size_t)-1) + { + cd = iconv_open(codeset, "ASCII"); + if (cd != (iconv_t)-1) + { + char c2; + inbuf = &c1; + inbytesleft = 1; + outbuf = &c2; + outbytesleft = 1; + n = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft); + iconv_close(cd); + if (n != (size_t)-1) + return c2; + } + } + } + return '\0'; + } +#endif + + template<> + void + numpunct<char>::_M_initialize_numpunct(__c_locale __cloc) + { + if (!_M_data) + _M_data = new __numpunct_cache<char>; + + 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. + _M_data->_M_decimal_point = *(nl_langinfo_l(RADIXCHAR, __cloc)); + const char* thousands_sep = nl_langinfo_l(THOUSEP, __cloc); + + if (thousands_sep[0] != '\0' && thousands_sep[1] != '\0') + _M_data->_M_thousands_sep = __narrow_multibyte_chars(thousands_sep, + __cloc); + else + _M_data->_M_thousands_sep = *thousands_sep; + + // Check for NULL, which implies no grouping. + if (_M_data->_M_thousands_sep == '\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 + { + locale_t orig = ::uselocale(__cloc); // FIXME: use RAII + const char* str = localeconv()->grouping; + if (size_t len = strlen(str)) + { + char* dest = new char[len + 1]; + memcpy(dest, str, len + 1); + _M_data->_M_grouping = dest; + _M_data->_M_grouping_size = len; + } + else + { + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + } + ::uselocale(orig); + } + } + + // NB: There is no way to extract this info from posix locales. + // _M_truename = nl_langinfo_l(YESEXPR, __cloc); + _M_data->_M_truename = "true"; + _M_data->_M_truename_size = 4; + // _M_falsename = nl_langinfo_l(NOEXPR, __cloc); + _M_data->_M_falsename = "false"; + _M_data->_M_falsename_size = 5; + } + + template<> + numpunct<char>::~numpunct() + { + if (_M_data->_M_grouping_size) + delete [] _M_data->_M_grouping; + delete _M_data; + } + +#ifdef _GLIBCXX_USE_WCHAR_T + template<> + void + numpunct<wchar_t>::_M_initialize_numpunct(__c_locale __cloc) + { + if (!_M_data) + _M_data = new __numpunct_cache<wchar_t>; + + // 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<wchar_t>(__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<wchar_t>(__num_base::_S_atoms_in[__j]); + } + // FIXME: use iconv to convert narrow strings to wide. +#if 0 + else + { + } +#endif + + // NB: There is no way to extract this info from posix locales. + // FIXME: Use iconv to convert narrow names to wide strings? + // _M_truename = nl_langinfo_l(YESEXPR, __cloc); + _M_data->_M_truename = L"true"; + _M_data->_M_truename_size = 4; + // _M_falsename = nl_langinfo_l(NOEXPR, __cloc); + _M_data->_M_falsename = L"false"; + _M_data->_M_falsename_size = 5; + } + + template<> + numpunct<wchar_t>::~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/ieee_1003.1-2008/time_members.cc b/libstdc++-v3/config/locale/ieee_1003.1-2008/time_members.cc new file mode 100644 index 00000000000..2945362bd55 --- /dev/null +++ b/libstdc++-v3/config/locale/ieee_1003.1-2008/time_members.cc @@ -0,0 +1,384 @@ +// std::time_get, std::time_put implementation, GNU version -*- C++ -*- + +// Copyright (C) 2001-2024 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 +// <http://www.gnu.org/licenses/>. + +// +// 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 <b...@redhat.com> + +#define _POSIX_C_SOURCE 200809L + +#include <locale> +#include <langinfo.h> + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template<> + void + __timepunct<char>:: + _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, + _M_c_locale_timepunct); + // Make sure __s is null terminated. + if (__len == 0) + __s[0] = '\0'; + } + + template<> + void + __timepunct<char>::_M_initialize_timepunct(__c_locale __cloc) + { + if (!_M_data) + _M_data = new __timepunct_cache<char>; + + 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_data->_M_date_format; + _M_data->_M_time_format = "%H:%M:%S"; + _M_data->_M_time_era_format = _M_data->_M_time_format; + _M_data->_M_date_time_format = "%a %b %e %T %Y"; + _M_data->_M_date_time_era_format = _M_data->_M_date_time_format; + _M_data->_M_am = "AM"; + _M_data->_M_pm = "PM"; + _M_data->_M_am_pm_format = "%I:%M:%S %p"; + + // 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, __cloc); + _M_data->_M_date_era_format = ::nl_langinfo_l(ERA_D_FMT, __cloc); + _M_data->_M_time_format = ::nl_langinfo_l(T_FMT, __cloc); + _M_data->_M_time_era_format = ::nl_langinfo_l(ERA_T_FMT, __cloc); + _M_data->_M_date_time_format = ::nl_langinfo_l(D_T_FMT, __cloc); + _M_data->_M_date_time_era_format = ::nl_langinfo_l(ERA_D_T_FMT, + __cloc); + _M_data->_M_am = ::nl_langinfo_l(AM_STR, __cloc); + _M_data->_M_pm = ::nl_langinfo_l(PM_STR, __cloc); + _M_data->_M_am_pm_format = ::nl_langinfo_l(T_FMT_AMPM, __cloc); + + // Day names, starting with "C"'s Sunday. + _M_data->_M_day1 = ::nl_langinfo_l(DAY_1, __cloc); + _M_data->_M_day2 = ::nl_langinfo_l(DAY_2, __cloc); + _M_data->_M_day3 = ::nl_langinfo_l(DAY_3, __cloc); + _M_data->_M_day4 = ::nl_langinfo_l(DAY_4, __cloc); + _M_data->_M_day5 = ::nl_langinfo_l(DAY_5, __cloc); + _M_data->_M_day6 = ::nl_langinfo_l(DAY_6, __cloc); + _M_data->_M_day7 = ::nl_langinfo_l(DAY_7, __cloc); + + // Abbreviated day names, starting with "C"'s Sun. + _M_data->_M_aday1 = ::nl_langinfo_l(ABDAY_1, __cloc); + _M_data->_M_aday2 = ::nl_langinfo_l(ABDAY_2, __cloc); + _M_data->_M_aday3 = ::nl_langinfo_l(ABDAY_3, __cloc); + _M_data->_M_aday4 = ::nl_langinfo_l(ABDAY_4, __cloc); + _M_data->_M_aday5 = ::nl_langinfo_l(ABDAY_5, __cloc); + _M_data->_M_aday6 = ::nl_langinfo_l(ABDAY_6, __cloc); + _M_data->_M_aday7 = ::nl_langinfo_l(ABDAY_7, __cloc); + + // Month names, starting with "C"'s January. + _M_data->_M_month01 = ::nl_langinfo_l(MON_1, __cloc); + _M_data->_M_month02 = ::nl_langinfo_l(MON_2, __cloc); + _M_data->_M_month03 = ::nl_langinfo_l(MON_3, __cloc); + _M_data->_M_month04 = ::nl_langinfo_l(MON_4, __cloc); + _M_data->_M_month05 = ::nl_langinfo_l(MON_5, __cloc); + _M_data->_M_month06 = ::nl_langinfo_l(MON_6, __cloc); + _M_data->_M_month07 = ::nl_langinfo_l(MON_7, __cloc); + _M_data->_M_month08 = ::nl_langinfo_l(MON_8, __cloc); + _M_data->_M_month09 = ::nl_langinfo_l(MON_9, __cloc); + _M_data->_M_month10 = ::nl_langinfo_l(MON_10, __cloc); + _M_data->_M_month11 = ::nl_langinfo_l(MON_11, __cloc); + _M_data->_M_month12 = ::nl_langinfo_l(MON_12, __cloc); + + // Abbreviated month names, starting with "C"'s Jan. + _M_data->_M_amonth01 = ::nl_langinfo_l(ABMON_1, __cloc); + _M_data->_M_amonth02 = ::nl_langinfo_l(ABMON_2, __cloc); + _M_data->_M_amonth03 = ::nl_langinfo_l(ABMON_3, __cloc); + _M_data->_M_amonth04 = ::nl_langinfo_l(ABMON_4, __cloc); + _M_data->_M_amonth05 = ::nl_langinfo_l(ABMON_5, __cloc); + _M_data->_M_amonth06 = ::nl_langinfo_l(ABMON_6, __cloc); + _M_data->_M_amonth07 = ::nl_langinfo_l(ABMON_7, __cloc); + _M_data->_M_amonth08 = ::nl_langinfo_l(ABMON_8, __cloc); + _M_data->_M_amonth09 = ::nl_langinfo_l(ABMON_9, __cloc); + _M_data->_M_amonth10 = ::nl_langinfo_l(ABMON_10, __cloc); + _M_data->_M_amonth11 = ::nl_langinfo_l(ABMON_11, __cloc); + _M_data->_M_amonth12 = ::nl_langinfo_l(ABMON_12, __cloc); + } + } + +#ifdef _GLIBCXX_USE_WCHAR_T + template<> + void + __timepunct<wchar_t>:: + _M_put(wchar_t* __s, size_t __maxlen, const wchar_t* __format, + const tm* __tm) const throw() + { + locale_t orig = ::uselocale(_M_c_locale_timepunct); + const size_t __len = wcsftime(__s, __maxlen, __format, __tm); + ::uselocale(orig); + // Make sure __s is null terminated. + if (__len == 0) + __s[0] = L'\0'; + } + + template<> + void + __timepunct<wchar_t>::_M_initialize_timepunct(__c_locale __cloc) + { + if (!_M_data) + _M_data = new __timepunct_cache<wchar_t>; + + // 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 = _M_data->_M_date_format; + _M_data->_M_time_format = L"%H:%M:%S"; + _M_data->_M_time_era_format = _M_data->_M_time_format; + _M_data->_M_date_time_format = L"%a %b %e %T %Y"; + _M_data->_M_date_time_era_format = _M_data->_M_date_time_format; + _M_data->_M_am = L"AM"; + _M_data->_M_pm = L"PM"; + _M_data->_M_am_pm_format = L"%I:%M:%S %p"; + + // 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"; + } + // FIXME: use iconv to get wide strings? +#if 0 + else + { + _M_c_locale_timepunct = _S_clone_c_locale(__cloc); + + union { char *__s; wchar_t *__w; } __u; + + __u.__s = ::nl_langinfo_l(_NL_WD_FMT, __cloc); + _M_data->_M_date_format = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WERA_D_FMT, __cloc); + _M_data->_M_date_era_format = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WT_FMT, __cloc); + _M_data->_M_time_format = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WERA_T_FMT, __cloc); + _M_data->_M_time_era_format = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WD_T_FMT, __cloc); + _M_data->_M_date_time_format = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WERA_D_T_FMT, __cloc); + _M_data->_M_date_time_era_format = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WAM_STR, __cloc); + _M_data->_M_am = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WPM_STR, __cloc); + _M_data->_M_pm = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WT_FMT_AMPM, __cloc); + _M_data->_M_am_pm_format = __u.__w; + + // Day names, starting with "C"'s Sunday. + __u.__s = ::nl_langinfo_l(_NL_WDAY_1, __cloc); + _M_data->_M_day1 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WDAY_2, __cloc); + _M_data->_M_day2 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WDAY_3, __cloc); + _M_data->_M_day3 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WDAY_4, __cloc); + _M_data->_M_day4 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WDAY_5, __cloc); + _M_data->_M_day5 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WDAY_6, __cloc); + _M_data->_M_day6 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WDAY_7, __cloc); + _M_data->_M_day7 = __u.__w; + + // Abbreviated day names, starting with "C"'s Sun. + __u.__s = ::nl_langinfo_l(_NL_WABDAY_1, __cloc); + _M_data->_M_aday1 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WABDAY_2, __cloc); + _M_data->_M_aday2 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WABDAY_3, __cloc); + _M_data->_M_aday3 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WABDAY_4, __cloc); + _M_data->_M_aday4 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WABDAY_5, __cloc); + _M_data->_M_aday5 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WABDAY_6, __cloc); + _M_data->_M_aday6 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WABDAY_7, __cloc); + _M_data->_M_aday7 = __u.__w; + + // Month names, starting with "C"'s January. + __u.__s = ::nl_langinfo_l(_NL_WMON_1, __cloc); + _M_data->_M_month01 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WMON_2, __cloc); + _M_data->_M_month02 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WMON_3, __cloc); + _M_data->_M_month03 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WMON_4, __cloc); + _M_data->_M_month04 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WMON_5, __cloc); + _M_data->_M_month05 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WMON_6, __cloc); + _M_data->_M_month06 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WMON_7, __cloc); + _M_data->_M_month07 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WMON_8, __cloc); + _M_data->_M_month08 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WMON_9, __cloc); + _M_data->_M_month09 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WMON_10, __cloc); + _M_data->_M_month10 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WMON_11, __cloc); + _M_data->_M_month11 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WMON_12, __cloc); + _M_data->_M_month12 = __u.__w; + + // Abbreviated month names, starting with "C"'s Jan. + __u.__s = ::nl_langinfo_l(_NL_WABMON_1, __cloc); + _M_data->_M_amonth01 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WABMON_2, __cloc); + _M_data->_M_amonth02 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WABMON_3, __cloc); + _M_data->_M_amonth03 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WABMON_4, __cloc); + _M_data->_M_amonth04 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WABMON_5, __cloc); + _M_data->_M_amonth05 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WABMON_6, __cloc); + _M_data->_M_amonth06 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WABMON_7, __cloc); + _M_data->_M_amonth07 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WABMON_8, __cloc); + _M_data->_M_amonth08 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WABMON_9, __cloc); + _M_data->_M_amonth09 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WABMON_10, __cloc); + _M_data->_M_amonth10 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WABMON_11, __cloc); + _M_data->_M_amonth11 = __u.__w; + __u.__s = ::nl_langinfo_l(_NL_WABMON_12, __cloc); + _M_data->_M_amonth12 = __u.__w; + } +#endif + } +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace diff --git a/libstdc++-v3/config/locale/ieee_1003.1-2008/time_members.h b/libstdc++-v3/config/locale/ieee_1003.1-2008/time_members.h new file mode 100644 index 00000000000..92680315873 --- /dev/null +++ b/libstdc++-v3/config/locale/ieee_1003.1-2008/time_members.h @@ -0,0 +1,89 @@ +// std::time_get, std::time_put implementation, GNU version -*- C++ -*- + +// Copyright (C) 2001-2024 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 +// <http://www.gnu.org/licenses/>. + +/** @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 <b...@redhat.com> + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template<typename _CharT> + __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<typename _CharT> + __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<typename _CharT> + __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<typename _CharT> + __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); + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace diff --git a/libstdc++-v3/config/os/bsd/freebsd/ctype_inline.h b/libstdc++-v3/config/os/bsd/freebsd/ctype_inline.h index 0f678ebf983..fc5287e9689 100644 --- a/libstdc++-v3/config/os/bsd/freebsd/ctype_inline.h +++ b/libstdc++-v3/config/os/bsd/freebsd/ctype_inline.h @@ -112,6 +112,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } #ifdef _GLIBCXX_USE_WCHAR_T +#define _GLIBCXX_CTYPE_INLINE_WCHAR_MEMBERS 1 inline bool ctype<wchar_t>:: do_is(mask __m, wchar_t __c) const diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure index e115ee55739..84eb76f17ec 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|ieee_1003.1-2008|posix-2001|posix-2008|newlib|yes|no|auto) ;; *) as_fn_error $? "Unknown argument to enable/disable clocale" "$LINENO" 5 ;; esac @@ -16660,6 +16660,10 @@ fi # Either a known package, or "auto" if test $enable_clocale = no || test $enable_clocale = yes; then enable_clocale=auto + elif test $enable_clocale = posix-2001; then + enable_clocale=ieee_1003.1-2001 + elif test $enable_clocale = posix-2008; then + enable_clocale=ieee_1003.1-2008 fi enable_clocale_flag=$enable_clocale @@ -16931,8 +16935,8 @@ fi CLOCALE_INTERNAL_H=config/locale/gnu/c++locale_internal.h ;; ieee_1003.1-2001) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: IEEE 1003.1" >&5 -$as_echo "IEEE 1003.1" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: IEEE 1003.1-2001" >&5 +$as_echo "IEEE 1003.1-2001" >&6; } CLOCALE_H=config/locale/ieee_1003.1-2001/c_locale.h CLOCALE_CC=config/locale/ieee_1003.1-2001/c_locale.cc @@ -16947,6 +16951,25 @@ $as_echo "IEEE 1003.1" >&6; } CTIME_CC=config/locale/generic/time_members.cc CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h ;; + + ieee_1003.1-2008) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: IEEE 1003.1-2008" >&5 +$as_echo "IEEE 1003.1-2008" >&6; } + + 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/ieee_1003.1-2001/messages_members.h + CMESSAGES_CC=config/locale/ieee_1003.1-2001/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) { $as_echo "$as_me:${as_lineno-$LINENO}: result: newlib" >&5 $as_echo "newlib" >&6; } diff --git a/libstdc++-v3/include/bits/locale_facets_nonio.h b/libstdc++-v3/include/bits/locale_facets_nonio.h index 5a90e1e6ac6..7cb0e9c4fad 100644 --- a/libstdc++-v3/include/bits/locale_facets_nonio.h +++ b/libstdc++-v3/include/bits/locale_facets_nonio.h @@ -1823,9 +1823,16 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 * @brief Messages facet base class providing catalog typedef. * @ingroup locales */ - struct messages_base + class messages_base { + public: +#ifdef _GLIBCXX_MESSAGES_BASE_CATALOG_TYPE + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2028. messages_base::catalog overspecified + typedef _GLIBCXX_MESSAGES_BASE_CATALOG_TYPE catalog; +#else typedef int catalog; +#endif }; _GLIBCXX_BEGIN_NAMESPACE_CXX11 -- 2.47.0