public inbox for cygwin@cygwin.com
 help / color / mirror / Atom feed
From: Takashi Yano <takashi.yano@nifty.ne.jp>
To: cygwin@cygwin.com
Subject: Re: std::runtime_error on std::locale("")
Date: Wed, 27 Sep 2023 19:50:39 +0900	[thread overview]
Message-ID: <20230927195039.e62f7482898ab5615cc1605b@nifty.ne.jp> (raw)
In-Reply-To: <20230923172359.d854a5a98afbc44beaf50c78@nifty.ne.jp>

[-- Attachment #1: Type: text/plain, Size: 1497 bytes --]

Hi Achim,

On Sat, 23 Sep 2023 17:23:59 +0900
Takashi Yano via Cygwin <cygwin@cygwin.com> wrote:
> On Fri, 22 Sep 2023 08:48:45 +0200
> ASSI  wrote:
> > Takashi Yano via Cygwin writes:
> > > I wonder why the following code throws std::runtime_error
> > > even though the LC_ALL is set to valid locale other than "C".
> > > This does not occur only when LC_ALL is set to "C".
> > 
> > This functionality is currently only supported for Glibc targets in
> > libstdc++.  I seem to remember that I've looked into this some time ago,
> > but there didn't seem to be an easy way of enabling it for Cygwin at
> > that time.
> 
> Thanks for the answer.
> 
> It might not be an easy way, but I tried to enabling the locale
> feature for libstdc++.
> 
> Please try:
> 
> 1) Run cygport gcc prep
> 2) Remove libstdc++-v3/config/locale/generic
> 3) Copy libstdc++-v3/config/locale/gnu to libstdc++-v3/config/locale/generic
> 4) Apply patches attached to the working source directory.
> 5) Run cygport gcc compile
> 
> I also tried to automate above steps in gcc.cygport.
> 
> Further, I tested and confirmed that a few test cases works as expected.
> 
> What do you think of this idea?

I have a new revised draft patch. The patch attached is against
the HEAD of upstream gcc repository. However, it can be applied
to 11.4.0 as well if s/c++11/c++98/g.

This is not a last-minute job like last time, but a full rework.

Any advice or comment would be appreciated.

-- 
Takashi Yano <takashi.yano@nifty.ne.jp>

[-- Attachment #2: 0001-libstdc-Implement-most-of-locale-features-for-newlib.patch --]
[-- Type: text/plain, Size: 111280 bytes --]

From 02685bbf7643f62d1a8b380b6049c37edfdf431a Mon Sep 17 00:00:00 2001
From: Takashi Yano <takashi.yano@nifty.ne.jp>
Date: Sun, 24 Sep 2023 13:13:08 +0900
Subject: [PATCH] libstdc++: Implement most of locale features for newlib.

Previously, locale implementation for newlib supports only "C" locale.
With this patch, the locale implementation for newlib has been much
improved using newlib functionality currently supported so that most
of locale features can be used. The most of the codes are based on
the implementation for the GNU libc.
---
 libstdc++-v3/Makefile.in                      |   1 +
 libstdc++-v3/acinclude.m4                     |  28 +-
 .../config/locale/dragonfly/c_locale.cc       |   1 +
 .../config/locale/generic/c_locale.cc         |   1 +
 libstdc++-v3/config/locale/gnu/c_locale.cc    |   1 +
 .../locale/ieee_1003.1-2001/c_locale.cc       |   2 +
 .../config/locale/newlib/c++locale_internal.h |  95 ++
 libstdc++-v3/config/locale/newlib/c_locale.cc | 384 +++++++
 libstdc++-v3/config/locale/newlib/c_locale.h  |  82 ++
 .../config/locale/newlib/codecvt_members.cc   | 288 ++++++
 .../config/locale/newlib/collate_members.cc   |  74 ++
 .../config/locale/newlib/ctype_members.cc     |  58 +-
 .../config/locale/newlib/messages_members.cc  | 173 ++++
 .../config/locale/newlib/messages_members.h   | 152 +++
 .../config/locale/newlib/monetary_members.cc  | 942 ++++++++++++++++++
 .../config/locale/newlib/numeric_members.cc   | 282 ++++++
 .../config/locale/newlib/time_members.cc      | 379 +++++++
 .../config/locale/newlib/time_members.h       |  90 ++
 libstdc++-v3/configure                        |  29 +-
 libstdc++-v3/src/Makefile.in                  |   3 +-
 libstdc++-v3/src/c++11/locale_init.cc         |   3 +-
 21 files changed, 3016 insertions(+), 52 deletions(-)
 create mode 100644 libstdc++-v3/config/locale/newlib/c++locale_internal.h
 create mode 100644 libstdc++-v3/config/locale/newlib/c_locale.cc
 create mode 100644 libstdc++-v3/config/locale/newlib/c_locale.h
 create mode 100644 libstdc++-v3/config/locale/newlib/codecvt_members.cc
 create mode 100644 libstdc++-v3/config/locale/newlib/collate_members.cc
 create mode 100644 libstdc++-v3/config/locale/newlib/messages_members.cc
 create mode 100644 libstdc++-v3/config/locale/newlib/messages_members.h
 create mode 100644 libstdc++-v3/config/locale/newlib/monetary_members.cc
 create mode 100644 libstdc++-v3/config/locale/newlib/numeric_members.cc
 create mode 100644 libstdc++-v3/config/locale/newlib/time_members.cc
 create mode 100644 libstdc++-v3/config/locale/newlib/time_members.h

diff --git a/libstdc++-v3/Makefile.in b/libstdc++-v3/Makefile.in
index 500c0d75282..c05d20e2568 100644
--- a/libstdc++-v3/Makefile.in
+++ b/libstdc++-v3/Makefile.in
@@ -244,6 +244,7 @@ ERROR_CONSTANTS_SRCDIR = @ERROR_CONSTANTS_SRCDIR@
 EXEEXT = @EXEEXT@
 EXTRA_CFLAGS = @EXTRA_CFLAGS@
 EXTRA_CXX_FLAGS = @EXTRA_CXX_FLAGS@
+EXTRA_LIBS = @EXTRA_LIBS@
 FGREP = @FGREP@
 FORMAT_FILE = @FORMAT_FILE@
 FREESTANDING_FLAGS = @FREESTANDING_FLAGS@
diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index d8f0ba1c3e2..202b3c475cf 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -2807,7 +2807,7 @@ AC_DEFUN([GLIBCXX_ENABLE_CLOCALE], [
       dragonfly* | freebsd*)
 	enable_clocale_flag=dragonfly
 	;;
-      openbsd*)
+      openbsd* | cygwin*)
 	enable_clocale_flag=newlib
 	;;
       *)
