cosmopolitan/third_party/libcxx/locale4.cc
2022-09-04 04:53:52 -07:00

1010 lines
25 KiB
C++

// clang-format off
//===------------------------- locale.cpp ---------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "third_party/libcxx/string"
#include "third_party/libcxx/locale"
#include "third_party/libcxx/codecvt"
#include "third_party/libcxx/vector"
#include "third_party/libcxx/algorithm"
#include "third_party/libcxx/typeinfo"
#ifndef _LIBCPP_NO_EXCEPTIONS
#include "third_party/libcxx/type_traits"
#endif
#include "third_party/libcxx/clocale"
#include "third_party/libcxx/cstring"
#include "third_party/libcxx/cwctype"
#include "third_party/libcxx/__sso_allocator"
#include "third_party/libcxx/include/atomic_support.hh"
#include "libc/str/locale.h"
#include "third_party/libcxx/countof.internal.hh"
#include "third_party/libcxx/__undef_macros"
// On Linux, wint_t and wchar_t have different signed-ness, and this causes
// lots of noise in the build log, but no bugs that I know of.
#if defined(__clang__)
#pragma clang diagnostic ignored "-Wsign-conversion"
#endif
_LIBCPP_BEGIN_NAMESPACE_STD
namespace {
_LIBCPP_NORETURN static void __throw_runtime_error(const string &msg)
{
#ifndef _LIBCPP_NO_EXCEPTIONS
throw runtime_error(msg);
#else
(void)msg;
_VSTD::abort();
#endif
}
} // namespace
// time_get
static
string*
init_weeks()
{
static string weeks[14];
weeks[0] = "Sunday";
weeks[1] = "Monday";
weeks[2] = "Tuesday";
weeks[3] = "Wednesday";
weeks[4] = "Thursday";
weeks[5] = "Friday";
weeks[6] = "Saturday";
weeks[7] = "Sun";
weeks[8] = "Mon";
weeks[9] = "Tue";
weeks[10] = "Wed";
weeks[11] = "Thu";
weeks[12] = "Fri";
weeks[13] = "Sat";
return weeks;
}
static
wstring*
init_wweeks()
{
static wstring weeks[14];
weeks[0] = L"Sunday";
weeks[1] = L"Monday";
weeks[2] = L"Tuesday";
weeks[3] = L"Wednesday";
weeks[4] = L"Thursday";
weeks[5] = L"Friday";
weeks[6] = L"Saturday";
weeks[7] = L"Sun";
weeks[8] = L"Mon";
weeks[9] = L"Tue";
weeks[10] = L"Wed";
weeks[11] = L"Thu";
weeks[12] = L"Fri";
weeks[13] = L"Sat";
return weeks;
}
template <>
const string*
__time_get_c_storage<char>::__weeks() const
{
static const string* weeks = init_weeks();
return weeks;
}
template <>
const wstring*
__time_get_c_storage<wchar_t>::__weeks() const
{
static const wstring* weeks = init_wweeks();
return weeks;
}
static
string*
init_months()
{
static string months[24];
months[0] = "January";
months[1] = "February";
months[2] = "March";
months[3] = "April";
months[4] = "May";
months[5] = "June";
months[6] = "July";
months[7] = "August";
months[8] = "September";
months[9] = "October";
months[10] = "November";
months[11] = "December";
months[12] = "Jan";
months[13] = "Feb";
months[14] = "Mar";
months[15] = "Apr";
months[16] = "May";
months[17] = "Jun";
months[18] = "Jul";
months[19] = "Aug";
months[20] = "Sep";
months[21] = "Oct";
months[22] = "Nov";
months[23] = "Dec";
return months;
}
static
wstring*
init_wmonths()
{
static wstring months[24];
months[0] = L"January";
months[1] = L"February";
months[2] = L"March";
months[3] = L"April";
months[4] = L"May";
months[5] = L"June";
months[6] = L"July";
months[7] = L"August";
months[8] = L"September";
months[9] = L"October";
months[10] = L"November";
months[11] = L"December";
months[12] = L"Jan";
months[13] = L"Feb";
months[14] = L"Mar";
months[15] = L"Apr";
months[16] = L"May";
months[17] = L"Jun";
months[18] = L"Jul";
months[19] = L"Aug";
months[20] = L"Sep";
months[21] = L"Oct";
months[22] = L"Nov";
months[23] = L"Dec";
return months;
}
template <>
const string*
__time_get_c_storage<char>::__months() const
{
static const string* months = init_months();
return months;
}
template <>
const wstring*
__time_get_c_storage<wchar_t>::__months() const
{
static const wstring* months = init_wmonths();
return months;
}
static
string*
init_am_pm()
{
static string am_pm[2];
am_pm[0] = "AM";
am_pm[1] = "PM";
return am_pm;
}
static
wstring*
init_wam_pm()
{
static wstring am_pm[2];
am_pm[0] = L"AM";
am_pm[1] = L"PM";
return am_pm;
}
template <>
const string*
__time_get_c_storage<char>::__am_pm() const
{
static const string* am_pm = init_am_pm();
return am_pm;
}
template <>
const wstring*
__time_get_c_storage<wchar_t>::__am_pm() const
{
static const wstring* am_pm = init_wam_pm();
return am_pm;
}
template <>
const string&
__time_get_c_storage<char>::__x() const
{
static string s("%m/%d/%y");
return s;
}
template <>
const wstring&
__time_get_c_storage<wchar_t>::__x() const
{
static wstring s(L"%m/%d/%y");
return s;
}
template <>
const string&
__time_get_c_storage<char>::__X() const
{
static string s("%H:%M:%S");
return s;
}
template <>
const wstring&
__time_get_c_storage<wchar_t>::__X() const
{
static wstring s(L"%H:%M:%S");
return s;
}
template <>
const string&
__time_get_c_storage<char>::__c() const
{
static string s("%a %b %d %H:%M:%S %Y");
return s;
}
template <>
const wstring&
__time_get_c_storage<wchar_t>::__c() const
{
static wstring s(L"%a %b %d %H:%M:%S %Y");
return s;
}
template <>
const string&
__time_get_c_storage<char>::__r() const
{
static string s("%I:%M:%S %p");
return s;
}
template <>
const wstring&
__time_get_c_storage<wchar_t>::__r() const
{
static wstring s(L"%I:%M:%S %p");
return s;
}
// time_get_byname
__time_get::__time_get(const char* nm)
: __loc_(newlocale(LC_ALL_MASK, nm, 0))
{
if (__loc_ == 0)
__throw_runtime_error("time_get_byname"
" failed to construct for " + string(nm));
}
__time_get::__time_get(const string& nm)
: __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
{
if (__loc_ == 0)
__throw_runtime_error("time_get_byname"
" failed to construct for " + nm);
}
__time_get::~__time_get()
{
freelocale(__loc_);
}
#if defined(__clang__)
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
#endif
#if defined(__GNUG__)
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#endif
template <>
string
__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
{
tm t = {0};
t.tm_sec = 59;
t.tm_min = 55;
t.tm_hour = 23;
t.tm_mday = 31;
t.tm_mon = 11;
t.tm_year = 161;
t.tm_wday = 6;
t.tm_yday = 364;
t.tm_isdst = -1;
char buf[100];
char f[3] = {0};
f[0] = '%';
f[1] = fmt;
size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
char* bb = buf;
char* be = buf + n;
string result;
while (bb != be)
{
if (ct.is(ctype_base::space, *bb))
{
result.push_back(' ');
for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
;
continue;
}
char* w = bb;
ios_base::iostate err = ios_base::goodbit;
ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
ct, err, false)
- this->__weeks_;
if (i < 14)
{
result.push_back('%');
if (i < 7)
result.push_back('A');
else
result.push_back('a');
bb = w;
continue;
}
w = bb;
i = __scan_keyword(w, be, this->__months_, this->__months_+24,
ct, err, false)
- this->__months_;
if (i < 24)
{
result.push_back('%');
if (i < 12)
result.push_back('B');
else
result.push_back('b');
if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
result.back() = 'm';
bb = w;
continue;
}
if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
{
w = bb;
i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
ct, err, false) - this->__am_pm_;
if (i < 2)
{
result.push_back('%');
result.push_back('p');
bb = w;
continue;
}
}
w = bb;
if (ct.is(ctype_base::digit, *bb))
{
switch(__get_up_to_n_digits(bb, be, err, ct, 4))
{
case 6:
result.push_back('%');
result.push_back('w');
break;
case 7:
result.push_back('%');
result.push_back('u');
break;
case 11:
result.push_back('%');
result.push_back('I');
break;
case 12:
result.push_back('%');
result.push_back('m');
break;
case 23:
result.push_back('%');
result.push_back('H');
break;
case 31:
result.push_back('%');
result.push_back('d');
break;
case 55:
result.push_back('%');
result.push_back('M');
break;
case 59:
result.push_back('%');
result.push_back('S');
break;
case 61:
result.push_back('%');
result.push_back('y');
break;
case 364:
result.push_back('%');
result.push_back('j');
break;
case 2061:
result.push_back('%');
result.push_back('Y');
break;
default:
for (; w != bb; ++w)
result.push_back(*w);
break;
}
continue;
}
if (*bb == '%')
{
result.push_back('%');
result.push_back('%');
++bb;
continue;
}
result.push_back(*bb);
++bb;
}
return result;
}
#if defined(__clang__)
#pragma clang diagnostic ignored "-Wmissing-braces"
#endif
template <>
wstring
__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
{
tm t = {0};
t.tm_sec = 59;
t.tm_min = 55;
t.tm_hour = 23;
t.tm_mday = 31;
t.tm_mon = 11;
t.tm_year = 161;
t.tm_wday = 6;
t.tm_yday = 364;
t.tm_isdst = -1;
char buf[100];
char f[3] = {0};
f[0] = '%';
f[1] = fmt;
strftime_l(buf, countof(buf), f, &t, __loc_);
wchar_t wbuf[100];
wchar_t* wbb = wbuf;
mbstate_t mb = {0};
const char* bb = buf;
size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
wchar_t* wbe = wbb + j;
wstring result;
while (wbb != wbe)
{
if (ct.is(ctype_base::space, *wbb))
{
result.push_back(L' ');
for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
;
continue;
}
wchar_t* w = wbb;
ios_base::iostate err = ios_base::goodbit;
ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
ct, err, false)
- this->__weeks_;
if (i < 14)
{
result.push_back(L'%');
if (i < 7)
result.push_back(L'A');
else
result.push_back(L'a');
wbb = w;
continue;
}
w = wbb;
i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
ct, err, false)
- this->__months_;
if (i < 24)
{
result.push_back(L'%');
if (i < 12)
result.push_back(L'B');
else
result.push_back(L'b');
if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
result.back() = L'm';
wbb = w;
continue;
}
if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
{
w = wbb;
i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
ct, err, false) - this->__am_pm_;
if (i < 2)
{
result.push_back(L'%');
result.push_back(L'p');
wbb = w;
continue;
}
}
w = wbb;
if (ct.is(ctype_base::digit, *wbb))
{
switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
{
case 6:
result.push_back(L'%');
result.push_back(L'w');
break;
case 7:
result.push_back(L'%');
result.push_back(L'u');
break;
case 11:
result.push_back(L'%');
result.push_back(L'I');
break;
case 12:
result.push_back(L'%');
result.push_back(L'm');
break;
case 23:
result.push_back(L'%');
result.push_back(L'H');
break;
case 31:
result.push_back(L'%');
result.push_back(L'd');
break;
case 55:
result.push_back(L'%');
result.push_back(L'M');
break;
case 59:
result.push_back(L'%');
result.push_back(L'S');
break;
case 61:
result.push_back(L'%');
result.push_back(L'y');
break;
case 364:
result.push_back(L'%');
result.push_back(L'j');
break;
case 2061:
result.push_back(L'%');
result.push_back(L'Y');
break;
default:
for (; w != wbb; ++w)
result.push_back(*w);
break;
}
continue;
}
if (ct.narrow(*wbb, 0) == '%')
{
result.push_back(L'%');
result.push_back(L'%');
++wbb;
continue;
}
result.push_back(*wbb);
++wbb;
}
return result;
}
template <>
void
__time_get_storage<char>::init(const ctype<char>& ct)
{
tm t = {0};
char buf[100];
// __weeks_
for (int i = 0; i < 7; ++i)
{
t.tm_wday = i;
strftime_l(buf, countof(buf), "%A", &t, __loc_);
__weeks_[i] = buf;
strftime_l(buf, countof(buf), "%a", &t, __loc_);
__weeks_[i+7] = buf;
}
// __months_
for (int i = 0; i < 12; ++i)
{
t.tm_mon = i;
strftime_l(buf, countof(buf), "%B", &t, __loc_);
__months_[i] = buf;
strftime_l(buf, countof(buf), "%b", &t, __loc_);
__months_[i+12] = buf;
}
// __am_pm_
t.tm_hour = 1;
strftime_l(buf, countof(buf), "%p", &t, __loc_);
__am_pm_[0] = buf;
t.tm_hour = 13;
strftime_l(buf, countof(buf), "%p", &t, __loc_);
__am_pm_[1] = buf;
__c_ = __analyze('c', ct);
__r_ = __analyze('r', ct);
__x_ = __analyze('x', ct);
__X_ = __analyze('X', ct);
}
template <>
void
__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
{
tm t = {0};
char buf[100];
wchar_t wbuf[100];
wchar_t* wbe;
mbstate_t mb = {0};
// __weeks_
for (int i = 0; i < 7; ++i)
{
t.tm_wday = i;
strftime_l(buf, countof(buf), "%A", &t, __loc_);
mb = mbstate_t();
const char* bb = buf;
size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
wbe = wbuf + j;
__weeks_[i].assign(wbuf, wbe);
strftime_l(buf, countof(buf), "%a", &t, __loc_);
mb = mbstate_t();
bb = buf;
j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
wbe = wbuf + j;
__weeks_[i+7].assign(wbuf, wbe);
}
// __months_
for (int i = 0; i < 12; ++i)
{
t.tm_mon = i;
strftime_l(buf, countof(buf), "%B", &t, __loc_);
mb = mbstate_t();
const char* bb = buf;
size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
wbe = wbuf + j;
__months_[i].assign(wbuf, wbe);
strftime_l(buf, countof(buf), "%b", &t, __loc_);
mb = mbstate_t();
bb = buf;
j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
wbe = wbuf + j;
__months_[i+12].assign(wbuf, wbe);
}
// __am_pm_
t.tm_hour = 1;
strftime_l(buf, countof(buf), "%p", &t, __loc_);
mb = mbstate_t();
const char* bb = buf;
size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
wbe = wbuf + j;
__am_pm_[0].assign(wbuf, wbe);
t.tm_hour = 13;
strftime_l(buf, countof(buf), "%p", &t, __loc_);
mb = mbstate_t();
bb = buf;
j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
wbe = wbuf + j;
__am_pm_[1].assign(wbuf, wbe);
__c_ = __analyze('c', ct);
__r_ = __analyze('r', ct);
__x_ = __analyze('x', ct);
__X_ = __analyze('X', ct);
}
template <class CharT>
struct _LIBCPP_HIDDEN __time_get_temp
: public ctype_byname<CharT>
{
explicit __time_get_temp(const char* nm)
: ctype_byname<CharT>(nm, 1) {}
explicit __time_get_temp(const string& nm)
: ctype_byname<CharT>(nm, 1) {}
};
template <>
__time_get_storage<char>::__time_get_storage(const char* __nm)
: __time_get(__nm)
{
const __time_get_temp<char> ct(__nm);
init(ct);
}
template <>
__time_get_storage<char>::__time_get_storage(const string& __nm)
: __time_get(__nm)
{
const __time_get_temp<char> ct(__nm);
init(ct);
}
template <>
__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
: __time_get(__nm)
{
const __time_get_temp<wchar_t> ct(__nm);
init(ct);
}
template <>
__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
: __time_get(__nm)
{
const __time_get_temp<wchar_t> ct(__nm);
init(ct);
}
template <>
time_base::dateorder
__time_get_storage<char>::__do_date_order() const
{
unsigned i;
for (i = 0; i < __x_.size(); ++i)
if (__x_[i] == '%')
break;
++i;
switch (__x_[i])
{
case 'y':
case 'Y':
for (++i; i < __x_.size(); ++i)
if (__x_[i] == '%')
break;
if (i == __x_.size())
break;
++i;
switch (__x_[i])
{
case 'm':
for (++i; i < __x_.size(); ++i)
if (__x_[i] == '%')
break;
if (i == __x_.size())
break;
++i;
if (__x_[i] == 'd')
return time_base::ymd;
break;
case 'd':
for (++i; i < __x_.size(); ++i)
if (__x_[i] == '%')
break;
if (i == __x_.size())
break;
++i;
if (__x_[i] == 'm')
return time_base::ydm;
break;
}
break;
case 'm':
for (++i; i < __x_.size(); ++i)
if (__x_[i] == '%')
break;
if (i == __x_.size())
break;
++i;
if (__x_[i] == 'd')
{
for (++i; i < __x_.size(); ++i)
if (__x_[i] == '%')
break;
if (i == __x_.size())
break;
++i;
if (__x_[i] == 'y' || __x_[i] == 'Y')
return time_base::mdy;
break;
}
break;
case 'd':
for (++i; i < __x_.size(); ++i)
if (__x_[i] == '%')
break;
if (i == __x_.size())
break;
++i;
if (__x_[i] == 'm')
{
for (++i; i < __x_.size(); ++i)
if (__x_[i] == '%')
break;
if (i == __x_.size())
break;
++i;
if (__x_[i] == 'y' || __x_[i] == 'Y')
return time_base::dmy;
break;
}
break;
}
return time_base::no_order;
}
template <>
time_base::dateorder
__time_get_storage<wchar_t>::__do_date_order() const
{
unsigned i;
for (i = 0; i < __x_.size(); ++i)
if (__x_[i] == L'%')
break;
++i;
switch (__x_[i])
{
case L'y':
case L'Y':
for (++i; i < __x_.size(); ++i)
if (__x_[i] == L'%')
break;
if (i == __x_.size())
break;
++i;
switch (__x_[i])
{
case L'm':
for (++i; i < __x_.size(); ++i)
if (__x_[i] == L'%')
break;
if (i == __x_.size())
break;
++i;
if (__x_[i] == L'd')
return time_base::ymd;
break;
case L'd':
for (++i; i < __x_.size(); ++i)
if (__x_[i] == L'%')
break;
if (i == __x_.size())
break;
++i;
if (__x_[i] == L'm')
return time_base::ydm;
break;
}
break;
case L'm':
for (++i; i < __x_.size(); ++i)
if (__x_[i] == L'%')
break;
if (i == __x_.size())
break;
++i;
if (__x_[i] == L'd')
{
for (++i; i < __x_.size(); ++i)
if (__x_[i] == L'%')
break;
if (i == __x_.size())
break;
++i;
if (__x_[i] == L'y' || __x_[i] == L'Y')
return time_base::mdy;
break;
}
break;
case L'd':
for (++i; i < __x_.size(); ++i)
if (__x_[i] == L'%')
break;
if (i == __x_.size())
break;
++i;
if (__x_[i] == L'm')
{
for (++i; i < __x_.size(); ++i)
if (__x_[i] == L'%')
break;
if (i == __x_.size())
break;
++i;
if (__x_[i] == L'y' || __x_[i] == L'Y')
return time_base::dmy;
break;
}
break;
}
return time_base::no_order;
}
// time_put
__time_put::__time_put(const char* nm)
: __loc_(newlocale(LC_ALL_MASK, nm, 0))
{
if (__loc_ == 0)
__throw_runtime_error("time_put_byname"
" failed to construct for " + string(nm));
}
__time_put::__time_put(const string& nm)
: __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
{
if (__loc_ == 0)
__throw_runtime_error("time_put_byname"
" failed to construct for " + nm);
}
__time_put::~__time_put()
{
if (__loc_ != _LIBCPP_GET_C_LOCALE)
freelocale(__loc_);
}
void
__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
char __fmt, char __mod) const
{
char fmt[] = {'%', __fmt, __mod, 0};
if (__mod != 0)
swap(fmt[1], fmt[2]);
size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
__ne = __nb + n;
}
void
__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
char __fmt, char __mod) const
{
char __nar[100];
char* __ne = __nar + 100;
__do_put(__nar, __ne, __tm, __fmt, __mod);
mbstate_t mb = {0};
const char* __nb = __nar;
size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
__we = __wb + j;
}
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<char>;
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<wchar_t>;
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<char>;
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<wchar_t>;
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<char>;
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<wchar_t>;
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<char>;
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<wchar_t>;
_LIBCPP_END_NAMESPACE_STD