public inbox for cygwin@cygwin.com
 help / color / mirror / Atom feed
* std::runtime_error on std::locale("")
@ 2023-09-21 16:12 Takashi Yano
  2023-09-21 16:28 ` Takashi Yano
  2023-09-22  6:48 ` ASSI
  0 siblings, 2 replies; 13+ messages in thread
From: Takashi Yano @ 2023-09-21 16:12 UTC (permalink / raw)
  To: cygwin

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".

#include <locale>
int main()
{
	std::locale("");
	return 0;
}

In linux, this occurs only when the LC_ALL is set to invalid
locale (i.e. locale that is not registered in system).

Any idea?

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

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: std::runtime_error on std::locale("")
  2023-09-21 16:12 std::runtime_error on std::locale("") Takashi Yano
@ 2023-09-21 16:28 ` Takashi Yano
  2023-09-21 18:08   ` Brian Inglis
  2023-09-22  6:48 ` ASSI
  1 sibling, 1 reply; 13+ messages in thread
From: Takashi Yano @ 2023-09-21 16:28 UTC (permalink / raw)
  To: cygwin

On Fri, 22 Sep 2023 01:12:04 +0900
Takashi Yano wrote:
> 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".
> 
> #include <locale>
> int main()
> {
> 	std::locale("");
> 	return 0;
> }
> 
> In linux, this occurs only when the LC_ALL is set to invalid
> locale (i.e. locale that is not registered in system).

Similarly,
std::locale("ja_JP.UTF-8")
throws std::runtime_error in cygwin.

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

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: std::runtime_error on std::locale("")
  2023-09-21 16:28 ` Takashi Yano
@ 2023-09-21 18:08   ` Brian Inglis
  2023-09-21 19:06     ` Christian Franke
  0 siblings, 1 reply; 13+ messages in thread
From: Brian Inglis @ 2023-09-21 18:08 UTC (permalink / raw)
  To: cygwin

On 2023-09-21 10:28, Takashi Yano via Cygwin wrote:
> On Fri, 22 Sep 2023 01:12:04 +0900
> Takashi Yano wrote:
>> 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".
>>
>> #include <locale>
>> int main()
>> {
>> 	std::locale("");
>> 	return 0;
>> }
>>
>> In linux, this occurs only when the LC_ALL is set to invalid
>> locale (i.e. locale that is not registered in system).
> 
> Similarly,
> std::locale("ja_JP.UTF-8")
> throws std::runtime_error in cygwin.

Looks like the implementation does not like any default "" or explicit 
"en_US.UTF-8" strings there! See example at link and below; results are always 
the same:

	https://en.cppreference.com/w/cpp/locale/locale

#include <iostream>
#include <locale>

int main()
{
     std::wcout << "User-preferred locale setting is "
	       << std::locale().name().c_str() << '\n';

     // on startup, the global locale is the "C" locale
     std::wcout << 1000.01 << '\n';
	
     // replace the C++ global locale and the "C" locale with the user-preferred 
locale
     std::locale::global(std::locale(""));
     // use the new global locale for future wide character output
     std::wcout.imbue(std::locale());

     // output the same number again
     std::wcout << 1000.01 << '\n';
}

$ g++ -o c++locale{,.cc}
$ ./c++locale
User-preferred locale setting is C
1000.01
terminate called after throwing an instance of 'std::runtime_error'
   what():  locale::facet::_S_create_c_locale name not valid
Aborted (core dumped)

-- 
Take care. Thanks, Brian Inglis              Calgary, Alberta, Canada

La perfection est atteinte                   Perfection is achieved
non pas lorsqu'il n'y a plus rien à ajouter  not when there is no more to add
mais lorsqu'il n'y a plus rien à retirer     but when there is no more to cut
                                 -- Antoine de Saint-Exupéry

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: std::runtime_error on std::locale("")
  2023-09-21 18:08   ` Brian Inglis
@ 2023-09-21 19:06     ` Christian Franke
  2023-09-22  4:08       ` Takashi Yano
  2023-09-22  5:56       ` Martin Wege
  0 siblings, 2 replies; 13+ messages in thread
From: Christian Franke @ 2023-09-21 19:06 UTC (permalink / raw)
  To: cygwin

Brian Inglis via Cygwin wrote:
> On 2023-09-21 10:28, Takashi Yano via Cygwin wrote:
>> On Fri, 22 Sep 2023 01:12:04 +0900
>> Takashi Yano wrote:
>>> 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".
>>>
>>> #include <locale>
>>> int main()
>>> {
>>>     std::locale("");
>>>     return 0;
>>> }
>>>
>>> In linux, this occurs only when the LC_ALL is set to invalid
>>> locale (i.e. locale that is not registered in system).
>>
>> Similarly,
>> std::locale("ja_JP.UTF-8")
>> throws std::runtime_error in cygwin.
>
> Looks like the implementation does not like any default "" or explicit 
> "en_US.UTF-8" strings there! See example at link and below; results 
> are always the same:
>
>     https://en.cppreference.com/w/cpp/locale/locale
>
> #include <iostream>
> #include <locale>
>
> int main()
> {
>     std::wcout << "User-preferred locale setting is "
>            << std::locale().name().c_str() << '\n';
>
>     // on startup, the global locale is the "C" locale
>     std::wcout << 1000.01 << '\n';
>
>     // replace the C++ global locale and the "C" locale with the 
> user-preferred locale
>     std::locale::global(std::locale(""));
>     // use the new global locale for future wide character output
>     std::wcout.imbue(std::locale());
>
>     // output the same number again
>     std::wcout << 1000.01 << '\n';
> }
>
> $ g++ -o c++locale{,.cc}
> $ ./c++locale
> User-preferred locale setting is C
> 1000.01
> terminate called after throwing an instance of 'std::runtime_error'
>   what():  locale::facet::_S_create_c_locale name not valid
> Aborted (core dumped)
>

According to libstdc++ source, the internal function 
locale::facet::_S_create_c_locale() calls some __newlocale() which 
apparently does not arrive at newlocale() from cygwin1.dll. But 
cygstdc++-6.dll imports newlocale() from cygwin1.dll.

Only standard locale "C" and its alias "POSIX" work with C++ std::locale().

The cygwin1.dll function newlocale() works as expected - except that it 
does not set errno if the locale name is invalid.

-- 
Regards,
Christian


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: std::runtime_error on std::locale("")
  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
  1 sibling, 1 reply; 13+ messages in thread
From: Takashi Yano @ 2023-09-22  4:08 UTC (permalink / raw)
  To: cygwin

On Thu, 21 Sep 2023 21:06:59 +0200
Christian Franke wrote:
> Brian Inglis via Cygwin wrote:
> > On 2023-09-21 10:28, Takashi Yano via Cygwin wrote:
> >> On Fri, 22 Sep 2023 01:12:04 +0900
> >> Takashi Yano wrote:
> >>> 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".
> >>>
> >>> #include <locale>
> >>> int main()
> >>> {
> >>>     std::locale("");
> >>>     return 0;
> >>> }
> >>>
> >>> In linux, this occurs only when the LC_ALL is set to invalid
> >>> locale (i.e. locale that is not registered in system).
> >>
> >> Similarly,
> >> std::locale("ja_JP.UTF-8")
> >> throws std::runtime_error in cygwin.
> >
> > Looks like the implementation does not like any default "" or explicit 
> > "en_US.UTF-8" strings there! See example at link and below; results 
> > are always the same:
> >
> >     https://en.cppreference.com/w/cpp/locale/locale
> >
> > #include <iostream>
> > #include <locale>
> >
> > int main()
> > {
> >     std::wcout << "User-preferred locale setting is "
> >            << std::locale().name().c_str() << '\n';
> >
> >     // on startup, the global locale is the "C" locale
> >     std::wcout << 1000.01 << '\n';
> >
> >     // replace the C++ global locale and the "C" locale with the 
> > user-preferred locale
> >     std::locale::global(std::locale(""));
> >     // use the new global locale for future wide character output
> >     std::wcout.imbue(std::locale());
> >
> >     // output the same number again
> >     std::wcout << 1000.01 << '\n';
> > }
> >
> > $ g++ -o c++locale{,.cc}
> > $ ./c++locale
> > User-preferred locale setting is C
> > 1000.01
> > terminate called after throwing an instance of 'std::runtime_error'
> >   what():  locale::facet::_S_create_c_locale name not valid
> > Aborted (core dumped)
> >
> 
> According to libstdc++ source, the internal function 
> locale::facet::_S_create_c_locale() calls some __newlocale() which 
> apparently does not arrive at newlocale() from cygwin1.dll. But 
> cygstdc++-6.dll imports newlocale() from cygwin1.dll.

Thanks for the pointer. I looked into the cygstdc++6.dll source code,
and noticed that the code you mentioned is for glibc. In glibc, 
__newlocale() is defined and newlocale() is a weak alias for that.