@@ -2819,6 +2819,10 @@ AC_DEFUN([GLIBCXX_ENABLE_CLOCALE], [
 	;;
     esac
   fi
+  case ${target_os} in cygwin*)
+    EXTRA_LIBS="-lintl"
+    ;;
+  esac
 
   # Sanity check model, and test for special functionality.
   if test $enable_clocale_flag = gnu; then
@@ -2984,18 +2988,18 @@ AC_DEFUN([GLIBCXX_ENABLE_CLOCALE], [
     newlib)
       AC_MSG_RESULT(newlib)
 
-      CLOCALE_H=config/locale/generic/c_locale.h
-      CLOCALE_CC=config/locale/generic/c_locale.cc
-      CCODECVT_CC=config/locale/generic/codecvt_members.cc
-      CCOLLATE_CC=config/locale/generic/collate_members.cc
+      CLOCALE_H=config/locale/newlib/c_locale.h
+      CLOCALE_CC=config/locale/newlib/c_locale.cc
+      CCODECVT_CC=config/locale/newlib/codecvt_members.cc
+      CCOLLATE_CC=config/locale/newlib/collate_members.cc
       CCTYPE_CC=config/locale/newlib/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
-      CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h
+      CMESSAGES_H=config/locale/newlib/messages_members.h
+      CMESSAGES_CC=config/locale/newlib/messages_members.cc
+      CMONEY_CC=config/locale/newlib/monetary_members.cc
+      CNUMERIC_CC=config/locale/newlib/numeric_members.cc
+      CTIME_H=config/locale/newlib/time_members.h
+      CTIME_CC=config/locale/newlib/time_members.cc
+      CLOCALE_INTERNAL_H=config/locale/newlib/c++locale_internal.h
       ;;
   esac
 
diff --git a/libstdc++-v3/config/locale/dragonfly/c_locale.cc b/libstdc++-v3/config/locale/dragonfly/c_locale.cc
index f026e17d5a0..0e10188f220 100644
--- a/libstdc++-v3/config/locale/dragonfly/c_locale.cc
+++ b/libstdc++-v3/config/locale/dragonfly/c_locale.cc
@@ -188,6 +188,7 @@ namespace std _GLIBCXX_VISIBILITY(default)
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   const char* const* const locale::_S_categories = __gnu_cxx::category_names;
+  const __typeof(setlocale) *__setlocale = setlocale;
 
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
diff --git a/libstdc++-v3/config/locale/generic/c_locale.cc b/libstdc++-v3/config/locale/generic/c_locale.cc
index 8849d78fdfa..27a246921e6 100644
--- a/libstdc++-v3/config/locale/generic/c_locale.cc
+++ b/libstdc++-v3/config/locale/generic/c_locale.cc
@@ -284,6 +284,7 @@ namespace std _GLIBCXX_VISIBILITY(default)
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   const char* const* const locale::_S_categories = __gnu_cxx::category_names;
+  const __typeof(setlocale) *__setlocale = setlocale;
 
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
diff --git a/libstdc++-v3/config/locale/gnu/c_locale.cc b/libstdc++-v3/config/locale/gnu/c_locale.cc
index 5ddbde1e6cc..55271b6161b 100644
--- a/libstdc++-v3/config/locale/gnu/c_locale.cc
+++ b/libstdc++-v3/config/locale/gnu/c_locale.cc
@@ -283,6 +283,7 @@ namespace std _GLIBCXX_VISIBILITY(default)
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   const char* const* const locale::_S_categories = __gnu_cxx::category_names;
+  const __typeof(setlocale) *__setlocale = setlocale;
 
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
diff --git a/libstdc++-v3/config/locale/ieee_1003.1-2001/c_locale.cc b/libstdc++-v3/config/locale/ieee_1003.1-2001/c_locale.cc
index c91183e2f8c..287234a8c67 100644
--- a/libstdc++-v3/config/locale/ieee_1003.1-2001/c_locale.cc
+++ b/libstdc++-v3/config/locale/ieee_1003.1-2001/c_locale.cc
@@ -103,5 +103,7 @@ namespace std _GLIBCXX_VISIBILITY(default)
       _M_neg_format = money_base::_S_default_pattern;
     }
 #endif
+
+  const __typeof(setlocale) *__setlocale = setlocale;
 }  // namespace std
 