For generic libc (i.e. other than glibc), _S_create_c_locale() is
defined as:

  void
  locale::facet::_S_create_c_locale(__c_locale& __cloc, const char* __s,
                    __c_locale)
  {
    // Currently, the generic model only supports the "C" locale.
    // See http://gcc.gnu.org/ml/libstdc++/2003-02/msg00345.html
    __cloc = 0;
    if (strcmp(__s, "C"))
      __throw_runtime_error(__N("locale::facet::_S_create_c_locale "
                "name not valid"));
  }

in /libstdc++-v3/config/locale/generic/c_locale.cc.

Obviously from the code, locale other than "C" causes runtime_error.
The behaviour is as designed but not a bug in cygwin environment.

Thanks for discussion.

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

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: std::runtime_error on std::locale("")
  2023-09-21 19:06     ` Christian Franke
  2023-09-22  4:08       ` Takashi Yano
@ 2023-09-22  5:56       ` Martin Wege
  2023-09-22 12:01         ` Brian Inglis
  1 sibling, 1 reply; 13+ messages in thread
From: Martin Wege @ 2023-09-22  5:56 UTC (permalink / raw)
  To: cygwin

On Thu, Sep 21, 2023 at 9:07 PM Christian Franke via Cygwin
<cygwin@cygwin.com> wrote:
>
> Brian Inglis via Cygwin wrote:
> > On 2023-09-21 10:28, Takashi Yano via Cygwin wrote:
> >> On Fri, 22 Sep 2023 01:12:04 +0900
> >> Takashi Yano wrote:
> >>> 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".
> >>>
> >>> #include <locale>
> >>> int main()
> >>> {
> >>>     std::locale("");
> >>>     return 0;
> >>> }
> >>>
> >>> In linux, this occurs only when the LC_ALL is set to invalid
> >>> locale (i.e. locale that is not registered in system).
> >>
> >> Similarly,
> >> std::locale("ja_JP.UTF-8")
> >> throws std::runtime_error in cygwin.
> >
> > Looks like the implementation does not like any default "" or explicit
> > "en_US.UTF-8" strings there! See example at link and below; results
> > are always the same:
> >
> >     https://en.cppreference.com/w/cpp/locale/locale
> >
> > #include <iostream>
> > #include <locale>
> >
> > int main()
> > {
> >     std::wcout << "User-preferred locale setting is "
> >            << std::locale().name().c_str() << '\n';
> >
> >     // on startup, the global locale is the "C" locale
> >     std::wcout << 1000.01 << '\n';
> >
> >     // replace the C++ global locale and the "C" locale with the
> > user-preferred locale
> >     std::locale::global(std::locale(""));
> >     // use the new global locale for future wide character output
> >     std::wcout.imbue(std::locale());
> >
> >     // output the same number again
> >     std::wcout << 1000.01 << '\n';
> > }
> >
> > $ g++ -o c++locale{,.cc}
> > $ ./c++locale
> > User-preferred locale setting is C
> > 1000.01
> > terminate called after throwing an instance of 'std::runtime_error'
> >   what():  locale::facet::_S_create_c_locale name not valid
> > Aborted (core dumped)
> >
>
> According to libstdc++ source, the internal function
> locale::facet::_S_create_c_locale() calls some __newlocale() which
> apparently does not arrive at newlocale() from cygwin1.dll. But
> cygstdc++-6.dll imports newlocale() from cygwin1.dll.

So this is a BUG?

>
> Only standard locale "C" and its alias "POSIX" work with C++ std::locale().
>
> The cygwin1.dll function newlocale() works as expected - except that it
> does not set errno if the locale name is invalid.

What does
bash -c 'locale -a'
print on your system?

Thanks,
Martin

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: std::runtime_error on std::locale("")
  2023-09-21 16:12 std::runtime_error on std::locale("") Takashi Yano
  2023-09-21 16:28 ` Takashi Yano
@ 2023-09-22  6:48 ` ASSI
  2023-09-23  8:23   ` Takashi Yano
  1 sibling, 1 reply; 13+ messages in thread
From: ASSI @ 2023-09-22  6:48 UTC (permalink / raw)
  To: cygwin

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.


Regards,
Achim.
-- 
+<[Q+ Matrix-12 WAVE#46+305 Neuron microQkb Andromeda XTk Blofeld]>+

SD adaptations for Waldorf Q V3.00R3 and Q+ V3.54R2:
http://Synth.Stromeko.net/Downloads.html#WaldorfSDada

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: std::runtime_error on std::locale("")
  2023-09-22  4:08       ` Takashi Yano
@ 2023-09-22  7:20         ` Christian Franke
  0 siblings, 0 replies; 13+ messages in thread
From: Christian Franke @ 2023-09-22  7:20 UTC (permalink / raw)
  To: cygwin

Takashi Yano via Cygwin wrote:
> On Thu, 21 Sep 2023 21:06:59 +0200
> Christian Franke wrote:
>> ...
>> According to libstdc++ source, the internal function
>> locale::facet::_S_create_c_locale() calls some __newlocale() which
>> apparently does not arrive at newlocale() from cygwin1.dll. But
>> cygstdc++-6.dll imports newlocale() from cygwin1.dll.
> Thanks for the pointer. I looked into the cygstdc++6.dll source code,
> and noticed that the code you mentioned is for glibc. In glibc,
> __newlocale() is defined and newlocale() is a weak alias for that.
>
> For generic libc (i.e. other than glibc), _S_create_c_locale() is
> defined as:
>
>    void
>    locale::facet::_S_create_c_locale(__c_locale& __cloc, const char* __s,
>                      __c_locale)
>    {
>      // Currently, the generic model only supports the "C" locale.
>      // See http://gcc.gnu.org/ml/libstdc++/2003-02/msg00345.html
>      __cloc = 0;
>      if (strcmp(__s, "C"))
>        __throw_runtime_error(__N("locale::facet::_S_create_c_locale "
>                  "name not valid"));
>    }
>
> in /libstdc++-v3/config/locale/generic/c_locale.cc.

Thanks for clarification. Same applies to MinGW-w64 runtime.

The reason why cygstdc++-6.dll imports newlocale() and other *locale() 
from cygwin1.dll are only the C++17 std::from_chars() functions 
(src/c++17/floating_from_chars.cc). These switch temporarily to "C" 
locale. MinGW-w64 does not support these.

-- 
Regards,
Christian


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: std::runtime_error on std::locale("")
  2023-09-22  5:56       ` Martin Wege