diff --git a/libstdc++-v3/config/locale/newlib/c++locale_internal.h b/libstdc++-v3/config/locale/newlib/c++locale_internal.h
new file mode 100644
index 00000000000..351d4566b3a
--- /dev/null
+++ b/libstdc++-v3/config/locale/newlib/c++locale_internal.h
@@ -0,0 +1,95 @@
+// Locale internal implementation header -*- C++ -*-
+
+// Copyright (C) 2002-2023 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_internal.h
+ *  This is an internal header file, included by other library headers.
+ *  Do not attempt to use it directly. @headername{locale}
+ */
+
+// Written by Jakub Jelinek <jakub@redhat.com>
+// Modified by Takashi Yano <takashi.yano@nifty.ne.jp>
+
+#include <bits/c++config.h>
+#include <clocale>
+#include <cstdlib>
+#include <cstring>
+#include <cstddef>
+#include <langinfo.h>
+
+#include <vector>
+#include <string.h>	// ::strdup
+
+#include <ext/concurrence.h>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  struct Catalog_info
+  {
+    Catalog_info(messages_base::catalog __id, const char* __domain,
+		 locale __loc)
+      : _M_id(__id), _M_domain(strdup(__domain)), _M_locale(__loc)
+    { }
+
+    ~Catalog_info()
+    { free(_M_domain); }
+
+    messages_base::catalog _M_id;
+    char* _M_domain;
+    locale _M_locale;
+
+  private:
+    Catalog_info(const Catalog_info&);
+
+    Catalog_info&
+    operator=(const Catalog_info&);
+  };
+
+  class Catalogs
+  {
+  public:
+    Catalogs() : _M_catalog_counter(0) { }
+    ~Catalogs();
+
+    messages_base::catalog
+    _M_add(const char* __domain, locale __l);
+
+    void
+    _M_erase(messages_base::catalog __c);
+
+    const Catalog_info*
+    _M_get(messages_base::catalog __c) const;
+
+  private:
+    mutable __gnu_cxx::__mutex _M_mutex;
+    messages_base::catalog _M_catalog_counter;
+    vector<Catalog_info*> _M_infos;
+  };
+
+  Catalogs&
+  get_catalogs();
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
diff --git a/libstdc++-v3/config/locale/newlib/c_locale.cc b/libstdc++-v3/config/locale/newlib/c_locale.cc
new file mode 100644
index 00000000000..c49e575394b
--- /dev/null
+++ b/libstdc++-v3/config/locale/newlib/c_locale.cc
@@ -0,0 +1,384 @@
+// Wrapper for underlying C-language localization -*- C++ -*-
+
+// Copyright (C) 2001-2023 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 <bkoz@redhat.com>
+// Modified by Takashi Yano <takashi.yano@nifty.ne.jp>
+
+#define _GNU_SOURCE 1
+#include <cstdio>
+#include <locale>
+#include <stdexcept>
+#include <limits>
+#include <algorithm>
+#include <langinfo.h>
+#include <bits/c++locale_internal.h>
+
+#include <backward/auto_ptr.h>
+
+/* Newlib constatnt */
+#define ENCODING_LEN 31
+#define CATEGORY_LEN 11
+#define NUM_CATEGORIES 6
+#define xstr(s) str(s)
+#define str(s) #s
+#define FMT_LOCALE "%" xstr(CATEGORY_LEN) "[^=]=%" xstr(ENCODING_LEN) "[^;]"
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  template<>
+    void
+    __convert_to_v(const char* __s, float& __v, ios_base::iostate& __err,
+		   const __c_locale& __cloc) throw()
+    {
+      char* __sanity;
+      __v = strtof_l(__s, &__sanity, __cloc);
+
+      // _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()
+    {
+      char* __sanity;
+      __v = strtod_l(__s, &__sanity, __cloc);
+
+      // _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()
+    {
+      char* __sanity;
+      __v = strtold_l(__s, &__sanity, __cloc);
+
+      // _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(1 << LC_ALL, __s, __old);
+    if (__cloc)
+      return;
+
+    /* Newlib does not support locale strig such as
+       "LC_CTYPE=en_US.UTF8;LC_NUMERIC=de_DE.UTF8;..." */
+    const char *__p = __s;
+    __cloc = __old;
+    char __cat[CATEGORY_LEN + 1], __loc[ENCODING_LEN + 1];
+    while (2 == sscanf(__p, FMT_LOCALE, __cat, __loc))
+      {
+	struct {const char *__cat; int __mask;} __tbl[NUM_CATEGORIES + 1] =
+	  {
+	      {"LC_CTYPE", LC_CTYPE_MASK},
+	      {"LC_NUMERIC", LC_NUMERIC_MASK},
+	      {"LC_TIME", LC_TIME_MASK},
+	      {"LC_COLLATE", LC_COLLATE_MASK},
+	      {"LC_MONETARY", LC_MONETARY_MASK},
+	      {"LC_MESSAGES", LC_MESSAGES_MASK},
+	      {NULL, 0}
+	  };
+	for (int __i = 0; __tbl[__i].__cat; __i++)
+	  if (strcmp(__tbl[__i].__cat, __cat) == 0)
+	    {
+	      __cloc = newlocale(__tbl[__i].__mask, __loc, __cloc);
+	      break;
+	    }
+	if (!__cloc)
+	  break;
+	if ((__p = strchr(__p, ';')) == NULL)
+	  break;
+	__p++;
+      }
+    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))
+      {
+	/* Newlib does not support locale strig such as
+	   "LC_CTYPE=en_US.UTF8;LC_NUMERIC=de_DE.UTF8;..." */
+	const char *__p = __s;
+	char __cat[CATEGORY_LEN + 1], __loc[ENCODING_LEN + 1];
+	while (2 == sscanf(__p, FMT_LOCALE, __cat, __loc))
+	  {
+	    if (strcmp("LC_CTYPE", __cat) == 0)
+	      {
+		__changed = newlocale(LC_CTYPE_MASK, __loc, __dup);
+		break;
+	      }
+	    if ((__p = strchr(__p, ';')) == NULL)
+	      break;
+	    __p++;
+	  }
+      }
+    if (__changed == __c_locale(0))
+      {
+	freelocale(__dup);
+	__throw_runtime_error(__N("locale::facet::_S_lc_ctype_c_locale "
+				  "newlocale error"));
+      }
+    return __changed;
+  }
+
+  struct _CatalogIdComp
+  {
+    bool
+    operator()(messages_base::catalog __cat, const Catalog_info* __info) const
+    { return __cat < __info->_M_id; }
+
+    bool
+    operator()(const Catalog_info* __info, messages_base::catalog __cat) const
+    { return __info->_M_id < __cat; }
+  };
+
+  Catalogs::~Catalogs()
+  {
+    for (vector<Catalog_info*>::iterator __it = _M_infos.begin();
+	 __it != _M_infos.end(); ++__it)
+      delete *__it;
+  }
+
+  messages_base::catalog
+  Catalogs::_M_add(const char* __domain, locale __l)
+  {
+    __gnu_cxx::__scoped_lock lock(_M_mutex);
+
+    // The counter is not likely to roll unless catalogs keep on being
+    // opened/closed which is consider as an application mistake for the
+    // moment.
+    if (_M_catalog_counter == numeric_limits<messages_base::catalog>::max())
+      return -1;
+
+    auto_ptr<Catalog_info> info(new Catalog_info(_M_catalog_counter++,
+						 __domain, __l));
+
+    // Check if we managed to allocate memory for domain.
+    if (!info->_M_domain)
+      return -1;
+
+    _M_infos.push_back(info.get());
+    return info.release()->_M_id;
+  }
+
+  void
+  Catalogs::_M_erase(messages_base::catalog __c)
+  {
+    __gnu_cxx::__scoped_lock lock(_M_mutex);
+
+    vector<Catalog_info*>::iterator __res =
+      lower_bound(_M_infos.begin(), _M_infos.end(), __c, _CatalogIdComp());
+    if (__res == _M_infos.end() || (*__res)->_M_id != __c)
+      return;
+
+    delete *__res;
+    _M_infos.erase(__res);
+
+    // Just in case closed catalog was the last open.
+    if (__c == _M_catalog_counter - 1)
+      --_M_catalog_counter;
+  }
+
+  const Catalog_info*
+  Catalogs::_M_get(messages_base::catalog __c) const
+  {
+    __gnu_cxx::__scoped_lock lock(_M_mutex);
+
+    vector<Catalog_info*>::const_iterator __res =
+      lower_bound(_M_infos.begin(), _M_infos.end(), __c, _CatalogIdComp());
+
+    if (__res != _M_infos.end() && (*__res)->_M_id == __c)
+      return *__res;
+
+    return 0;
+  }
+
+  Catalogs&
+  get_catalogs()
+  {
+    static Catalogs __catalogs;
+    return __catalogs;
+  }
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  const char* const category_names[NUM_CATEGORIES] =
+    {
+      "LC_CTYPE",
+      "LC_NUMERIC",
+      "LC_TIME",
+      "LC_COLLATE",
+      "LC_MONETARY",
+      "LC_MESSAGES",
+    };
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+static char *
+__setlocale_for_newlib(int __category, const char *__locale)
+{
+  char *__ret;
+  if ((__ret = setlocale(__category, __locale)) == NULL
+      && __category == LC_ALL)
+    {
+      /* Newlib does not support locale strig such as
+	 "LC_CTYPE=en_US.UTF8;LC_NUMERIC=de_DE.UTF8;..." */
+      char __buf[NUM_CATEGORIES][ENCODING_LEN + 1];
+      const char *__p = __locale;
+      char __cat[CATEGORY_LEN + 1], __loc[ENCODING_LEN + 1];
+      while (2 == sscanf(__p, FMT_LOCALE, __cat, __loc))
+	{
+	  const char *__tbl[NUM_CATEGORIES] =
+	    {
+	      "LC_COLLATE",
+	      "LC_CTYPE",
+	      "LC_MONETARY",
+	      "LC_NUMERIC",
+	      "LC_TIME",
+	      "LC_MESSAGES"
+	    };
+	  for (int __i = 0; __i < NUM_CATEGORIES; __i++)
+	    if (strcmp(__tbl[__i], __cat) == 0)
+	      {
+		strncpy(__buf[__i], __loc, sizeof(__buf[__i]));
+		__buf[__i][ENCODING_LEN] = '\0';
+		break;
+	      }
+	  if ((__p = strchr(__p, ';')) == NULL)
+	    break;
+	  __p ++;
+	}
+      char __newloc[(ENCODING_LEN + 1) * NUM_CATEGORIES];
+      sprintf(__newloc, "%s/%s/%s/%s/%s/%s",
+	      __buf[0], __buf[1], __buf[2], __buf[3], __buf[4], __buf[5]);
+      __ret = setlocale(__category, __newloc);
+
+    }
+  return __ret;
+}
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  const char* const* const locale::_S_categories = __gnu_cxx::category_names;
+  const __typeof(setlocale) *__setlocale = __setlocale_for_newlib;
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+// XXX GLIBCXX_ABI Deprecated
+#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);
+#endif // _GLIBCXX_LONG_DOUBLE_COMPAT
diff --git a/libstdc++-v3/config/locale/newlib/c_locale.h b/libstdc++-v3/config/locale/newlib/c_locale.h
new file mode 100644
index 00000000000..4629103525f
--- /dev/null
+++ b/libstdc++-v3/config/locale/newlib/c_locale.h
@@ -0,0 +1,82 @@
+// Wrapper for underlying C-language localization -*- C++ -*-
+
+// Copyright (C) 2001-2023 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 <bkoz@redhat.com>
+// Modified by Takashi Yano <takashi.yano@nifty.ne.jp>
+
+#ifndef _GLIBCXX_CXX_LOCALE_H
+#define _GLIBCXX_CXX_LOCALE_H 1
+
+#pragma GCC system_header
+
+#include <clocale>
+
+#define _GLIBCXX_NUM_CATEGORIES 0
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  typedef locale_t __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 __attribute__ ((__unused__)),
+		   char* __out,
+		   const int __size __attribute__ ((__unused__)),
+		   const char* __fmt, ...)
+  {
+    __c_locale __old = uselocale(__cloc);
+
+    __builtin_va_list __args;
+    __builtin_va_start(__args, __fmt);
+
+#if _GLIBCXX_USE_C99_STDIO
+    const int __ret = __builtin_vsnprintf(__out, __size, __fmt, __args);
+#else
+    const int __ret = __builtin_vsprintf(__out, __fmt, __args);
+#endif
+
+    __builtin_va_end(__args);
+
+    uselocale(__old);
+    return __ret;
+  }
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+#endif
diff --git a/libstdc++-v3/config/locale/newlib/codecvt_members.cc b/libstdc++-v3/config/locale/newlib/codecvt_members.cc
new file mode 100644
index 00000000000..e483542ceb4
--- /dev/null
+++ b/libstdc++-v3/config/locale/newlib/codecvt_members.cc
@@ -0,0 +1,288 @@
+// std::codecvt implementation details, newlib version -*- C++ -*-
+
+// Copyright (C) 2002-2023 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 <bkoz@redhat.com>
+// Modified by Takashi Yano <takashi.yano@nifty.ne.jp>
+
+#include <locale>
+#include <cstdlib>  // For MB_CUR_MAX
+#include <climits>  // For MB_LEN_MAX
+#include <bits/c++locale_internal.h>
+
+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/newlib/collate_members.cc b/libstdc++-v3/config/locale/newlib/collate_members.cc
new file mode 100644
index 00000000000..74a646143be
--- /dev/null
+++ b/libstdc++-v3/config/locale/newlib/collate_members.cc
@@ -0,0 +1,74 @@
+// std::collate implementation details, newlib version -*- C++ -*-
+
+// Copyright (C) 2001-2023 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 <bkoz@redhat.com>
+// Modified by Takashi Yano <takashi.yano@nifty.ne.jp>
+
+#include <locale>
+#include <bits/c++locale_internal.h>
+
+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/newlib/ctype_members.cc b/libstdc++-v3/config/locale/newlib/ctype_members.cc
index ee7e7a79efe..6e60dfd5837 100644
--- a/libstdc++-v3/config/locale/newlib/ctype_members.cc
+++ b/libstdc++-v3/config/locale/newlib/ctype_members.cc
@@ -58,37 +58,37 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     switch (__m)
       {
       case space:
-	__ret = wctype("space");
+	__ret = wctype_l("space", _M_c_locale_ctype);
 	break;
       case print:
-	__ret = wctype("print");
+	__ret = wctype_l("print", _M_c_locale_ctype);
 	break;
       case cntrl:
-	__ret = wctype("cntrl");
+	__ret = wctype_l("cntrl", _M_c_locale_ctype);
 	break;
       case upper:
-	__ret = wctype("upper");
+	__ret = wctype_l("upper", _M_c_locale_ctype);
 	break;
       case lower:
-	__ret = wctype("lower");
+	__ret = wctype_l("lower", _M_c_locale_ctype);
 	break;
       case alpha:
-	__ret = wctype("alpha");
+	__ret = wctype_l("alpha", _M_c_locale_ctype);
 	break;
       case digit:
-	__ret = wctype("digit");
+	__ret = wctype_l("digit", _M_c_locale_ctype);
 	break;
       case punct:
-	__ret = wctype("punct");
+	__ret = wctype_l("punct", _M_c_locale_ctype);
 	break;
       case xdigit:
-	__ret = wctype("xdigit");
+	__ret = wctype_l("xdigit", _M_c_locale_ctype);
 	break;
       case alnum:
-	__ret = wctype("alnum");
+	__ret = wctype_l("alnum", _M_c_locale_ctype);
 	break;
       case graph:
-	__ret = wctype("graph");
+	__ret = wctype_l("graph", _M_c_locale_ctype);
 	break;
       default:
 	// Different from the generic version, xdigit and print in
@@ -100,25 +100,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	// equal to _X or _B, the two cases are specifically handled
 	// here.
 	if (__m & xdigit)
-	  __ret = wctype("xdigit");
+	  __ret = wctype_l("xdigit", _M_c_locale_ctype);
 	else if (__m & print)
-	  __ret = wctype("print");
+	  __ret = wctype_l("print", _M_c_locale_ctype);
 	else
 	  __ret = __wmask_type();
       }
     return __ret;
-  };
+  }
 
   wchar_t
   ctype<wchar_t>::do_toupper(wchar_t __c) const
-  { return towupper(__c); }
+  { 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(*__lo);
+	*__lo = towupper_l(*__lo, _M_c_locale_ctype);
         ++__lo;
       }
     return __hi;
@@ -126,14 +126,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   wchar_t
   ctype<wchar_t>::do_tolower(wchar_t __c) const
-  { return towlower(__c); }
+  { 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(*__lo);
+	*__lo = towlower_l(*__lo, _M_c_locale_ctype);
         ++__lo;
       }
     return __hi;
@@ -148,7 +148,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     const size_t __bitmasksize = 7;
     for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
       if (__m & _M_bit[__bitcur]
-	  && iswctype(__c, _M_wmask[__bitcur]))
+	  && iswctype_l(__c, _M_wmask[__bitcur], _M_c_locale_ctype))
 	{
 	  __ret = true;
 	  break;
@@ -166,7 +166,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	const size_t __bitmasksize = 7;
 	mask __m = 0;
 	for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
-	  if (iswctype(*__lo, _M_wmask[__bitcur]))
+	  if (iswctype_l(*__lo, _M_wmask[__bitcur], _M_c_locale_ctype))
 	    __m |= _M_bit[__bitcur];
 	*__vec = __m;
       }
@@ -215,7 +215,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   {
     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));
   }
 