@ 2023-09-22 12:01         ` Brian Inglis
  0 siblings, 0 replies; 13+ messages in thread
From: Brian Inglis @ 2023-09-22 12:01 UTC (permalink / raw)
  To: cygwin; +Cc: Martin Wege

On 2023-09-21 23:56, Martin Wege via Cygwin wrote:
> On Thu, Sep 21, 2023 at 9:07 PM Christian Franke via Cygwin
> <cygwin@cygwin.com> wrote:
>>
>> Brian Inglis via Cygwin wrote:
>>> On 2023-09-21 10:28, Takashi Yano via Cygwin wrote:
>>>> On Fri, 22 Sep 2023 01:12:04 +0900
>>>> Takashi Yano wrote:
>>>>> 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".
>>>>> #include <locale>
>>>>> int main()
>>>>> {
>>>>>      std::locale("");
>>>>>      return 0;
>>>>> }
>>>>> In linux, this occurs only when the LC_ALL is set to invalid
>>>>> locale (i.e. locale that is not registered in system).

>>>> Similarly,
>>>> std::locale("ja_JP.UTF-8")
>>>> throws std::runtime_error in cygwin.

>>> Looks like the implementation does not like any default "" or explicit
>>> "en_US.UTF-8" strings there! See example at link and below; results
>>> are always the same:
>>>      https://en.cppreference.com/w/cpp/locale/locale
>>> #include <iostream>
>>> #include <locale>
>>> int main()
>>> {
>>>      std::wcout << "User-preferred locale setting is "
>>>             << std::locale().name().c_str() << '\n';
>>>      // on startup, the global locale is the "C" locale
>>>      std::wcout << 1000.01 << '\n';
>>>      // replace the C++ global locale and the "C" locale with the
>>> user-preferred locale
>>>      std::locale::global(std::locale(""));
>>>      // use the new global locale for future wide character output
>>>      std::wcout.imbue(std::locale());
>>>      // output the same number again
>>>      std::wcout << 1000.01 << '\n';
>>> }
>>> $ g++ -o c++locale{,.cc}
>>> $ ./c++locale
>>> User-preferred locale setting is C
>>> 1000.01
>>> terminate called after throwing an instance of 'std::runtime_error'
>>>    what():  locale::facet::_S_create_c_locale name not valid
>>> Aborted (core dumped)

>> According to libstdc++ source, the internal function
>> locale::facet::_S_create_c_locale() calls some __newlocale() which
>> apparently does not arrive at newlocale() from cygwin1.dll. But
>> cygstdc++-6.dll imports newlocale() from cygwin1.dll.

> So this is a BUG?

>> Only standard locale "C" and its alias "POSIX" work with C++ std::locale().
>>
>> The cygwin1.dll function newlocale() works as expected - except that it
>> does not set errno if the locale name is invalid.

As this is (presumably) conforming code from the reference website, this 
certainly appears as if the current Cygwin implmentation may be non-conforming, 
and less than useful for many users and uses.

-- 
Take care. Thanks, Brian Inglis              Calgary, Alberta, Canada

La perfection est atteinte                   Perfection is achieved
non pas lorsqu'il n'y a plus rien à ajouter  not when there is no more to add
mais lorsqu'il n'y a plus rien à retirer     but when there is no more to cut
                                 -- Antoine de Saint-Exupéry

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: std::runtime_error on std::locale("")
  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
  0 siblings, 2 replies; 13+ messages in thread
From: Takashi Yano @ 2023-09-23  8:23 UTC (permalink / raw)
  To: cygwin

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

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?

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

[-- Attachment #2: Cygwin-libstdc++-locale.patch --]
[-- Type: text/plain, Size: 10184 bytes --]

diff --git a/src/gcc-11.4.0/libstdc++-v3/config/locale/generic/c++locale_internal.h b/src/gcc-11.4.0/libstdc++-v3/config/locale/generic/c++locale_internal.h
index 3ab6af8..81d72f3 100644
--- a/src/gcc-11.4.0/libstdc++-v3/config/locale/generic/c++locale_internal.h
+++ b/src/gcc-11.4.0/libstdc++-v3/config/locale/generic/c++locale_internal.h
@@ -41,6 +41,107 @@
 
 #include <ext/concurrence.h>
 
+#ifdef __CYGWIN__
+typedef locale_t __c_locale;
+#define __locale_t locale_t
+#define __nl_langinfo_l nl_langinfo_l
+#define __strcoll_l strcoll_l
+#define __strftime_l strftime_l
+#define __strtod_l strtod_l
+#define __strtof_l strtof_l
+#define __strtold_l strtold_l
+#define __strxfrm_l strxfrm_l
+#define __newlocale newlocale
+#define __freelocale freelocale
+#define __duplocale duplocale
+#define __uselocale uselocale
+#ifdef _GLIBCXX_USE_WCHAR_T
+#define __iswctype_l iswctype_l
+#define __towlower_l towlower_l
+#define __towupper_l towupper_l
+#define __wcscoll_l wcscoll_l
+#define __wcsftime_l wcsftime_l
+#define __wcsxfrm_l wcsxfrm_l
+#define __wctype_l wctype_l
+#endif
+// monetary
+#define __MON_DECIMAL_POINT _NL_MONETARY_MON_DECIMAL_POINT
+#define __MON_THOUSANDS_SEP _NL_MONETARY_MON_THOUSANDS_SEP
+#define __INT_FRAC_DIGITS _NL_MONETARY_INT_FRAC_DIGITS
+#define __MON_GROUPING _NL_MONETARY_MON_GROUPING
+#define __POSITIVE_SIGN _NL_MONETARY_POSITIVE_SIGN
+#define __NEGATIVE_SIGN _NL_MONETARY_NEGATIVE_SIGN
+#define __INT_CURR_SYMBOL _NL_MONETARY_INT_CURR_SYMBOL
+#define __INT_P_SIGN_POSN _NL_MONETARY_INT_P_SIGN_POSN
+#define __INT_N_SIGN_POSN _NL_MONETARY_INT_N_SIGN_POSN
+#define __INT_P_CS_PRECEDES _NL_MONETARY_INT_P_CS_PRECEDES
+#define __INT_N_CS_PRECEDES _NL_MONETARY_INT_N_CS_PRECEDES
+#define __INT_P_SEP_BY_SPACE _NL_MONETARY_INT_P_SEP_BY_SPACE
+#define __INT_N_SEP_BY_SPACE _NL_MONETARY_INT_N_SEP_BY_SPACE
+#define __CURRENCY_SYMBOL _NL_MONETARY_CURRENCY_SYMBOL
+#define __P_SIGN_POSN _NL_MONETARY_P_SIGN_POSN
+#define __N_SIGN_POSN _NL_MONETARY_N_SIGN_POSN
+#define __P_CS_PRECEDES _NL_MONETARY_P_CS_PRECEDES
+#define __N_CS_PRECEDES _NL_MONETARY_N_CS_PRECEDES
+#define __P_SEP_BY_SPACE _NL_MONETARY_P_SEP_BY_SPACE
+#define __N_SEP_BY_SPACE _NL_MONETARY_N_SEP_BY_SPACE
+#define __FRAC_DIGITS _NL_MONETARY_FRAC_DIGITS
+#define _NL_MONETARY_DECIMAL_POINT_WC _NL_MONETARY_WMON_DECIMAL_POINT
+#define _NL_MONETARY_THOUSANDS_SEP_WC _NL_MONETARY_WMON_THOUSANDS_SEP
+// numeric
+#define DECIMAL_POINT _NL_MONETARY_MON_DECIMAL_POINT // No other appropriate ones.
+#define THOUSANDS_SEP _NL_MONETARY_MON_THOUSANDS_SEP // No other appropriate ones.
+#define GROUPING _NL_NUMERIC_GROUPING
+// time
+#define _NL_WD_FMT _NL_TIME_WD_FMT
+#define _NL_WD_T_FMT _NL_TIME_WD_T_FMT
+#define _NL_WT_FMT _NL_TIME_WT_FMT
+#define _NL_WERA_D_FMT _NL_TIME_WERA_D_FMT
+#define _NL_WERA_D_T_FMT _NL_TIME_WERA_D_T_FMT
+#define _NL_WERA_T_FMT _NL_TIME_WERA_T_FMT
+#define _NL_WAM_STR _NL_TIME_WAM_STR
+#define _NL_WPM_STR _NL_TIME_WPM_STR
+#define _NL_WT_FMT_AMPM _NL_TIME_WT_FMT_AMPM
+#define _NL_WDAY_1 _NL_TIME_WWEEKDAY_1
+#define _NL_WDAY_2 _NL_TIME_WWEEKDAY_2
+#define _NL_WDAY_3 _NL_TIME_WWEEKDAY_3
+#define _NL_WDAY_4 _NL_TIME_WWEEKDAY_4
+#define _NL_WDAY_5 _NL_TIME_WWEEKDAY_5
+#define _NL_WDAY_6 _NL_TIME_WWEEKDAY_6
+#define _NL_WDAY_7 _NL_TIME_WWEEKDAY_7
+#define _NL_WABDAY_1 _NL_TIME_WWDAY_1
+#define _NL_WABDAY_2 _NL_TIME_WWDAY_2
+#define _NL_WABDAY_3 _NL_TIME_WWDAY_3
+#define _NL_WABDAY_4 _NL_TIME_WWDAY_4
+#define _NL_WABDAY_5 _NL_TIME_WWDAY_5
+#define _NL_WABDAY_6 _NL_TIME_WWDAY_6
+#define _NL_WABDAY_7 _NL_TIME_WWDAY_7
+#define _NL_WMON_1 _NL_TIME_WMONTH_1
+#define _NL_WMON_2 _NL_TIME_WMONTH_2
+#define _NL_WMON_3 _NL_TIME_WMONTH_3
+#define _NL_WMON_4 _NL_TIME_WMONTH_4
+#define _NL_WMON_5 _NL_TIME_WMONTH_5
+#define _NL_WMON_6 _NL_TIME_WMONTH_6
+#define _NL_WMON_7 _NL_TIME_WMONTH_7
+#define _NL_WMON_8 _NL_TIME_WMONTH_8
+#define _NL_WMON_9 _NL_TIME_WMONTH_9
+#define _NL_WMON_10 _NL_TIME_WMONTH_10
+#define _NL_WMON_11 _NL_TIME_WMONTH_11
+#define _NL_WMON_12 _NL_TIME_WMONTH_12
+#define _NL_WABMON_1 _NL_TIME_WMON_1
+#define _NL_WABMON_2 _NL_TIME_WMON_2
+#define _NL_WABMON_3 _NL_TIME_WMON_3
+#define _NL_WABMON_4 _NL_TIME_WMON_4
+#define _NL_WABMON_5 _NL_TIME_WMON_5
+#define _NL_WABMON_6 _NL_TIME_WMON_6
+#define _NL_WABMON_7 _NL_TIME_WMON_7
+#define _NL_WABMON_8 _NL_TIME_WMON_8
+#define _NL_WABMON_9 _NL_TIME_WMON_9
+#define _NL_WABMON_10 _NL_TIME_WMON_10
+#define _NL_WABMON_11 _NL_TIME_WMON_11
+#define _NL_WABMON_12 _NL_TIME_WMON_12
+#else // __CYGWIN__
+
 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
 
 extern "C" __typeof(nl_langinfo_l) __nl_langinfo_l;
@@ -67,6 +168,8 @@ extern "C" __typeof(wctype_l) __wctype_l;
 
 #endif // GLIBC 2.3 and later
 
+#endif // __CYGWIN__
+
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
diff --git a/src/gcc-11.4.0/libstdc++-v3/config/locale/generic/c_locale.cc b/src/gcc-11.4.0/libstdc++-v3/config/locale/generic/c_locale.cc
index 45437e7..177882c 100644
--- a/src/gcc-11.4.0/libstdc++-v3/config/locale/generic/c_locale.cc
+++ b/src/gcc-11.4.0/libstdc++-v3/config/locale/generic/c_locale.cc
@@ -28,6 +28,9 @@
 
 // Written by Benjamin Kosnik <bkoz@redhat.com>
 
+#ifdef __CYGWIN__
+#define _GNU_SOURCE 1
+#endif
 #include <locale>
 #include <stdexcept>
 #include <limits>
diff --git a/src/gcc-11.4.0/libstdc++-v3/config/locale/generic/c_locale.h b/src/gcc-11.4.0/libstdc++-v3/config/locale/generic/c_locale.h
index bc24355..6f13e06 100644
--- a/src/gcc-11.4.0/libstdc++-v3/config/locale/generic/c_locale.h
+++ b/src/gcc-11.4.0/libstdc++-v3/config/locale/generic/c_locale.h
@@ -49,7 +49,11 @@ namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
+#ifdef __CYGWIN__
+#define __uselocale uselocale
+#else
   extern "C" __typeof(uselocale) __uselocale;
+#endif
 
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
@@ -59,7 +63,11 @@ namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
+#ifdef __CYGWIN__
+  typedef locale_t		__c_locale;
+#else
   typedef __locale_t		__c_locale;
+#endif
 
   // Convert numeric value of type double and long double to string and
   // return length of string.  If vsnprintf is available use it, otherwise
diff --git a/src/gcc-11.4.0/libstdc++-v3/config/locale/generic/ctype_members.cc b/src/gcc-11.4.0/libstdc++-v3/config/locale/generic/ctype_members.cc
index e7a66f1..ee3c236 100644
--- a/src/gcc-11.4.0/libstdc++-v3/config/locale/generic/ctype_members.cc
+++ b/src/gcc-11.4.0/libstdc++-v3/config/locale/generic/ctype_members.cc
@@ -32,6 +32,15 @@
 #include <cstdio>
 #include <bits/c++locale_internal.h>
 
+#ifdef __CYGWIN__
+# include <endian.h>
+# if __BYTE_ORDER == __BIG_ENDIAN
+#  define _ISbit(bit)        (1 << (bit))
+# else /* __BYTE_ORDER == __LITTLE_ENDIAN */
+#  define _ISbit(bit)        ((bit) < 8 ? ((1 << (bit)) << 8) : ((1 << (bit)) >> 8))
+# endif
+#endif
+
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -45,9 +54,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       {
 	this->_S_destroy_c_locale(this->_M_c_locale_ctype);
 	this->_S_create_c_locale(this->_M_c_locale_ctype, __s);
+#ifndef __CYGWIN__
 	this->_M_toupper = this->_M_c_locale_ctype->__ctype_toupper;
 	this->_M_tolower = this->_M_c_locale_ctype->__ctype_tolower;
 	this->_M_table = this->_M_c_locale_ctype->__ctype_b;
+#endif
       }
   }
 
@@ -94,9 +105,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       case graph:
 	__ret = __wctype_l("graph", _M_c_locale_ctype);
 	break;
+#ifndef __CYGWIN__
       case blank:
 	__ret = __wctype_l("blank", _M_c_locale_ctype);
 	break;
+#endif
       default:
 	__ret = __wmask_type();
       }
diff --git a/src/gcc-11.4.0/libstdc++-v3/config/locale/generic/monetary_members.cc b/src/gcc-11.4.0/libstdc++-v3/config/locale/generic/monetary_members.cc
index 0b7e0ec..05c4161 100644
--- a/src/gcc-11.4.0/libstdc++-v3/config/locale/generic/monetary_members.cc
+++ b/src/gcc-11.4.0/libstdc++-v3/config/locale/generic/monetary_members.cc
@@ -596,12 +596,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  setlocale(LC_ALL, __name);
 #endif
 
+#ifdef __CYGWIN__
+	  union { char *__s; wchar_t *__w; } __u;
+	  __u.__s = __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC, __cloc);
+	  _M_data->_M_decimal_point = *__u.__w;
+
+	  __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc);
+	  _M_data->_M_thousands_sep = *__u.__w;
+#else
 	  union { char *__s; wchar_t __w; } __u;
 	  __u.__s = __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC, __cloc);
 	  _M_data->_M_decimal_point = __u.__w;
 
 	  __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc);
 	  _M_data->_M_thousands_sep = __u.__w;
+#endif
 
 	  // Check for NULL, which implies no fractional digits.
 	  if (_M_data->_M_decimal_point == L'\0')
diff --git a/src/gcc-11.4.0/libstdc++-v3/config/locale/generic/numeric_members.cc b/src/gcc-11.4.0/libstdc++-v3/config/locale/generic/numeric_members.cc
index 19bf7d1..a793140 100644
--- a/src/gcc-11.4.0/libstdc++-v3/config/locale/generic/numeric_members.cc
+++ b/src/gcc-11.4.0/libstdc++-v3/config/locale/generic/numeric_members.cc
@@ -206,6 +206,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       else
 	{
 	  // Named locale.
+#ifdef __CYGWIN__
+	  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;
+#else
 	  // 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);
@@ -213,6 +221,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 	  __u.__s = __nl_langinfo_l(_NL_NUMERIC_THOUSANDS_SEP_WC, __cloc);
 	  _M_data->_M_thousands_sep = __u.__w;
+#endif
 
 	  // Check for NULL, which implies no grouping.
 	  if (_M_data->_M_thousands_sep == L'\0')

[-- Attachment #3: gcc.cygport --]
[-- Type: text/plain, Size: 16153 bytes --]

# -*- mode: sh; sh-shell: bash -*-
BUILD_REQUIRES=""
################################################################################
#
# Cygport control script for gcc.
#
# Copyright (C) 2008, 2009, 2010 Dave Korn
#
# This script 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 of the License, or
# (at your option) any later version.
#
# This script 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.
#
# You should have received a copy of the GNU General Public License
# along with this script.  If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
TOOLCHAIN_TARGET="native"
inherit toolchain python3

NAME="gcc"
VERSION="11.4.0"
RELEASE="1"
CATEGORY="Devel"
SUMMARY="GNU Compiler Collection"
DESCRIPTION="The GNU Compiler Collection includes front ends for C, C++,
Objective-C, Fortran, and Go, as well as libraries for these
languages (libstdc++, libgcj,...)."
HOMEPAGE="https://gcc.gnu.org/"
LICENSE="GPL-3.0-or-later"
GFMABI="15"
PVmaj=${PV%%.*}
case ${PV} in
    *+20[1-9][0-9][0-1][0-9][0-3][0-9]) # snapshot
	SD=${PV##*+}
	SRC_URI="  mirror://gcc/snapshots/${PVmaj}-${SD}/gcc-${PVmaj}-${SD}.tar.xz"
	SRC_URI+=" mirror://gcc/snapshots/${PVmaj}-${SD}/sha512.sum#/gcc-${PVmaj}-${SD}.tar.xz.sha512"
	SRC_DIR="gcc-${PVmaj}-${SD}"
	;;
    *)                                  # release
	SRC_URI="  mirror://gnu/gcc/gcc-${PV}/gcc-${PV}.tar.xz"
	SRC_URI+=" mirror://gnu/gcc/gcc-${PV}/gcc-${PV}.tar.xz.sig"
	SRC_DIR="gcc-${PV}"
	;;
esac
SRC_URI+=" Cygwin-libstdc++-locale.patch"
# patches re-created in cygwin-gcc git branch cygwin-11.3.1
PATCH_URI="
  0001-Cygwin-use-SysV-ABI-on-x86_64.patch
  0002-Cygwin-add-dummy-pthread-tsaware-and-large-address-a.patch
  0003-Cygwin-handle-dllimport-properly-in-medium-model-V2.patch
  0004-Cygwin-MinGW-skip-test.patch
  0005-Cygwin-define-RTS_CONTROL_ENABLE-and-DTR_CONTROL_ENA.patch
  0007-Cygwin-__cxa-atexit.patch
  0008-Cygwin-libgomp-soname.patch
  0009-Cygwin-g-time.patch
  0010-Cygwin-newlib-ftm.patch
  0011-Cygwin-define-STD_UNIX.patch
"
# already fixed in snapshot
#  0006-Cygwin-fix-some-implicit-declaration-warnings-and-re.patch
#DISABLE_BOOTSTRAP=1
defined DISABLE_BOOTSTRAP &&
    inform "Disable Bootstrapping."
LIBGCCJIT=1
if defined DISABLE_LIBGCCJIT
then
    inform "Support for libgccjit disabled."
else
    PATCH_URI+="
      0101-Cygwin-enable-libgccjit-not-just-for-MingW.patch
      0102-Cygwin-testsuite-fixes-for-libgccjit.patch
    "
    inform "Support for libgccjit enabled."
fi
# Ada
PATCH_URI+="
  0201-Cygwin-ada-shared-prefix.patch
"

# CI hints
SCALLYWAG="nobuild notest nodeploy"

# new files created by patches, need to be removed if re-prep'ing
DISTCLEANFILES="config/mt-cygwin gcc/ada/system-cygwin-x86_64.ads libgomp/config/cygwin/plugin-suffix.h"

# These must not be set in the environment, but main cygport
# script tries to be too helpful here and confuses auto-detection
# process during gcc build stages.
unset CC CXX F77 FC GCJ GOC OBJC OBJCXX FCFLAGS FFLAGS CFLAGS CXXFLAGS

CYGPORT_USE_UNSTABLE_API=1
src_unpack_hook() {
        chmod a+x gcc/testsuite/ada/acats/run_test.exp
}

# gccgo: requires <ucontext.h>
# libexecdir: http://cygwin.com/ml/cygwin/2013-11/msg00018.html et al
# libssp: conflicts with builtin SSP
CYGCONF_ARGS="
    --libexecdir=/usr/lib
    --with-gcc-major-version-only
    --enable-shared --enable-shared-libgcc --enable-static
    --enable-version-specific-runtime-libs
    $(cross_compiling || echo --enable-bootstrap)
    --enable-__cxa_atexit
    --with-dwarf2
    ${ARCH_i686+--with-arch=i686} --with-tune=generic
    ${ARCH_i686+--disable-sjlj-exceptions}
    ${DISABLE_BOOTSTRAP+--disable-bootstrap}
    --enable-languages=ada,c,c++,d,fortran,lto,objc,obj-c++${LIBGCCJIT+,jit}
    --enable-graphite
    --enable-threads=posix
    --enable-libatomic
    --enable-libgomp
    --enable-libquadmath
    --enable-libquadmath-support
    --disable-libssp
    --enable-libada
    --disable-symvers
    --disable-multilib
    --with-gnu-ld --with-gnu-as
    --with-cloog-include=$(${TOOLCHAIN_TARGET}-gcc -print-sysroot)/usr/include/cloog-isl
    --without-libiconv-prefix
    --without-libintl-prefix
    --with-system-zlib
    --enable-linker-build-id
    --with-default-libstdcxx-abi=gcc4-compatible
    --enable-libstdcxx-filesystem-ts
"

MAKEOPTS+=" -Otarget"

src_compile() {
    # Enable c++ locale features for not just "C" locale.
    cd ${S}
    rm -r libstdc++-v3/config/locale/generic
    cp -r libstdc++-v3/config/locale/gnu libstdc++-v3/config/locale/generic
    patch -p 3 < Cygwin-libstdc++-locale.patch

    cd ${B}
    # use built-in SSP with Cygwin 2.10
    # FIXME: --disable-libssp should suffice in GCC 8
    # export gcc_cv_libc_provides_ssp=yes
    # configure tries to test SUSv4-compliant behaviour of
    # realpath(..., NULL) via _XOPEN_VERSION
    export glibcxx_cv_realpath=yes

    ___CFLAGS=`echo ${CFLAGS} | sed s/-Werror=format-security/-Wformat-security/g`
    ___CFLAGS=`echo ${___CFLAGS} | sed s/\(-Wp,\)\?-D_FORTIFY_SOURCE=[12]//g`
    ___CFLAGS=`echo ${___CFLAGS} | sed 's/[[:blank:]]\+/ /g'`

    ___CXXFLAGS=`echo ${CXXFLAGS} | sed s/-Werror=format-security/-Wformat-security/g`
    ___CXXFLAGS=`echo ${___CXXFLAGS} | sed s/\(-Wp,\)\?-D_FORTIFY_SOURCE=[12]//g`
    ___CXXFLAGS=`echo ${___CXXFLAGS} | sed 's/[[:blank:]]\+/ /g'`

    export CFLAGS=${___CFLAGS}
    export CXXFLAGS=${___CXXFLAGS}
    # MingW64 header clash
    export CPPFLAGS+=" -DWIN32_LEAN_AND_MEAN"
    # parallel make encounters problems frequently
    defined CYGPORT_RECOMPILE && echo recompile only ||
            cygconf # CYGCONF_ARGS defined above
    # make hangs after finishing everything on x86_64?
    #cygmake BOOT_CFLAGS="${CXXFLAGS}"
    make ${MAKEOPTS} BOOT_CFLAGS="${CXXFLAGS}" || true
}