@@ -224,6 +226,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   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)
 	{
@@ -245,12 +248,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  ++__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)
       {
@@ -264,15 +269,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       _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 __i = 0; __i <= 7; ++__i)
+    for (size_t __k = 0; __k <= 7; ++__k)
       {
-	_M_bit[__i] = static_cast<mask>(1 << __i);
-	_M_wmask[__i] = _M_convert_to_wmask(_M_bit[__i]);
+	_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
 
diff --git a/libstdc++-v3/config/locale/newlib/messages_members.cc b/libstdc++-v3/config/locale/newlib/messages_members.cc
new file mode 100644
index 00000000000..591995faba4
--- /dev/null
+++ b/libstdc++-v3/config/locale/newlib/messages_members.cc
@@ -0,0 +1,173 @@
+// std::messages implementation details, newlib version -*- C++ -*-
+
+// Copyright (C) 2001-2023 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.7.1.2  messages virtual functions
+//
+
+// Written by Benjamin Kosnik <bkoz@redhat.com>
+// Modified by Takashi Yano <takashi.yano@nifty.ne.jp>
+
+#include <locale>
+#include <bits/c++locale_internal.h>
+
+#include <cstdlib>	// std::free
+#include <string.h>	// ::strdup
+
+namespace
+{
+  using namespace std;
+
+  const char*
+  get_glibc_msg(__c_locale __locale_messages __attribute__((unused)),
+		const char* __name_messages __attribute__((unused)),
+		const char* __domainname,
+		const char* __dfault)
+  {
+    std::__c_locale __old = uselocale(__locale_messages);
+    const char* __msg = dgettext(__domainname, __dfault);
+    uselocale(__old);
+    return __msg;
+  }
+}
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  // Specializations.
+  template<>
+    typename messages<char>::catalog
+    messages<char>::do_open(const basic_string<char>& __s,
+			    const locale& __l) const
+    {
+      typedef codecvt<char, char, mbstate_t> __codecvt_t;
+      const __codecvt_t& __codecvt = use_facet<__codecvt_t>(__l);
+
+      bind_textdomain_codeset(__s.c_str(),
+	  nl_langinfo_l(CODESET, __codecvt._M_c_locale_codecvt));
+      return get_catalogs()._M_add(__s.c_str(), __l);
+    }
+
+  template<>
+    void
+    messages<char>::do_close(catalog __c) const
+    { get_catalogs()._M_erase(__c); }
+
+  template<>
+    string
+    messages<char>::do_get(catalog __c, int, int,
+			   const string& __dfault) const
+    {
+      if (__c < 0 || __dfault.empty())
+	return __dfault;
+
+      const Catalog_info* __cat_info = get_catalogs()._M_get(__c);
+
+      if (!__cat_info)
+	return __dfault;
+
+      return get_glibc_msg(_M_c_locale_messages, _M_name_messages,
+			   __cat_info->_M_domain,
+			   __dfault.c_str());
+    }
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+  template<>
+    typename messages<wchar_t>::catalog
+    messages<wchar_t>::do_open(const basic_string<char>& __s,
+			       const locale& __l) const
+    {
+      typedef codecvt<wchar_t, char, mbstate_t> __codecvt_t;
+      const __codecvt_t& __codecvt = use_facet<__codecvt_t>(__l);
+
+      bind_textdomain_codeset(__s.c_str(),
+	  nl_langinfo_l(CODESET, __codecvt._M_c_locale_codecvt));
+
+      return get_catalogs()._M_add(__s.c_str(), __l);
+    }
+
+  template<>
+    void
+    messages<wchar_t>::do_close(catalog __c) const
+    { get_catalogs()._M_erase(__c); }
+
+  template<>
+    wstring
+    messages<wchar_t>::do_get(catalog __c, int, int,
+			      const wstring& __wdfault) const
+    {
+      if (__c < 0 || __wdfault.empty())
+	return __wdfault;
+
+      const Catalog_info* __cat_info = get_catalogs()._M_get(__c);
+
+      if (!__cat_info)
+	return __wdfault;
+
+      typedef codecvt<wchar_t, char, mbstate_t> __codecvt_t;
+      const __codecvt_t& __conv =
+	use_facet<__codecvt_t>(__cat_info->_M_locale);
+
+      const char* __translation;
+      mbstate_t __state;
+      __builtin_memset(&__state, 0, sizeof(mbstate_t));
+      {
+	const wchar_t* __wdfault_next;
+	size_t __mb_size = __wdfault.size() * __conv.max_length();
+	char* __dfault =
+	  static_cast<char*>(__builtin_alloca(sizeof(char) * (__mb_size + 1)));
+	char* __dfault_next;
+	__conv.out(__state,
+		   __wdfault.data(), __wdfault.data() + __wdfault.size(),
+		   __wdfault_next,
+		   __dfault, __dfault + __mb_size, __dfault_next);
+
+	// Make sure string passed to dgettext is \0 terminated.
+	*__dfault_next = '\0';
+	__translation = get_glibc_msg(_M_c_locale_messages, _M_name_messages,
+				      __cat_info->_M_domain, __dfault);
+
+	// If we end up getting default value back we can simply return original
+	// default value.
+	if (__translation == __dfault)
+	  return __wdfault;
+      }
+
+      __builtin_memset(&__state, 0, sizeof(mbstate_t));
+      size_t __size = __builtin_strlen(__translation);
+      const char* __translation_next;
+      wchar_t* __wtranslation =
+	static_cast<wchar_t*>(__builtin_alloca(sizeof(wchar_t) * (__size + 1)));
+      wchar_t* __wtranslation_next;
+      __conv.in(__state, __translation, __translation + __size,
+		__translation_next,
+		__wtranslation, __wtranslation + __size,
+		__wtranslation_next);
+      return wstring(__wtranslation, __wtranslation_next);
+    }
+#endif
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
diff --git a/libstdc++-v3/config/locale/newlib/messages_members.h b/libstdc++-v3/config/locale/newlib/messages_members.h
new file mode 100644
index 00000000000..ddfac207897
--- /dev/null
+++ b/libstdc++-v3/config/locale/newlib/messages_members.h
@@ -0,0 +1,152 @@
+// std::messages implementation details, newlib version -*- C++ -*-
+
+// Copyright (C) 2001-2023 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/messages_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.7.1.2  messages functions
+//
+
+// Written by Benjamin Kosnik <bkoz@redhat.com>
+// Modified by Takashi Yano <takashi.yano@nifty.ne.jp>
+
+#include <libintl.h>
+
+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()),
+      _M_name_messages(_S_get_c_name())
+    { }
+
+  template<typename _CharT>
+    messages<_CharT>::messages(__c_locale __cloc, const char* __s,
+			       size_t __refs)
+    : facet(__refs), _M_c_locale_messages(0), _M_name_messages(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_messages = __tmp;
+	}
+      else
+	_M_name_messages = _S_get_c_name();
+
+      // Last to avoid leaking memory if new throws.
+      _M_c_locale_messages = _S_clone_c_locale(__cloc);
+    }
+
+  template<typename _CharT>
+    typename messages<_CharT>::catalog
+    messages<_CharT>::open(const basic_string<char>& __s, const locale& __loc,
+			   const char* __dir) const
+    {
+      bindtextdomain(__s.c_str(), __dir);
+      return this->do_open(__s, __loc);
+    }
+
+  // Virtual member functions.
+  template<typename _CharT>
+    messages<_CharT>::~messages()
+    {
+      if (_M_name_messages != _S_get_c_name())
+	delete [] _M_name_messages;
+      _S_destroy_c_locale(_M_c_locale_messages);
+    }
+
+  template<typename _CharT>
+    typename messages<_CharT>::catalog
+    messages<_CharT>::do_open(const basic_string<char>& __s,
+			      const locale&) const
+    {
+      // No error checking is done, assume the catalog exists and can
+      // be used.
+      textdomain(__s.c_str());
+      return 0;
+    }
+
+  template<typename _CharT>
+    void
+    messages<_CharT>::do_close(catalog) const
+    { }
+
+  // messages_byname
+  template<typename _CharT>
+    messages_byname<_CharT>::messages_byname(const char* __s, size_t __refs)
+    : messages<_CharT>(__refs)
+    {
+      if (this->_M_name_messages != locale::facet::_S_get_c_name())
+	{
+	  delete [] this->_M_name_messages;
+	  if (__builtin_strcmp(__s, locale::facet::_S_get_c_name()) != 0)
+	    {
+	      const size_t __len = __builtin_strlen(__s) + 1;
+	      char* __tmp = new char[__len];
+	      __builtin_memcpy(__tmp, __s, __len);
+	      this->_M_name_messages = __tmp;
+	    }
+	  else
+	    this->_M_name_messages = locale::facet::_S_get_c_name();
+	}
+
+      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);
+	}
+    }
+
+   //Specializations.
+  template<>
+    typename messages<char>::catalog
+    messages<char>::do_open(const basic_string<char>&,
+			    const locale&) const;
+
+  template<>
+    void
+    messages<char>::do_close(catalog) const;
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+  template<>
+    typename messages<wchar_t>::catalog
+    messages<wchar_t>::do_open(const basic_string<char>&,
+			       const locale&) const;
+
+  template<>
+    void
+    messages<wchar_t>::do_close(catalog) const;
+#endif
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
diff --git a/libstdc++-v3/config/locale/newlib/monetary_members.cc b/libstdc++-v3/config/locale/newlib/monetary_members.cc
new file mode 100644
index 00000000000..2bbc96e73a4
--- /dev/null
+++ b/libstdc++-v3/config/locale/newlib/monetary_members.cc
@@ -0,0 +1,942 @@
+// std::moneypunct implementation details, newlib version -*- C++ -*-
+
+// Copyright (C) 2001-2023 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 <bkoz@redhat.com>
+// Modified by Takashi Yano <takashi.yano@nifty.ne.jp>
+
+#include <locale>
+#include <bits/c++locale_internal.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.
+	  _M_data->_M_decimal_point =
+	    *(nl_langinfo_l(_NL_MONETARY_MON_DECIMAL_POINT, __cloc));
+	  const char* thousands_sep =
+	    nl_langinfo_l(_NL_MONETARY_MON_THOUSANDS_SEP, __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 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(_NL_MONETARY_INT_FRAC_DIGITS, __cloc));
+
+	  const char* __cgroup =
+	    nl_langinfo_l(_NL_MONETARY_MON_GROUPING, __cloc);
+	  const char* __cpossign =
+	    nl_langinfo_l(_NL_MONETARY_POSITIVE_SIGN, __cloc);
+	  const char* __cnegsign =
+	    nl_langinfo_l(_NL_MONETARY_NEGATIVE_SIGN, __cloc);
+	  // _Intl == true
+	  const char* __ccurr =
+	    nl_langinfo_l(_NL_MONETARY_INT_CURR_SYMBOL, __cloc);
+
+	  char* __group = 0;
+	  char* __ps = 0;
+	  char* __ns = 0;
+	  const char __nposn =
+	    *(nl_langinfo_l(_NL_MONETARY_INT_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(_NL_MONETARY_INT_P_CS_PRECEDES, __cloc));
+	  char __pspace =
+	    *(nl_langinfo_l(_NL_MONETARY_INT_P_SEP_BY_SPACE, __cloc));
+	  char __pposn =
+	    *(nl_langinfo_l(_NL_MONETARY_INT_P_SIGN_POSN, __cloc));
+	  _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
+							__pposn);
+	  char __nprecedes =
+	    *(nl_langinfo_l(_NL_MONETARY_INT_N_CS_PRECEDES, __cloc));
+	  char __nspace =
+	    *(nl_langinfo_l(_NL_MONETARY_INT_N_SEP_BY_SPACE, __cloc));
+	  _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
+							__nposn);
+	}
+    }
+
+  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];
+	}
+      else
+	{
+	  // Named locale.
+	  _M_data->_M_decimal_point =
+	    *(nl_langinfo_l(_NL_MONETARY_MON_DECIMAL_POINT, __cloc));
+	  _M_data->_M_thousands_sep =
+	    *(nl_langinfo_l(_NL_MONETARY_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(_NL_MONETARY_FRAC_DIGITS, __cloc));
+
+	  const char* __cgroup =
+	    nl_langinfo_l(_NL_MONETARY_MON_GROUPING, __cloc);
+	  const char* __cpossign =
+	    nl_langinfo_l(_NL_MONETARY_POSITIVE_SIGN, __cloc);
+	  const char* __cnegsign =
+	    nl_langinfo_l(_NL_MONETARY_NEGATIVE_SIGN, __cloc);
+	  // _Intl == false
+	  const char* __ccurr =
+	    nl_langinfo_l(_NL_MONETARY_CURRENCY_SYMBOL, __cloc);
+
+	  char* __group = 0;
+	  char* __ps = 0;
+	  char* __ns = 0;
+	  const char __nposn =
+	    *(nl_langinfo_l(_NL_MONETARY_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(_NL_MONETARY_P_CS_PRECEDES, __cloc));
+	  char __pspace =
+	    *(nl_langinfo_l(_NL_MONETARY_P_SEP_BY_SPACE, __cloc));
+	  char __pposn = *(nl_langinfo_l(_NL_MONETARY_P_SIGN_POSN, __cloc));
+	  _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
+							__pposn);
+	  char __nprecedes =
+	    *(nl_langinfo_l(_NL_MONETARY_N_CS_PRECEDES, __cloc));
+	  char __nspace =
+	    *(nl_langinfo_l(_NL_MONETARY_N_SEP_BY_SPACE, __cloc));
+	  _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
+							__nposn);
+	}
+    }
+
+  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]);
+	}
+      else
+	{
+	  // Named locale.
+	  __c_locale __old = uselocale(__cloc);
+
+	  union { char *__s; wchar_t __w; } __u;
+	  __u.__s = nl_langinfo_l(_NL_MONETARY_WMON_DECIMAL_POINT, __cloc);
+	  _M_data->_M_decimal_point = __u.__w;
+
+	  __u.__s = nl_langinfo_l(_NL_MONETARY_WMON_THOUSANDS_SEP, __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(_NL_MONETARY_INT_FRAC_DIGITS, __cloc));
+
+	  const char* __cgroup =
+	    nl_langinfo_l(_NL_MONETARY_MON_GROUPING, __cloc);
+	  const char* __cpossign =
+	    nl_langinfo_l(_NL_MONETARY_POSITIVE_SIGN, __cloc);
+	  const char* __cnegsign =
+	    nl_langinfo_l(_NL_MONETARY_NEGATIVE_SIGN, __cloc);
+	  const char* __ccurr =
+	    nl_langinfo_l(_NL_MONETARY_INT_CURR_SYMBOL, __cloc);
+
+	  char* __group = 0;
+	  wchar_t* __wcs_ps = 0;
+	  wchar_t* __wcs_ns = 0;
+	  const char __nposn =
+	    *(nl_langinfo_l(_NL_MONETARY_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(_NL_MONETARY_INT_P_CS_PRECEDES, __cloc));
+	  char __pspace =
+	    *(nl_langinfo_l(_NL_MONETARY_INT_P_SEP_BY_SPACE, __cloc));
+	  char __pposn =
+	    *(nl_langinfo_l(_NL_MONETARY_INT_P_SIGN_POSN, __cloc));
+	  _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
+							__pposn);
+	  char __nprecedes =
+	    *(nl_langinfo_l(_NL_MONETARY_INT_N_CS_PRECEDES, __cloc));
+	  char __nspace =
+	    *(nl_langinfo_l(_NL_MONETARY_INT_N_SEP_BY_SPACE, __cloc));
+	  _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
+							__nposn);
+
+	  uselocale(__old);
+	}
+    }
+
+  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]);
+	}
+      else
+	{
+	  // Named locale.
+	  __c_locale __old = uselocale(__cloc);
+
+	  union { char *__s; wchar_t *__w; } __u;
+	  __u.__s = nl_langinfo_l(_NL_MONETARY_WMON_DECIMAL_POINT, __cloc);
+	  _M_data->_M_decimal_point = *__u.__w;
+
+	  __u.__s = nl_langinfo_l(_NL_MONETARY_WMON_THOUSANDS_SEP, __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(_NL_MONETARY_FRAC_DIGITS, __cloc));
+
+	  const char* __cgroup =
+	    nl_langinfo_l(_NL_MONETARY_MON_GROUPING, __cloc);
+	  const char* __cpossign =
+	    nl_langinfo_l(_NL_MONETARY_POSITIVE_SIGN, __cloc);
+	  const char* __cnegsign =
+	    nl_langinfo_l(_NL_MONETARY_NEGATIVE_SIGN, __cloc);
+	  const char* __ccurr =
+	    nl_langinfo_l(_NL_MONETARY_CURRENCY_SYMBOL, __cloc);
+
+	  char* __group = 0;
+	  wchar_t* __wcs_ps = 0;
+	  wchar_t* __wcs_ns = 0;
+	  const char __nposn =
+	    *(nl_langinfo_l(_NL_MONETARY_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(_NL_MONETARY_P_CS_PRECEDES, __cloc));
+	  char __pspace =
+	    *(nl_langinfo_l(_NL_MONETARY_P_SEP_BY_SPACE, __cloc));
+	  char __pposn =
+	    *(nl_langinfo_l(_NL_MONETARY_P_SIGN_POSN, __cloc));
+	  _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
+							__pposn);
+	  char __nprecedes =
+	    *(nl_langinfo_l(_NL_MONETARY_N_CS_PRECEDES, __cloc));
+	  char __nspace =
+	    *(nl_langinfo_l(_NL_MONETARY_N_SEP_BY_SPACE, __cloc));
+	  _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
+							__nposn);
+
+	  uselocale(__old);
+	}
+    }
+
+  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/newlib/numeric_members.cc b/libstdc++-v3/config/locale/newlib/numeric_members.cc
new file mode 100644
index 00000000000..23807ea7171
--- /dev/null
+++ b/libstdc++-v3/config/locale/newlib/numeric_members.cc
@@ -0,0 +1,282 @@
+// std::numpunct implementation details, newlib version -*- C++ -*-
+
+// Copyright (C) 2001-2023 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 <bkoz@redhat.com>
+// Modified by Takashi Yano <takashi.yano@nifty.ne.jp>
+
+#include <locale>
+#include <bits/c++locale_internal.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("ASCII//TRANSLIT", 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.
+	  const char* decimal_point =
+	    (nl_langinfo_l(_NL_NUMERIC_DECIMAL_POINT_WC, __cloc));
+
+	  if (decimal_point[0] != '\0' && decimal_point[1] != '\0')
+	    _M_data->_M_decimal_point = __narrow_multibyte_chars(decimal_point,
+								 __cloc);
+	  else
+	    _M_data->_M_decimal_point = *decimal_point;
+
+	  const char* thousands_sep =
+	    nl_langinfo_l(_NL_NUMERIC_THOUSANDS_SEP_WC, __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
+	    {
+	      const char* __src = nl_langinfo_l(_NL_NUMERIC_GROUPING, __cloc);
+	      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 = "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<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]);
+	}
+      else
+	{
+	  // Named locale.
+	  // NB: In the GNU model wchar_t is always 32 bit wide.
+	  union { char *__s; wchar_t *__w; } __u;
+	  __u.__s = nl_langinfo_l(_NL_NUMERIC_DECIMAL_POINT_WC, __cloc);
+	  _M_data->_M_decimal_point = *__u.__w;
+
+	  __u.__s = nl_langinfo_l(_NL_NUMERIC_THOUSANDS_SEP_WC, __cloc);
+	  _M_data->_M_thousands_sep = *__u.__w;
+
+	  // 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
+	    {
+	      const char* __src = nl_langinfo_l(_NL_NUMERIC_GROUPING, __cloc);
+	      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<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/newlib/time_members.cc b/libstdc++-v3/config/locale/newlib/time_members.cc
new file mode 100644
index 00000000000..fd09fa589ba
--- /dev/null
+++ b/libstdc++-v3/config/locale/newlib/time_members.cc
@@ -0,0 +1,379 @@
+// std::time_get, std::time_put implementation, newlib version -*- C++ -*-
+
+// Copyright (C) 2001-2023 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 <bkoz@redhat.com>
+// Modified by Takashi Yano <takashi.yano@nifty.ne.jp>
+
+#define _GNU_SOURCE 1
+#include <locale>
+#include <bits/c++locale_internal.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/%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 = "%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()
+    {
+      const size_t __len = wcsftime_l(__s, __maxlen, __format, __tm,
+					_M_c_locale_timepunct);
+      // 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 = 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"%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";
+	}
+      else
+	{
+	  _M_c_locale_timepunct = _S_clone_c_locale(__cloc);
+
+	  union { char *__s; wchar_t *__w; } __u;
+
+	  __u.__s = nl_langinfo_l(_NL_TIME_WD_FMT, __cloc);
+	  _M_data->_M_date_format = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WERA_D_FMT, __cloc);
+	  _M_data->_M_date_era_format = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WT_FMT, __cloc);
+	  _M_data->_M_time_format = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WERA_T_FMT, __cloc);
+	  _M_data->_M_time_era_format = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WD_T_FMT, __cloc);
+	  _M_data->_M_date_time_format = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WERA_D_T_FMT, __cloc);
+	  _M_data->_M_date_time_era_format = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WAM_STR, __cloc);
+	  _M_data->_M_am = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WPM_STR, __cloc);
+	  _M_data->_M_pm = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_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_TIME_WWEEKDAY_1, __cloc);
+	  _M_data->_M_day1 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WWEEKDAY_2, __cloc);
+	  _M_data->_M_day2 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WWEEKDAY_3, __cloc);
+	  _M_data->_M_day3 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WWEEKDAY_4, __cloc);
+	  _M_data->_M_day4 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WWEEKDAY_5, __cloc);
+	  _M_data->_M_day5 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WWEEKDAY_6, __cloc);
+	  _M_data->_M_day6 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WWEEKDAY_7, __cloc);
+	  _M_data->_M_day7 = __u.__w;
+
+	  // Abbreviated day names, starting with "C"'s Sun.
+	  __u.__s = nl_langinfo_l(_NL_TIME_WWDAY_1, __cloc);
+	  _M_data->_M_aday1 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WWDAY_2, __cloc);
+	  _M_data->_M_aday2 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WWDAY_3, __cloc);
+	  _M_data->_M_aday3 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WWDAY_4, __cloc);
+	  _M_data->_M_aday4 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WWDAY_5, __cloc);
+	  _M_data->_M_aday5 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WWDAY_6, __cloc);
+	  _M_data->_M_aday6 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WWDAY_7, __cloc);
+	  _M_data->_M_aday7 = __u.__w;
+
+	  // Month names, starting with "C"'s January.
+	  __u.__s = nl_langinfo_l(_NL_TIME_WMONTH_1, __cloc);
+	  _M_data->_M_month01 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WMONTH_2, __cloc);
+	  _M_data->_M_month02 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WMONTH_3, __cloc);
+	  _M_data->_M_month03 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WMONTH_4, __cloc);
+	  _M_data->_M_month04 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WMONTH_5, __cloc);
+	  _M_data->_M_month05 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WMONTH_6, __cloc);
+	  _M_data->_M_month06 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WMONTH_7, __cloc);
+	  _M_data->_M_month07 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WMONTH_8, __cloc);
+	  _M_data->_M_month08 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WMONTH_9, __cloc);
+	  _M_data->_M_month09 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WMONTH_10, __cloc);
+	  _M_data->_M_month10 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WMONTH_11, __cloc);
+	  _M_data->_M_month11 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WMONTH_12, __cloc);
+	  _M_data->_M_month12 = __u.__w;
+
+	  // Abbreviated month names, starting with "C"'s Jan.
+	  __u.__s = nl_langinfo_l(_NL_TIME_WMON_1, __cloc);
+	  _M_data->_M_amonth01 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WMON_2, __cloc);
+	  _M_data->_M_amonth02 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WMON_3, __cloc);
+	  _M_data->_M_amonth03 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WMON_4, __cloc);
+	  _M_data->_M_amonth04 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WMON_5, __cloc);
+	  _M_data->_M_amonth05 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WMON_6, __cloc);
+	  _M_data->_M_amonth06 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WMON_7, __cloc);
+	  _M_data->_M_amonth07 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WMON_8, __cloc);
+	  _M_data->_M_amonth08 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WMON_9, __cloc);
+	  _M_data->_M_amonth09 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WMON_10, __cloc);
+	  _M_data->_M_amonth10 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WMON_11, __cloc);
+	  _M_data->_M_amonth11 = __u.__w;
+	  __u.__s = nl_langinfo_l(_NL_TIME_WMON_12, __cloc);
+	  _M_data->_M_amonth12 = __u.__w;
+	}
+    }
+#endif
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
diff --git a/libstdc++-v3/config/locale/newlib/time_members.h b/libstdc++-v3/config/locale/newlib/time_members.h
new file mode 100644
index 00000000000..b0c7c29bfde
--- /dev/null
+++ b/libstdc++-v3/config/locale/newlib/time_members.h
@@ -0,0 +1,90 @@
+// std::time_get, std::time_put implementation, newlib version -*- C++ -*-
+
+// Copyright (C) 2001-2023 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 <bkoz@redhat.com>
+// Modified by Takashi Yano <takashi.yano@nifty.ne.jp>
+
+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/configure b/libstdc++-v3/configure
index 13fc03b2a3f..535441cd181 100755
--- a/libstdc++-v3/configure
+++ b/libstdc++-v3/configure
@@ -723,6 +723,7 @@ CXXFILT
 LTLIBICONV
 LIBICONV
 OPT_LDFLAGS