# override default src_test, as we need to ignore failures and
# add build subdirectories to path so DLLs can definitely be found.
src_test() {
    local gccpath

    gccpath="${B}/gcc/ada/rts:"
    gccpath+="${B}/${TOOLCHAIN_TARGET}/libgcc/shlib:"
    gccpath+="${B}/${TOOLCHAIN_TARGET}/libatomic/.libs:"
    gccpath+="${B}/${TOOLCHAIN_TARGET}/libgfortran/.libs:"
    gccpath+="${B}/${TOOLCHAIN_TARGET}/libgomp/.libs:"
    gccpath+="${B}/${TOOLCHAIN_TARGET}/libobjc/.libs:"
    gccpath+="${B}/${TOOLCHAIN_TARGET}/libquadmath/.libs:"
    gccpath+="${B}/${TOOLCHAIN_TARGET}/libstdc++-v3/src/.libs:"

    cd ${B}
    # cygtest doesn't work since btest_gnudebuglink has no creation rule
    [ "no" != "${CYGPORT_RUN_UNSTABLE_TESTS-no}" ] &&
        PATH="${gccpath}${PATH}" make ${MAKEOPTS} -k check ||
	    echo "Unstable test, set CYGPORT_RUN_UNSTABLE_TESTS to run."
}

src_install() {
    cd ${B}
    # Appears to be a problem with parallel install; finclude/ dir
    # ends up empty somehow.
    cyginstall -j1

    # Workaround GCC install bug
    if defined ARCH_x86_64
    then
        mv ${D}/usr/lib/gcc/${TOOLCHAIN_TARGET}/lib/libgcc_s.dll.a ${D}/usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/
        #mv ${D}/usr/lib/gcc/${TOOLCHAIN_TARGET}/lib32/libgcc_s.dll.a ${D}/usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/32/
    fi

    # Move GDB auto-load to correct name and location
    dodir /usr/share/gdb/auto-load/usr/bin
    sed -i -e "/^libdir/ s|/lib/gcc/.*|/bin'|" \
        ${D}/usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/libstdc++.dll.a-gdb.py
    mv ${D}/usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/libstdc++.dll.a-gdb.py \
       ${D}/usr/share/gdb/auto-load/usr/bin/cygstdc++-6.dll-gdb.py
    python_optimize /usr/share/gcc-${PVmaj}/python

    # Move ADA DLLs
    mv -v ${D}/usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/adalib/cyggna*.dll ${D}/usr/bin/
    # rename libgna cyggna ${D}/usr/bin/libgna*.dll

    # Now move docs to correct location
    mkdir -p ${D}/usr/share/doc/${PN}
    tar -cj -C ${S} INSTALL | tar -xj -C ${D}/usr/share/doc/${PN}/

    # create standard aliases
    dosym gcc.exe /usr/bin/cc
    dosym ../bin/cpp.exe /usr/lib/cpp
    dosym gfortran.exe /usr/bin/f95

    cat > ${D}/usr/bin/c89 <<_EOF
#!/bin/sh
fl="-std=c89"
for opt; do
  case "\$opt" in
    -ansi|-std=c89|-std=iso9899:1990) fl="";;
    -std=*) echo "`basename \$0` called with non ANSI/ISO C option \$opt" >&2
            exit 1;;
  esac