+EXTRA_LIBS
 SECTION_LDFLAGS
 GLIBCXX_LIBS
 ENABLE_VTABLE_VERIFY_FALSE
@@ -16552,7 +16553,7 @@ fi
       dragonfly* | freebsd*)
 	enable_clocale_flag=dragonfly
 	;;
-      openbsd*)
+      openbsd* | cygwin*)
 	enable_clocale_flag=newlib
 	;;
       *)
@@ -16564,6 +16565,10 @@ fi
 	;;
     esac
   fi
+  case ${target_os} in cygwin*)
+    EXTRA_LIBS="-lintl"
+    ;;
+  esac
 
   # Sanity check model, and test for special functionality.
   if test $enable_clocale_flag = gnu; then
@@ -16824,18 +16829,18 @@ $as_echo "IEEE 1003.1" >&6; }
       { $as_echo "$as_me:${as_lineno-$LINENO}: result: newlib" >&5
 $as_echo "newlib" >&6; }
 
-      CLOCALE_H=config/locale/generic/c_locale.h
-      CLOCALE_CC=config/locale/generic/c_locale.cc
-      CCODECVT_CC=config/locale/generic/codecvt_members.cc
-      CCOLLATE_CC=config/locale/generic/collate_members.cc
+      CLOCALE_H=config/locale/newlib/c_locale.h
+      CLOCALE_CC=config/locale/newlib/c_locale.cc
+      CCODECVT_CC=config/locale/newlib/codecvt_members.cc
+      CCOLLATE_CC=config/locale/newlib/collate_members.cc
       CCTYPE_CC=config/locale/newlib/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
-      CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h
+      CMESSAGES_H=config/locale/newlib/messages_members.h
+      CMESSAGES_CC=config/locale/newlib/messages_members.cc
+      CMONEY_CC=config/locale/newlib/monetary_members.cc
+      CNUMERIC_CC=config/locale/newlib/numeric_members.cc
+      CTIME_H=config/locale/newlib/time_members.h
+      CTIME_CC=config/locale/newlib/time_members.cc
+      CLOCALE_INTERNAL_H=config/locale/newlib/c++locale_internal.h
       ;;
   esac
 
diff --git a/libstdc++-v3/src/Makefile.in b/libstdc++-v3/src/Makefile.in
index c5d01e7beba..20daa62e1d5 100644
--- a/libstdc++-v3/src/Makefile.in
+++ b/libstdc++-v3/src/Makefile.in
@@ -307,6 +307,7 @@ ERROR_CONSTANTS_SRCDIR = @ERROR_CONSTANTS_SRCDIR@
 EXEEXT = @EXEEXT@
 EXTRA_CFLAGS = @EXTRA_CFLAGS@
 EXTRA_CXX_FLAGS = @EXTRA_CXX_FLAGS@
+EXTRA_LIBS = @EXTRA_LIBS@
 FGREP = @FGREP@
 FORMAT_FILE = @FORMAT_FILE@
 FREESTANDING_FLAGS = @FREESTANDING_FLAGS@