done
exec /usr/bin/gcc \$fl \${1+"\$@"}
_EOF

    cat > ${D}/usr/bin/c99 <<_EOF
#!/bin/sh
fl="-std=c99"
for opt; do
  case "\$opt" in
    -std=c99|-std=iso9899:1999) fl="";;
    -std=*) echo "`basename \$0` called with non ISO C99 option \$opt" >&2
            exit 1;;
  esac
done
exec /usr/bin/gcc \$fl \${1+"\$@"}
_EOF
    chmod 755 ${D}/usr/bin/c?9

    # clean-up include-fixed
    mv ${D}/usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/include-fixed/*limits.h \
       ${D}/usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/include/
    rm -fr ${D}/usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/include-fixed/
}

KEEP_LA_FILES="none"

PKG_NAMES="${PN}-ada ${PN}-core ${PN}-g++ ${PN}-gdc ${PN}-fortran ${PN}-objc ${PN}-objc++"
PKG_NAMES+=" libatomic1 libgcc1 libgfortran5 libgomp1 libgnat11 libobjc4 libstdc++6 libquadmath0"
defined LIBGCCJIT &&
    PKG_NAMES+=" libgccjit0"
gcc_REQUIRES="${PN}${PVmaj} ${PN}-g++"
gcc_ada_SUMMARY="${SUMMARY} (Ada)"
gcc_ada_REQUIRES="${PN}${PVmaj}"
gcc_ada_CONTENTS="
    usr/bin/gnat*.exe
    usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/ada_target_properties
    usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/adainclude
    usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/adalib
    usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/gnat1.exe
    usr/share/info/gnat-style.info*
    usr/share/info/gnat_rm.info*
    usr/share/info/gnat_ugn.info*
"
gcc_core_SUMMARY="${SUMMARY} (C, OpenMP)"
gcc_core_REQUIRES="binutils cygwin-devel w32api-headers w32api-runtime windows-default-manifest"
gcc_core_OBSOLETES="${PN}-ada ${PN}-cilkplus"
gcc_core_PROVIDES="${PN}${PVmaj}"
gcc_core_CONTENTS="
    --exclude=jni*.h
    usr/bin/cc
    usr/bin/c89
    usr/bin/c99
    usr/bin/cpp.exe
    usr/bin/gcc.exe
    usr/bin/gcc-ar.exe
    usr/bin/gcc-nm.exe
    usr/bin/gcc-ranlib.exe
    usr/bin/gcov.exe
    usr/bin/gcov-tool.exe
    usr/bin/gcov-dump.exe
    usr/bin/lto-dump.exe
    usr/bin/${TOOLCHAIN_TARGET}-gcc-${PVmaj}.exe
    usr/bin/${TOOLCHAIN_TARGET}-gcc.exe
    usr/bin/${TOOLCHAIN_TARGET}-gcc-ar.exe
    usr/bin/${TOOLCHAIN_TARGET}-gcc-nm.exe
    usr/bin/${TOOLCHAIN_TARGET}-gcc-ranlib.exe
    usr/lib/cpp
    usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/include/*.h
    usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/install-tools
    usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/cc1.exe
    usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/collect2.exe
    usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/crt*.o
    usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/cyglto_plugin.dll
    usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/libatomic.*
    usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/libgcc*
    usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/libgcov.*
    usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/libgomp.*
    usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/libquadmath.*
    usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/lto*.exe
    usr/share/doc/${PN}/
    usr/share/info/cpp.info*
    usr/share/info/cppinternals.info*
    usr/share/info/gcc.info*
    usr/share/info/gccinstall.info*
    usr/share/info/gccint.info*
    usr/share/info/libgomp.info*
    usr/share/info/libquadmath.info*
    usr/share/locale/*
    usr/share/man/man1/cpp.1*
    usr/share/man/man1/gcc.1*
    usr/share/man/man1/gcov.1*
    usr/share/man/man1/gcov-dump.1.*
    usr/share/man/man1/gcov-tool.1.*
    usr/share/man/man1/lto-dump.1.*
    usr/share/man/man7/fsf-funding.7*
    usr/share/man/man7/gfdl.7*
    usr/share/man/man7/gpl.7*
"
gcc_g___SUMMARY="${SUMMARY} (C++)"
gcc_g___REQUIRES="${PN}${PVmaj}"
gcc_g___CONTENTS="
    --exclude=gnu
    usr/bin/c++.exe
    usr/bin/g++.exe
    usr/bin/${TOOLCHAIN_TARGET}-c++.exe
    usr/bin/${TOOLCHAIN_TARGET}-g++.exe
    usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/cc1plus.exe
    usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/g++-mapper-server.exe*
    usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/include/c++
    usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/libstdc++*
    usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/libsupc++*
    usr/share/man/man1/g++.1*
"
gcc_gdc_SUMMARY="${SUMMARY} (D)"
gcc_gdc_REQUIRES="${PN}${PVmaj}"
gcc_gdc_CONTENTS="
    --exclude=gnu
    usr/bin/gdc.exe
    usr/bin/${TOOLCHAIN_TARGET}-gdc.exe
    usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/d21.exe
    usr/share/info/gdc.info*
    usr/share/man/man1/gdc.1*
"
gcc_fortran_SUMMARY="${SUMMARY} (Fortran)"
gcc_fortran_REQUIRES="${PN}${PVmaj}"
gcc_fortran_PROVIDES="gfm${GFMABI}" # GNU Fortran Module version
gcc_fortran_CONTENTS="
    usr/bin/f95
    usr/bin/gfortran.exe
    usr/bin/${TOOLCHAIN_TARGET}-gfortran.exe
    usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/finclude/
    usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/f951.exe
    usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/libcaf_single.a
    usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/libgfortran*
    usr/share/info/gfortran.info*
    usr/share/man/man1/gfortran.1*
"
gcc_objc_SUMMARY="${SUMMARY} (Objective-C)"
gcc_objc_REQUIRES="${PN}${PVmaj}"
gcc_objc_CONTENTS="
    usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/include/objc/
    usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/cc1obj.exe
    usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/libobjc.*
"
gcc_objc___SUMMARY="${SUMMARY} (Objective-C++)"
gcc_objc___REQUIRES="${PN}${PVmaj} ${PN}-g++ ${PN}-objc"
gcc_objc___CONTENTS="
    usr/lib/gcc/${TOOLCHAIN_TARGET}/${PVmaj}/cc1objplus.exe
"
libatomic1_CATEGORY="Libs"
libatomic1_SUMMARY="GCC C11/C++11 locked atomics runtime library"
libatomic1_CONTENTS="usr/bin/cygatomic-1.dll"
libgcc1_CATEGORY="Libs"
libgcc1_SUMMARY="GCC C runtime library"
libgcc1_CONTENTS="usr/bin/cyggcc_s${ARCH_x86_64+-seh}-1.dll"
libgfortran5_CATEGORY="Libs"
libgfortran5_SUMMARY="GCC Fortran runtime library"
libgfortran5_CONTENTS="usr/bin/cyggfortran-5.dll"
libgnat11_CATEGORY="Libs"
libgnat11_SUMMARY="GCC Ada runtime library"
libgnat11_CONTENTS="usr/bin/cyggnarl-11.dll usr/bin/cyggnat-11.dll"
libgomp1_CATEGORY="Libs"
libgomp1_SUMMARY="GCC OpenMP runtime library"
libgomp1_CONTENTS="usr/bin/cyggomp-1.dll"
libobjc4_CATEGORY="Libs"
libobjc4_SUMMARY="GCC Objective-C runtime library"
libobjc4_CONTENTS="usr/bin/cygobjc-4.dll"
libstdc__6_CATEGORY="Libs"
libstdc__6_SUMMARY="GCC C++ runtime library"
libstdc__6_CONTENTS="usr/bin/cygstdc++-6.dll"
libstdc__devel_CATEGORY="_obsolete"
libstdc__devel_SUMMARY="Obsolete package"
libquadmath0_CATEGORY="Libs"
libquadmath0_SUMMARY="GCC Quad-Precision Math runtime library"
libquadmath0_CONTENTS="usr/bin/cygquadmath-0.dll"
libvtv0_CATEGORY="Libs"
libvtv0_SUMMARY="GCC vtable verification library"
libvtv0_CONTENTS="usr/bin/cygvtv-0.dll usr/bin/cygvtv_stubs-0.dll"
gcc_debuginfo_CONTENTS+=" usr/share/gcc-${PVmaj}/python/libstdcxx/"
if defined LIBGCCJIT
then
    inform "Package libgccjit0 will be provided."
    libgccjit0_CATEGORY="Libs"
    libgccjit0_SUMMARY="GCC JIT runtime library, header files and documentation"
    libgccjit0_CONTENTS="
        usr/bin/cyggccjit-0.dll
        usr/include/libgccjit*
        usr/lib/libgccjit.dll.a
        usr/share/info/libgccjit.info.gz
"
    libgccjit0_REQUIRES="gcc-core"
fi

DIFF_EXCLUDES="
    c_locale.cc
    c_locale.h
    c++locale_internal.h
    codecvt_members.cc
    collate_members.cc
    ctype_members.cc
    messages_members.cc
    messages_members.h
    monetary_members.cc
    numeric_members.cc
    time_members.cc
    time_members.h
"

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #4: gcc-11.4.0.src.patch --]
[-- Type: text/poain; name="gcc-11.4.0.src.patch", Size: 659 bytes --]

diff --git a/src/gcc-11.4.0/libstdc++-v3/src/Makefile.in b/src/gcc-11.4.0/libstdc++-v3/src/Makefile.in
index 2fff462..7cef94d 100644
--- a/src/gcc-11.4.0/libstdc++-v3/src/Makefile.in
+++ b/src/gcc-11.4.0/libstdc++-v3/src/Makefile.in
@@ -535,7 +535,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 -lintl
 
 libstdc___la_LINK = $(CXXLINK) $(libstdc___la_LDFLAGS) $(lt_host_flags)
 @GLIBCXX_LDBL_ALT128_COMPAT_FALSE@@GLIBCXX_LDBL_COMPAT_TRUE@LTCXXCOMPILE64 = $(LTCXXCOMPILE)

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: std::runtime_error on std::locale("")
  2023-09-23  8:23   ` Takashi Yano
@ 2023-09-23  8:42     ` Takashi Yano
  2023-09-27 10:50     ` Takashi Yano
  1 sibling, 0 replies; 13+ messages in thread
From: Takashi Yano @ 2023-09-23  8:42 UTC (permalink / raw)
  To: cygwin

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?

Sorry,
the patch file name gcc-11.4.0.src.patch should be gcc-11.4.0-1.src.patch.

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

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: std::runtime_error on std::locale("")
  2023-09-23  8:23   ` Takashi Yano
  2023-09-23  8:42     ` Takashi Yano
@ 2023-09-27 10:50     ` Takashi Yano
  2023-12-31  6:57       ` Takashi Yano
  1 sibling, 1 reply; 13+ messages in thread
From: Takashi Yano @ 2023-09-27 10:50 UTC (permalink / raw)
  To: cygwin

[-- 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


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: std::runtime_error on std::locale("")
  2023-09-27 10:50     ` Takashi Yano
@ 2023-12-31  6:57       ` Takashi Yano
  0 siblings, 0 replies; 13+ messages in thread
From: Takashi Yano @ 2023-12-31  6:57 UTC (permalink / raw)
  To: cygwin

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

On Wed, 27 Sep 2023 19:50:39 +0900
Takashi Yano via Cygwin <cygwin@cygwin.com> wrote:
> 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.

Some bugs have been fixed. Please review v3 patch attached.

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

[-- Attachment #2: v3-0001-libstdc-Implement-most-of-locale-features-for-new.patch --]
[-- Type: application/octet-stream, Size: 114703 bytes --]

From 6f4d937a77d48a47e78277b71ed09b31477f60c6 Mon Sep 17 00:00:00 2001
From: Takashi Yano <takashi.yano@nifty.ne.jp>
Date: Fri, 24 Nov 2023 00:34:48 +0900
Subject: [PATCH v3] 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.
---
 gcc/config/i386/cygwin.h                      |   2 +
 libgcc/config/i386/t-cygwin                   |   2 +-
 libstdc++-v3/Makefile.in                      |   1 +
 libstdc++-v3/acinclude.m4                     |  39 +-
 .../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 | 402 ++++++++
 libstdc++-v3/config/locale/newlib/c_locale.h  | 100 ++
 .../config/locale/newlib/codecvt_members.cc   | 288 ++++++
 .../config/locale/newlib/collate_members.cc   |  74 ++
 .../config/locale/newlib/ctype_members.cc     |  60 +-
 .../config/locale/newlib/messages_members.cc  | 178 ++++
 .../config/locale/newlib/messages_members.h   | 148 +++
 .../config/locale/newlib/monetary_members.cc  | 942 ++++++++++++++++++
 .../config/locale/newlib/numeric_members.cc   | 273 +++++
 .../config/locale/newlib/time_members.cc      | 381 +++++++
 .../config/locale/newlib/time_members.h       |  90 ++
 .../config/os/newlib/ctype_configure_char.cc  |  32 +-
 libstdc++-v3/configure                        |  66 +-
 .../include/bits/locale_facets_nonio.tcc      |   1 +
 libstdc++-v3/src/Makefile.in                  |   3 +-
 libstdc++-v3/src/c++98/locale_init.cc         |   3 +-
 25 files changed, 3111 insertions(+), 74 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/gcc/config/i386/cygwin.h b/gcc/config/i386/cygwin.h
index b2c45ab5f67..d896d527747 100644
--- a/gcc/config/i386/cygwin.h
+++ b/gcc/config/i386/cygwin.h
@@ -85,6 +85,8 @@ along with GCC; see the file COPYING3.  If not see
 #define LIB_SPEC "\
   %{pg:-lgmon} \
   %{pthread: } \
+  -lintl \
+  -liconv \
   -lcygwin \
   %{mwindows:-lgdi32 -lcomdlg32} \
   %{fvtable-verify=preinit:-lvtv -lpsapi; \
diff --git a/libgcc/config/i386/t-cygwin b/libgcc/config/i386/t-cygwin
index f85ec24220e..44d5e1b2425 100644
--- a/libgcc/config/i386/t-cygwin
+++ b/libgcc/config/i386/t-cygwin
@@ -5,7 +5,7 @@ LIBGCC2_INCLUDES += -I$(srcdir)/../winsup/include \
 	-I$(srcdir)/../winsup/cygwin/include
 
 # Cygwin-specific parts of LIB_SPEC
-SHLIB_LC = -lcygwin -ladvapi32 -lshell32 -luser32 -lkernel32
+SHLIB_LC = -lintl -liconv -lcygwin -ladvapi32 -lshell32 -luser32 -lkernel32
 
 # We have already included one of the t-{dw2,sjlj}-eh fragments for EH_MODEL
 SHLIB_EH_EXTENSION = $(subst -dw2,,-$(EH_MODEL))
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 7c843204d70..3cf9274674e 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -2434,7 +2434,7 @@ AC_DEFUN([GLIBCXX_ENABLE_CLOCALE], [
       dragonfly* | freebsd*)
 	enable_clocale_flag=dragonfly
 	;;
-      openbsd*)
+      openbsd* | cygwin*)
 	enable_clocale_flag=newlib
 	;;
       *)
@@ -2446,6 +2446,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
@@ -2610,19 +2614,30 @@ AC_DEFUN([GLIBCXX_ENABLE_CLOCALE], [
       ;;
     newlib)
       AC_MSG_RESULT(newlib)
+      AC_CHECK_HEADERS(libintl.h, ac_has_libintl_h=yes, ac_has_libintl_h=no)
+      AC_CHECK_HEADERS(iconv.h, ac_has_iconv_h=yes, ac_has_iconv_h=no)
 
-      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
+      if test $ac_has_libintl_h = yes; then
+	CMESSAGES_H=config/locale/newlib/messages_members.h
+	CMESSAGES_CC=config/locale/newlib/messages_members.cc
+      else
+	CMESSAGES_H=config/locale/generic/messages_members.h
+	CMESSAGES_CC=config/locale/generic/messages_members.cc
+      fi
+      CMONEY_CC=config/locale/newlib/monetary_members.cc
+      if test $ac_has_iconv_h = yes; then
+	CNUMERIC_CC=config/locale/newlib/numeric_members.cc
+      else
+	CNUMERIC_CC=config/locale/generic/numeric_members.cc
+      fi
+      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..b181999a2d1
--- /dev/null
+++ b/libstdc++-v3/config/locale/newlib/c_locale.cc
@@ -0,0 +1,402 @@
+// 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>
+
+#if __POSIX_VISIBLE < 200809
+struct __locale_t;
+typedef struct __locale_t *locale_t;
+
+#define LC_ALL_MASK		(1 << LC_ALL)
+#define LC_COLLATE_MASK		(1 << LC_COLLATE)
+#define LC_CTYPE_MASK		(1 << LC_CTYPE)
+#define LC_MONETARY_MASK	(1 << LC_MONETARY)
+#define LC_NUMERIC_MASK		(1 << LC_NUMERIC)
+#define LC_TIME_MASK		(1 << LC_TIME)
+#define LC_MESSAGES_MASK	(1 << LC_MESSAGES)
+
+extern "C" locale_t newlocale(int, const char *, locale_t);
+extern "C" void freelocale(locale_t);
+extern "C" locale_t duplocale(locale_t);
+extern "C" locale_t uselocale(locale_t);
+#endif /* __POSIX_VISIBLE < 200809 */
+
+/* Newlib constant */
+#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..c189abc872b
--- /dev/null
+++ b/libstdc++-v3/config/locale/newlib/c_locale.h
@@ -0,0 +1,100 @@
+// 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>
+
+#if __POSIX_VISIBLE < 200809
+struct __locale_t;
+typedef struct __locale_t *locale_t;
+
+#define LC_ALL_MASK		(1 << LC_ALL)
+#define LC_COLLATE_MASK		(1 << LC_COLLATE)
+#define LC_CTYPE_MASK		(1 << LC_CTYPE)
+#define LC_MONETARY_MASK	(1 << LC_MONETARY)
+#define LC_NUMERIC_MASK		(1 << LC_NUMERIC)
+#define LC_TIME_MASK		(1 << LC_TIME)
+#define LC_MESSAGES_MASK	(1 << LC_MESSAGES)
+
+extern "C" locale_t newlocale(int, const char *, locale_t);
+extern "C" void freelocale(locale_t);
+extern "C" locale_t duplocale(locale_t);
+extern "C" locale_t uselocale(locale_t);
+#endif /* __POSIX_VISIBLE < 200809 */
+
+#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..0e0efe47cc1 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;
@@ -144,11 +144,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   do_is(mask __m, wchar_t __c) const
   {
     bool __ret = false;
-    // Newlib C library has a compact encoding that uses 8 bits only.
     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;
@@ -162,11 +161,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   {
     for (; __lo < __hi; ++__vec, ++__lo)
       {
-	// Newlib C library has a compact encoding that uses 8 bits only.
 	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 +213,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 +224,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 +246,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 +267,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..463533a26a2
--- /dev/null
+++ b/libstdc++-v3/config/locale/newlib/messages_members.cc
@@ -0,0 +1,178 @@
+// 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)
+  {
+    if (char* __sav = strdup(setlocale(LC_ALL, 0)))
+      {
+	setlocale(LC_ALL, __name_messages);
+	const char* __msg = dgettext(__domainname, __dfault);
+	setlocale(LC_ALL, __sav);
+	free(__sav);
+	return __msg;
+      }
+    return __dfault;
+  }
+}
+
+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..64b66d9a7fb
--- /dev/null
+++ b/libstdc++-v3/config/locale/newlib/messages_members.h
@@ -0,0 +1,148 @@
+// 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>
+#include <cassert>
+
+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)
+    {
+      assert(this->_M_name_messages == locale::facet::_S_get_c_name());
+      if (__builtin_strcmp(__s, this->_M_name_messages) != 0)
+	{
+	  const size_t __len = __builtin_strlen(__s) + 1;
+	  char* __tmp = new char[__len];
+	  __builtin_memcpy(__tmp, __s, __len);
+	  this->_M_name_messages = __tmp;
+	}
+
+      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..9acd1a39f24
--- /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 = 0;
+	    /* *(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 = 1;
+	    /* *(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 = 0;
+	    /* *(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 = 1;
+	    /* *(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..cbd3c3b9f73
--- /dev/null
+++ b/libstdc++-v3/config/locale/newlib/numeric_members.cc
@@ -0,0 +1,273 @@
+// 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.
+	  __c_locale __old = uselocale(__cloc);
+	  union { char *__s; wchar_t *__w; } __u;
+	  __u.__s = nl_langinfo_l(_NL_NUMERIC_DECIMAL_POINT_WC, __cloc);
+	  _M_data->_M_decimal_point = wctob(*__u.__w);
+
+	  __u.__s = nl_langinfo_l(_NL_NUMERIC_THOUSANDS_SEP_WC, __cloc);
+	  _M_data->_M_thousands_sep = wctob(*__u.__w);
+	  uselocale(__old);
+
+	  // 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..190ef480e29
--- /dev/null
+++ b/libstdc++-v3/config/locale/newlib/time_members.cc
@@ -0,0 +1,381 @@
+// 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);
+	  __cloc = _M_c_locale_timepunct;
+
+	  _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);
+	  __cloc = _M_c_locale_timepunct;
+
+	  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/config/os/newlib/ctype_configure_char.cc b/libstdc++-v3/config/os/newlib/ctype_configure_char.cc
index 2f3727e5309..cfab413dd78 100644
--- a/libstdc++-v3/config/os/newlib/ctype_configure_char.cc
+++ b/libstdc++-v3/config/os/newlib/ctype_configure_char.cc
@@ -42,42 +42,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   ctype<char>::classic_table() throw()
   { return _ctype_ + 1; }
 
-  ctype<char>::ctype(__c_locale, const mask* __table, bool __del,
+  ctype<char>::ctype(__c_locale __cloc, const mask* __table, bool __del,
 		     size_t __refs)
-  : facet(__refs), _M_del(__table != 0 && __del),
+  : facet(__refs), _M_c_locale_ctype(_S_clone_c_locale(__cloc)),
+  _M_del(__table != 0 && __del),
   _M_toupper(NULL), _M_tolower(NULL),
-  _M_table(__table ? __table : classic_table())
+  _M_table(__table ? __table : classic_table()),
+  _M_widen_ok(0), _M_narrow_ok(0)
   {
     memset(_M_widen, 0, sizeof(_M_widen));
-    _M_widen_ok = 0;
     memset(_M_narrow, 0, sizeof(_M_narrow));
-    _M_narrow_ok = 0;
   }
 
   ctype<char>::ctype(const mask* __table, bool __del, size_t __refs)
-  : facet(__refs), _M_del(__table != 0 && __del),
+  : facet(__refs), _M_c_locale_ctype(_S_get_c_locale()),
+  _M_del(__table != 0 && __del),
   _M_toupper(NULL), _M_tolower(NULL),
-  _M_table(__table ? __table : classic_table())
+  _M_table(__table ? __table : classic_table()),
+  _M_widen_ok(0), _M_narrow_ok(0)
   {
     memset(_M_widen, 0, sizeof(_M_widen));
-    _M_widen_ok = 0;
     memset(_M_narrow, 0, sizeof(_M_narrow));
-    _M_narrow_ok = 0;
   }
 
   char
   ctype<char>::do_toupper(char __c) const
-  {
-    int __x = __c;
-    return (this->is(ctype_base::lower, __c) ? (__x - 'a' + 'A') : __x);
-  }
+  { return ::toupper((int) __c); }
 
   const char*
   ctype<char>::do_toupper(char* __low, const char* __high) const
   {
     while (__low < __high)
       {
-	*__low = this->do_toupper(*__low);
+	*__low = ::toupper((int) *__low);
 	++__low;
       }
     return __high;
@@ -85,17 +82,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   char
   ctype<char>::do_tolower(char __c) const
-  {
-    int __x = __c;
-    return (this->is(ctype_base::upper, __c) ? (__x - 'A' + 'a') : __x);
-  }
+  { return ::tolower((int) __c); }
 
   const char*
   ctype<char>::do_tolower(char* __low, const char* __high) const
   {
     while (__low < __high)
       {
-	*__low = this->do_tolower(*__low);
+	*__low = ::tolower((int) *__low);
 	++__low;
       }
     return __high;
diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
index 53882c3f6b6..69613f3a6ca 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
@@ -16514,7 +16515,7 @@ fi
       dragonfly* | freebsd*)
 	enable_clocale_flag=dragonfly
 	;;
-      openbsd*)
+      openbsd* | cygwin*)
 	enable_clocale_flag=newlib
 	;;
       *)
@@ -16526,6 +16527,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
@@ -16785,19 +16790,56 @@ $as_echo "IEEE 1003.1" >&6; }
     newlib)
       { $as_echo "$as_me:${as_lineno-$LINENO}: result: newlib" >&5
 $as_echo "newlib" >&6; }
+      for ac_header in libintl.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "libintl.h" "ac_cv_header_libintl_h" "$ac_includes_default"
+if test "x$ac_cv_header_libintl_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBINTL_H 1
+_ACEOF
+ ac_has_libintl_h=yes
+else
+  ac_has_libintl_h=no
+fi
 
-      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
+done
+
+      for ac_header in iconv.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "iconv.h" "ac_cv_header_iconv_h" "$ac_includes_default"
+if test "x$ac_cv_header_iconv_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_ICONV_H 1
+_ACEOF
+ ac_has_iconv_h=yes
+else
+  ac_has_iconv_h=no
+fi
+
+done
+
+
+      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
+      if test $ac_has_libintl_h = yes; then
+	CMESSAGES_H=config/locale/newlib/messages_members.h
+	CMESSAGES_CC=config/locale/newlib/messages_members.cc
+      else
+	CMESSAGES_H=config/locale/generic/messages_members.h
+	CMESSAGES_CC=config/locale/generic/messages_members.cc
+      fi
+      CMONEY_CC=config/locale/newlib/monetary_members.cc
+      if test $ac_has_iconv_h = yes; then
+	CNUMERIC_CC=config/locale/newlib/numeric_members.cc
+      else
+	CNUMERIC_CC=config/locale/generic/numeric_members.cc
+      fi
+      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/include/bits/locale_facets_nonio.tcc b/libstdc++-v3/include/bits/locale_facets_nonio.tcc
index b19f4425300..87e7faf5ab8 100644
--- a/libstdc++-v3/include/bits/locale_facets_nonio.tcc
+++ b/libstdc++-v3/include/bits/locale_facets_nonio.tcc
@@ -795,6 +795,7 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11
 		    }
 		  break;
 		case 'I':
+		case 'l': // for newlib
 		  // Hour [01, 12]. [tm_hour]
 		  __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2,
 					 __io, __tmperr);
diff --git a/libstdc++-v3/src/Makefile.in b/libstdc++-v3/src/Makefile.in
index f42d957af36..857c5eea1ca 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@
@@ -561,7 +562,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++98/locale_init.cc b/libstdc++-v3/src/c++98/locale_init.cc
index cfc22eaf5a4..582a816da65 100644
--- a/libstdc++-v3/src/c++98/locale_init.cc
+++ b/libstdc++-v3/src/c++98/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


^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2023-12-31  6:57 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-09-21 16:12 std::runtime_error on std::locale("") 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
2023-12-31  6:57       ` Takashi Yano

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).