@@ -563,7 +564,7 @@ libstdc___la_DEPENDENCIES = \
 	$(top_builddir)/src/c++20/libc++20convenience.la
 
 libstdc___la_LDFLAGS = \
-	-version-info $(libtool_VERSION) ${version_arg} -lm
+	-version-info $(libtool_VERSION) ${version_arg} -lm $(EXTRA_LIBS)
 
 libstdc___la_LINK = $(CXXLINK) $(libstdc___la_LDFLAGS) $(lt_host_flags)
 @GLIBCXX_LDBL_ALT128_COMPAT_FALSE@@GLIBCXX_LDBL_COMPAT_TRUE@LTCXXCOMPILE64 = $(LTCXXCOMPILE)
diff --git a/libstdc++-v3/src/c++11/locale_init.cc b/libstdc++-v3/src/c++11/locale_init.cc
index cfc22eaf5a4..582a816da65 100644
--- a/libstdc++-v3/src/c++11/locale_init.cc
+++ b/libstdc++-v3/src/c++11/locale_init.cc
@@ -300,8 +300,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	__other._M_impl->_M_add_reference();
       _S_global = __other._M_impl;
       const string __other_name = __other.name();
+      extern const __typeof(setlocale) *__setlocale;
       if (__other_name != "*")
-	setlocale(LC_ALL, __other_name.c_str());
+	__setlocale(LC_ALL, __other_name.c_str());
     }
 
     // Reference count sanity check: one reference removed for the
-- 
2.39.0


  parent reply	other threads:[~2023-09-27 10:50 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-09-21 16:12 Takashi Yano
2023-09-21 16:28 ` Takashi Yano
2023-09-21 18:08   ` Brian Inglis
2023-09-21 19:06     ` Christian Franke
2023-09-22  4:08       ` Takashi Yano
2023-09-22  7:20         ` Christian Franke
2023-09-22  5:56       ` Martin Wege
2023-09-22 12:01         ` Brian Inglis
2023-09-22  6:48 ` ASSI
2023-09-23  8:23   ` Takashi Yano
2023-09-23  8:42     ` Takashi Yano
2023-09-27 10:50     ` Takashi Yano [this message]
2023-12-31  6:57       ` Takashi Yano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230927195039.e62f7482898ab5615cc1605b@nifty.ne.jp \
    --to=takashi.yano@nifty.ne.jp \
    --cc=cygwin@cygwin.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).