From patchwork Fri Jul 31 16:06:45 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Marino X-Patchwork-Id: 502687 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 474E51402D1 for ; Sat, 1 Aug 2015 02:07:37 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=yHgrzyhX; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :subject:to:cc:message-id:date:mime-version:content-type; q=dns; s=default; b=as1N9SCj/CSpY9RC+EfagjtqpyOncjogq1YDmAa26NWYhRkT9Z OS+D76dLCX5HYYtIfVsdEEvCwU/am8BqbILzrZ/DVsv2TZvz0TxpdnHg94oI18Qi b+xY+e/pwLkh22DChlrkDMLKqB2ofR65k1nVTTjoP9w8n1WGDKXm798ec= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :subject:to:cc:message-id:date:mime-version:content-type; s= default; bh=CtMz2QnwHKAU6N5YjFwXoE0PRMc=; b=yHgrzyhXK8Qo1AAZpksR Ofm/1NumVMLvP4ZAcy8cpxj7omYp3DJoQCjZ+47z52cDjAA3SsSJu3kM8uLMksdh KFpuGbJ5FdzZ0hftLw6JSXcy6uiCFN/qAlc7MIiVk1C9kXZ1MEpbAow8RjjuGZUd xfSGva9RG1EVSDfcy1ss0MM= Received: (qmail 117504 invoked by alias); 31 Jul 2015 16:07:22 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 117491 invoked by uid 89); 31 Jul 2015 16:07:21 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=1.6 required=5.0 tests=BAYES_50, KAM_ASCII_DIVIDERS, SPF_PASS autolearn=no version=3.3.2 X-HELO: shepard.synsport.net Received: from mail.synsport.com (HELO shepard.synsport.net) (208.69.230.148) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-SHA encrypted) ESMTPS; Fri, 31 Jul 2015 16:07:01 +0000 Received: from [192.168.1.20] (85.Red-83-39-203.dynamicIP.rima-tde.net [83.39.203.85]) (using TLSv1 with cipher DHE-RSA-AES128-SHA (128/128 bits)) (No client certificate requested) by shepard.synsport.net (Postfix) with ESMTP id 0178C43CA1; Fri, 31 Jul 2015 11:06:48 -0500 (CDT) From: John Marino Subject: [patch][libstdc++] Provide nearly complete locale support for DragonFly X-Enigmail-Draft-Status: N1110 To: gcc-patches Cc: Jonathan Wakely Message-ID: <55BB9D15.8080202@marino.st> Date: Fri, 31 Jul 2015 18:06:45 +0200 User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:38.0) Gecko/20100101 Thunderbird/38.0.1 MIME-Version: 1.0 So far, DragonFly only handles the C/POSIX locale through the "generic" locale support files, similar to FreeBSD and Darwin. The following patchset enables nearly complete support for named locales. The except is for std:messages which requires gettext support in libc which is not present in any *BSD. For that category, I have left generic support in place at Jonathan's recommendation. The support was made by talking the GNU version and adapting it to work on DragonFly. Testing has shown these patches to be working. A "before" test results: https://gcc.gnu.org/ml/gcc-testresults/2015-07/msg01678.html PASS: 9883 FAIL: 89 XSUCC: 1 XFAIL: 66 UNSUP: 465 The most recent test: https://gcc.gnu.org/ml/gcc-testresults/2015-07/msg03024.html PASS: 10074 FAIL: 32 XFAIL: 68 UNSUP: 401 For full disclosure, a number of improvements were made to the OS in the area of locales, such as DragonFly being the first BSD to acquire full collation support. Most of the remaining failures are due to differences in locale definitions between linux and DragonFly (DragonFly now uses CLDR POSIX definitions, v2.0.1 currently) Attachments: 1. combined diff 2. diff between gnu and dragonfly version (FYI) 3. Suggested Changelog entry This work should be highly interesting for FreeBSD and perhaps darwin as well. FreeBSD may be able to switch to it directly without any required modifications, but of course that must be tested. There is no risk to approving this patchset because it affects only DragonFly. Please consider approving this for incorporating into trunk (also recall that my FSF copyright assignment is filed and in order.) Regards, John 2015-08-xx John Marino * acinclude.m4 (*-*-dragonfly*): Change 7 locale support files from generic to new DragonFly versions. * configure: Regenerate. * config/locale/dragonfly/c_locale.cc: Improve locale support. * config/locale/dragonfly/ctype_members.cc: likewise. * config/os/bsd/dragonfly/ctype_configure_char.cc: Likewise. * config/locale/dragonfly/c_locale.h: New. * config/locale/dragonfly/codecvt_members.cc: New. * config/locale/dragonfly/collate_members.cc: New. * config/locale/dragonfly/monetary_members.cc: New. * config/locale/dragonfly/numeric_members.cc: New. * config/locale/dragonfly/time_members.cc: New. * config/locale/dragonfly/time_members.h: New. Index: libstdc++-v3/acinclude.m4 =================================================================== --- libstdc++-v3/acinclude.m4 (revision 226444) +++ libstdc++-v3/acinclude.m4 (working copy) @@ -2087,17 +2087,17 @@ dragonfly) AC_MSG_RESULT(dragonfly) - CLOCALE_H=config/locale/generic/c_locale.h + CLOCALE_H=config/locale/dragonfly/c_locale.h CLOCALE_CC=config/locale/dragonfly/c_locale.cc - CCODECVT_CC=config/locale/generic/codecvt_members.cc - CCOLLATE_CC=config/locale/generic/collate_members.cc + CCODECVT_CC=config/locale/dragonfly/codecvt_members.cc + CCOLLATE_CC=config/locale/dragonfly/collate_members.cc CCTYPE_CC=config/locale/dragonfly/ctype_members.cc CMESSAGES_H=config/locale/generic/messages_members.h CMESSAGES_CC=config/locale/generic/messages_members.cc - CMONEY_CC=config/locale/generic/monetary_members.cc - CNUMERIC_CC=config/locale/generic/numeric_members.cc - CTIME_H=config/locale/generic/time_members.h - CTIME_CC=config/locale/generic/time_members.cc + CMONEY_CC=config/locale/dragonfly/monetary_members.cc + CNUMERIC_CC=config/locale/dragonfly/numeric_members.cc + CTIME_H=config/locale/dragonfly/time_members.h + CTIME_CC=config/locale/dragonfly/time_members.cc CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h ;; Index: libstdc++-v3/config/locale/dragonfly/c_locale.cc =================================================================== --- libstdc++-v3/config/locale/dragonfly/c_locale.cc (revision 226444) +++ libstdc++-v3/config/locale/dragonfly/c_locale.cc (working copy) @@ -1,4 +1,4 @@ -// Wrapper for underlying C-language localization -*- C++ -*- +// localization implementation details, DragonFly version -*- C++ -*- // Copyright (C) 2014-2015 Free Software Foundation, Inc. // @@ -27,19 +27,15 @@ // // Written by Benjamin Kosnik +// Modified for DragonFly by John Marino -#include // For errno -#include // For isinf, finite, finitef, fabs -#include // For strof, strtold -#include -#include +#include #include +#include #include +#include +#include -#ifdef _GLIBCXX_HAVE_IEEEFP_H -#include -#endif - namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -47,41 +43,11 @@ template<> void __convert_to_v(const char* __s, float& __v, ios_base::iostate& __err, - const __c_locale&) throw() + const __c_locale& __cloc) throw() { - // Assumes __s formatted for "C" locale. - char* __old = setlocale(LC_ALL, 0); - const size_t __len = strlen(__old) + 1; - char* __sav = new char[__len]; - memcpy(__sav, __old, __len); - setlocale(LC_ALL, "C"); char* __sanity; - bool __overflow = false; + __v = strtof_l(__s, &__sanity, (locale_t)__cloc); -#if !__FLT_HAS_INFINITY__ - errno = 0; -#endif - -#ifdef _GLIBCXX_HAVE_STRTOF - __v = strtof(__s, &__sanity); -#else - double __d = strtod(__s, &__sanity); - __v = static_cast(__d); -#ifdef _GLIBCXX_HAVE_FINITEF - if (!finitef (__v)) - __overflow = true; -#elif defined (_GLIBCXX_HAVE_FINITE) - if (!finite (static_cast (__v))) - __overflow = true; -#elif defined (_GLIBCXX_HAVE_ISINF) - if (isinf (static_cast (__v))) - __overflow = true; -#else - if (fabs(__d) > numeric_limits::max()) - __overflow = true; -#endif -#endif // _GLIBCXX_HAVE_STRTOF - // _GLIBCXX_RESOLVE_LIB_DEFECTS // 23. Num_get overflow result. if (__sanity == __s || *__sanity != '\0') @@ -89,45 +55,26 @@ __v = 0.0f; __err = ios_base::failbit; } - else if (__overflow -#if __FLT_HAS_INFINITY__ - || __v == numeric_limits::infinity() - || __v == -numeric_limits::infinity() -#else - || ((__v > 1.0f || __v < -1.0f) && errno == ERANGE) -#endif - ) + else if (__v == numeric_limits::infinity()) { - if (__v > 0.0f) - __v = numeric_limits::max(); - else - __v = -numeric_limits::max(); + __v = numeric_limits::max(); __err = ios_base::failbit; } - - setlocale(LC_ALL, __sav); - delete [] __sav; + else if (__v == -numeric_limits::infinity()) + { + __v = -numeric_limits::max(); + __err = ios_base::failbit; + } } template<> void __convert_to_v(const char* __s, double& __v, ios_base::iostate& __err, - const __c_locale&) throw() + const __c_locale& __cloc) throw() { - // Assumes __s formatted for "C" locale. - char* __old = setlocale(LC_ALL, 0); - const size_t __len = strlen(__old) + 1; - char* __sav = new char[__len]; - memcpy(__sav, __old, __len); - setlocale(LC_ALL, "C"); char* __sanity; + __v = strtod_l(__s, &__sanity, (locale_t)__cloc); -#if !__DBL_HAS_INFINITY__ - errno = 0; -#endif - - __v = strtod(__s, &__sanity); - // _GLIBCXX_RESOLVE_LIB_DEFECTS // 23. Num_get overflow result. if (__sanity == __s || *__sanity != '\0') @@ -135,132 +82,86 @@ __v = 0.0; __err = ios_base::failbit; } - else if ( -#if __DBL_HAS_INFINITY__ - __v == numeric_limits::infinity() - || __v == -numeric_limits::infinity()) -#else - (__v > 1.0 || __v < -1.0) && errno == ERANGE) -#endif + else if (__v == numeric_limits::infinity()) { - if (__v > 0.0) - __v = numeric_limits::max(); - else - __v = -numeric_limits::max(); + __v = numeric_limits::max(); __err = ios_base::failbit; } - - setlocale(LC_ALL, __sav); - delete [] __sav; + else if (__v == -numeric_limits::infinity()) + { + __v = -numeric_limits::max(); + __err = ios_base::failbit; + } } template<> void - __convert_to_v(const char* __s, long double& __v, - ios_base::iostate& __err, const __c_locale&) throw() + __convert_to_v(const char* __s, long double& __v, ios_base::iostate& __err, + const __c_locale& __cloc) throw() { - // Assumes __s formatted for "C" locale. - char* __old = setlocale(LC_ALL, 0); - const size_t __len = strlen(__old) + 1; - char* __sav = new char[__len]; - memcpy(__sav, __old, __len); - setlocale(LC_ALL, "C"); - -#if !__LDBL_HAS_INFINITY__ - errno = 0; -#endif - -#if defined(_GLIBCXX_HAVE_STRTOLD) && !defined(_GLIBCXX_HAVE_BROKEN_STRTOLD) char* __sanity; - __v = strtold(__s, &__sanity); + __v = strtold_l(__s, &__sanity, (locale_t)__cloc); // _GLIBCXX_RESOLVE_LIB_DEFECTS // 23. Num_get overflow result. if (__sanity == __s || *__sanity != '\0') -#else - typedef char_traits::int_type int_type; - int __p = sscanf(__s, "%Lf", &__v); - - if (!__p || static_cast(__p) == char_traits::eof()) -#endif { __v = 0.0l; __err = ios_base::failbit; } - else if ( -#if __LDBL_HAS_INFINITY__ - __v == numeric_limits::infinity() - || __v == -numeric_limits::infinity()) -#else - (__v > 1.0l || __v < -1.0l) && errno == ERANGE) -#endif + else if (__v == numeric_limits::infinity()) { - if (__v > 0.0l) - __v = numeric_limits::max(); - else - __v = -numeric_limits::max(); + __v = numeric_limits::max(); __err = ios_base::failbit; } - - setlocale(LC_ALL, __sav); - delete [] __sav; + else if (__v == -numeric_limits::infinity()) + { + __v = -numeric_limits::max(); + __err = ios_base::failbit; + } } - - /* DragonFly's implementation of setlocale won't accept something like - "de_DE". According to nls manpage, the expected format is: - language[_territory][.codeset][@modifier], but it seems that both - the _territory and .codeset components are required. - - As an attempt to correct for this, we'll tack on ".UTF-8" if - a period is not detected in the locale string. - - There are no locales with modifiers on DragonFly so if found, they - will just be stripped off silently. e.g "de_DE@euro" will be reduced - to "de_DE". The UTF-8 default would be added after that. - */ - void locale::facet::_S_create_c_locale(__c_locale& __cloc, const char* __s, - __c_locale) + __c_locale __old) { - const size_t size__s = (__s == NULL) ? 1 : strlen (__s); - const char UTF8[] = ".UTF-8"; - char localspec[size__s + 6 + 1]; - - if (__s == NULL) { - localspec[0] = '\0'; - } else { - strcpy (localspec, __s); - char * pch = strchr (localspec, '@'); - if (pch != NULL) - *pch = 0; - - if ( (strchr (__s, '.') == NULL) - && (strcmp (__s, "C") != 0) - && (strcmp (__s, "POSIX") != 0)) - strncat (localspec, UTF8, 6); - } - - const char * result = std::setlocale(LC_ALL, localspec); - - if ((strcmp(result, "C") != 0) && (strcmp (result, localspec) != 0)) - __throw_runtime_error(__N("locale::facet::_S_create_c_locale " - "name not valid")); - __cloc = 0; + __cloc = (__c_locale)newlocale(LC_ALL_MASK, __s, (locale_t)__old); + if (!__cloc) + { + // This named locale is not supported by the underlying OS. + __throw_runtime_error(__N("locale::facet::_S_create_c_locale " + "name not valid")); + } } void locale::facet::_S_destroy_c_locale(__c_locale& __cloc) - { __cloc = 0; } + { + if (__cloc && _S_get_c_locale() != __cloc) + freelocale((locale_t)__cloc); + } __c_locale - locale::facet::_S_clone_c_locale(__c_locale&) throw() - { return __c_locale(); } + locale::facet::_S_clone_c_locale(__c_locale& __cloc) throw() + { return (__c_locale)duplocale((locale_t)__cloc); } __c_locale - locale::facet::_S_lc_ctype_c_locale(__c_locale, const char*) - { return __c_locale(); } + locale::facet::_S_lc_ctype_c_locale(__c_locale __cloc, const char* __s) + { + __c_locale __dup = (__c_locale)duplocale((locale_t)__cloc); + if (__dup == __c_locale(0)) + __throw_runtime_error(__N("locale::facet::_S_lc_ctype_c_locale " + "duplocale error")); + __c_locale __changed = (__c_locale)newlocale(LC_CTYPE_MASK, __s, + (locale_t)__dup); + if (__changed == __c_locale(0)) + { + freelocale((locale_t)__dup); + __throw_runtime_error(__N("locale::facet::_S_lc_ctype_c_locale " + "newlocale error")); + } + return __changed; + } _GLIBCXX_END_NAMESPACE_VERSION } // namespace @@ -295,5 +196,5 @@ #ifdef _GLIBCXX_LONG_DOUBLE_COMPAT #define _GLIBCXX_LDBL_COMPAT(dbl, ldbl) \ extern "C" void ldbl (void) __attribute__ ((alias (#dbl))) -_GLIBCXX_LDBL_COMPAT(_ZSt14__convert_to_vIdEvPKcRT_RSt12_Ios_IostateRKPi, _ZSt14__convert_to_vIeEvPKcRT_RSt12_Ios_IostateRKPi); +_GLIBCXX_LDBL_COMPAT(_ZSt14__convert_to_vIdEvPKcRT_RSt12_Ios_IostateRKP15__locale_struct, _ZSt14__convert_to_vIeEvPKcRT_RSt12_Ios_IostateRKP15__locale_struct); #endif // _GLIBCXX_LONG_DOUBLE_COMPAT Index: libstdc++-v3/config/locale/dragonfly/c_locale.h =================================================================== --- libstdc++-v3/config/locale/dragonfly/c_locale.h (revision 0) +++ libstdc++-v3/config/locale/dragonfly/c_locale.h (working copy) @@ -0,0 +1,81 @@ +// localization implementation details, DragonFly version -*- C++ -*- + +// Copyright (C) 2001-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/c++locale.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{locale} + */ + +// +// ISO C++ 14882: 22.8 Standard locale categories. +// + +// Written by Benjamin Kosnik +// Modified for DragonFly by John Marino + +#ifndef _GLIBCXX_CXX_LOCALE_H +#define _GLIBCXX_CXX_LOCALE_H 1 + +#pragma GCC system_header + +#include + +#define _GLIBCXX_NUM_CATEGORIES 0 + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + typedef int* __c_locale; + + // Convert numeric value of type double and long double to string and + // return length of string. If vsnprintf is available use it, otherwise + // fall back to the unsafe vsprintf which, in general, can be dangerous + // and should be avoided. + inline int + __convert_from_v(const __c_locale& __cloc, char* __out, + const int __size __attribute__ ((__unused__)), + const char* __fmt, ...) + { + __c_locale __old = (__c_locale)uselocale((locale_t)__cloc); + + __builtin_va_list __args; + __builtin_va_start(__args, __fmt); + +#ifdef _GLIBCXX_USE_C99 + const int __ret = __builtin_vsnprintf(__out, __size, __fmt, __args); +#else + const int __ret = __builtin_vsprintf(__out, __fmt, __args); +#endif + + __builtin_va_end(__args); + + uselocale((locale_t)__old); + return __ret; + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif Index: libstdc++-v3/config/locale/dragonfly/codecvt_members.cc =================================================================== --- libstdc++-v3/config/locale/dragonfly/codecvt_members.cc (revision 0) +++ libstdc++-v3/config/locale/dragonfly/codecvt_members.cc (working copy) @@ -0,0 +1,288 @@ +// std::codecvt implementation details, DragonFly version -*- C++ -*- + +// Copyright (C) 2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +// +// ISO C++ 14882: 22.2.1.5 - Template class codecvt +// + +// Written by Benjamin Kosnik +// Modified for DragonFly by John Marino + +#include +#include +#include // For MB_CUR_MAX +#include // For MB_LEN_MAX + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Specializations. +#ifdef _GLIBCXX_USE_WCHAR_T + codecvt_base::result + codecvt:: + do_out(state_type& __state, const intern_type* __from, + const intern_type* __from_end, const intern_type*& __from_next, + extern_type* __to, extern_type* __to_end, + extern_type*& __to_next) const + { + result __ret = ok; + state_type __tmp_state(__state); + + __c_locale __old = (__c_locale)uselocale((locale_t)_M_c_locale_codecvt); + + // wcsnrtombs is *very* fast but stops if encounters NUL characters: + // in case we fall back to wcrtomb and then continue, in a loop. + // NB: wcsnrtombs is a GNU extension + for (__from_next = __from, __to_next = __to; + __from_next < __from_end && __to_next < __to_end + && __ret == ok;) + { + const intern_type* __from_chunk_end = wmemchr(__from_next, L'\0', + __from_end - __from_next); + if (!__from_chunk_end) + __from_chunk_end = __from_end; + + __from = __from_next; + const size_t __conv = wcsnrtombs(__to_next, &__from_next, + __from_chunk_end - __from_next, + __to_end - __to_next, &__state); + if (__conv == static_cast(-1)) + { + // In case of error, in order to stop at the exact place we + // have to start again from the beginning with a series of + // wcrtomb. + for (; __from < __from_next; ++__from) + __to_next += wcrtomb(__to_next, *__from, &__tmp_state); + __state = __tmp_state; + __ret = error; + } + else if (__from_next && __from_next < __from_chunk_end) + { + __to_next += __conv; + __ret = partial; + } + else + { + __from_next = __from_chunk_end; + __to_next += __conv; + } + + if (__from_next < __from_end && __ret == ok) + { + extern_type __buf[MB_LEN_MAX]; + __tmp_state = __state; + const size_t __conv2 = wcrtomb(__buf, *__from_next, &__tmp_state); + if (__conv2 > static_cast(__to_end - __to_next)) + __ret = partial; + else + { + memcpy(__to_next, __buf, __conv2); + __state = __tmp_state; + __to_next += __conv2; + ++__from_next; + } + } + } + + uselocale((locale_t)__old); + + return __ret; + } + + codecvt_base::result + codecvt:: + do_in(state_type& __state, const extern_type* __from, + const extern_type* __from_end, const extern_type*& __from_next, + intern_type* __to, intern_type* __to_end, + intern_type*& __to_next) const + { + result __ret = ok; + state_type __tmp_state(__state); + + __c_locale __old = (__c_locale)uselocale((locale_t)_M_c_locale_codecvt); + + // mbsnrtowcs is *very* fast but stops if encounters NUL characters: + // in case we store a L'\0' and then continue, in a loop. + // NB: mbsnrtowcs is a GNU extension + for (__from_next = __from, __to_next = __to; + __from_next < __from_end && __to_next < __to_end + && __ret == ok;) + { + const extern_type* __from_chunk_end; + __from_chunk_end = static_cast(memchr(__from_next, '\0', + __from_end + - __from_next)); + if (!__from_chunk_end) + __from_chunk_end = __from_end; + + __from = __from_next; + size_t __conv = mbsnrtowcs(__to_next, &__from_next, + __from_chunk_end - __from_next, + __to_end - __to_next, &__state); + if (__conv == static_cast(-1)) + { + // In case of error, in order to stop at the exact place we + // have to start again from the beginning with a series of + // mbrtowc. + for (;; ++__to_next, __from += __conv) + { + __conv = mbrtowc(__to_next, __from, __from_end - __from, + &__tmp_state); + if (__conv == static_cast(-1) + || __conv == static_cast(-2)) + break; + } + __from_next = __from; + __state = __tmp_state; + __ret = error; + } + else if (__from_next && __from_next < __from_chunk_end) + { + // It is unclear what to return in this case (see DR 382). + __to_next += __conv; + __ret = partial; + } + else + { + __from_next = __from_chunk_end; + __to_next += __conv; + } + + if (__from_next < __from_end && __ret == ok) + { + if (__to_next < __to_end) + { + // XXX Probably wrong for stateful encodings + __tmp_state = __state; + ++__from_next; + *__to_next++ = L'\0'; + } + else + __ret = partial; + } + } + + uselocale((locale_t)__old); + + return __ret; + } + + int + codecvt:: + do_encoding() const throw() + { + // XXX This implementation assumes that the encoding is + // stateless and is either single-byte or variable-width. + int __ret = 0; + __c_locale __old = (__c_locale)uselocale((locale_t)_M_c_locale_codecvt); + if (MB_CUR_MAX == 1) + __ret = 1; + uselocale((locale_t)__old); + return __ret; + } + + int + codecvt:: + do_max_length() const throw() + { + __c_locale __old = (__c_locale)uselocale((locale_t)_M_c_locale_codecvt); + // XXX Probably wrong for stateful encodings. + int __ret = MB_CUR_MAX; + uselocale((locale_t)__old); + return __ret; + } + + int + codecvt:: + do_length(state_type& __state, const extern_type* __from, + const extern_type* __end, size_t __max) const + { + int __ret = 0; + state_type __tmp_state(__state); + + __c_locale __old = (__c_locale)uselocale((locale_t)_M_c_locale_codecvt); + + // mbsnrtowcs is *very* fast but stops if encounters NUL characters: + // in case we advance past it and then continue, in a loop. + // NB: mbsnrtowcs is a GNU extension + + // A dummy internal buffer is needed in order for mbsnrtocws to consider + // its fourth parameter (it wouldn't with NULL as first parameter). + wchar_t* __to = static_cast(__builtin_alloca(sizeof(wchar_t) + * __max)); + while (__from < __end && __max) + { + const extern_type* __from_chunk_end; + __from_chunk_end = static_cast(memchr(__from, '\0', + __end + - __from)); + if (!__from_chunk_end) + __from_chunk_end = __end; + + const extern_type* __tmp_from = __from; + size_t __conv = mbsnrtowcs(__to, &__from, + __from_chunk_end - __from, + __max, &__state); + if (__conv == static_cast(-1)) + { + // In case of error, in order to stop at the exact place we + // have to start again from the beginning with a series of + // mbrtowc. + for (__from = __tmp_from;; __from += __conv) + { + __conv = mbrtowc(0, __from, __end - __from, + &__tmp_state); + if (__conv == static_cast(-1) + || __conv == static_cast(-2)) + break; + } + __state = __tmp_state; + __ret += __from - __tmp_from; + break; + } + if (!__from) + __from = __from_chunk_end; + + __ret += __from - __tmp_from; + __max -= __conv; + + if (__from < __end && __max) + { + // XXX Probably wrong for stateful encodings + __tmp_state = __state; + ++__from; + ++__ret; + --__max; + } + } + + uselocale((locale_t)__old); + + return __ret; + } +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace Index: libstdc++-v3/config/locale/dragonfly/collate_members.cc =================================================================== --- libstdc++-v3/config/locale/dragonfly/collate_members.cc (revision 0) +++ libstdc++-v3/config/locale/dragonfly/collate_members.cc (working copy) @@ -0,0 +1,74 @@ +// std::collate implementation details, DragonFly version -*- C++ -*- + +// Copyright (C) 2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +// +// ISO C++ 14882: 22.2.4.1.2 collate virtual functions +// + +// Written by Benjamin Kosnik +// Modified for DragonFly by John Marino + +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // These are basically extensions to char_traits, and perhaps should + // be put there instead of here. + template<> + int + collate::_M_compare(const char* __one, + const char* __two) const throw() + { + int __cmp = strcoll_l(__one, __two, (locale_t)_M_c_locale_collate); + return (__cmp >> (8 * sizeof (int) - 2)) | (__cmp != 0); + } + + template<> + size_t + collate::_M_transform(char* __to, const char* __from, + size_t __n) const throw() + { return strxfrm_l(__to, __from, __n, (locale_t)_M_c_locale_collate); } + +#ifdef _GLIBCXX_USE_WCHAR_T + template<> + int + collate::_M_compare(const wchar_t* __one, + const wchar_t* __two) const throw() + { + int __cmp = wcscoll_l(__one, __two, (locale_t)_M_c_locale_collate); + return (__cmp >> (8 * sizeof (int) - 2)) | (__cmp != 0); + } + + template<> + size_t + collate::_M_transform(wchar_t* __to, const wchar_t* __from, + size_t __n) const throw() + { return wcsxfrm_l(__to, __from, __n, (locale_t)_M_c_locale_collate); } +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace Index: libstdc++-v3/config/locale/dragonfly/ctype_members.cc =================================================================== --- libstdc++-v3/config/locale/dragonfly/ctype_members.cc (revision 226444) +++ libstdc++-v3/config/locale/dragonfly/ctype_members.cc (working copy) @@ -1,4 +1,4 @@ -// std::ctype implementation details, GNU version -*- C++ -*- +// std::ctype implementation details, DragonFly version -*- C++ -*- // Copyright (C) 2014-2015 Free Software Foundation, Inc. // @@ -27,18 +27,22 @@ // // Written by Benjamin Kosnik +// Modified for DragonFly by John Marino #include -#include -#include #include #include +#ifndef _ISbit +#define _ISbit(bit) ((bit) < 8 ? ((1 << (bit)) << 8) : ((1 << (bit)) >> 8)) +#endif + namespace std _GLIBCXX_VISIBILITY(default) { +_GLIBCXX_BEGIN_NAMESPACE_VERSION + // NB: The other ctype specializations are in src/locale.cc and // various /config/os/* files. - ctype_byname::ctype_byname(const char* __s, size_t __refs) : ctype(0, false, __refs) { @@ -54,17 +58,56 @@ #ifdef _GLIBCXX_USE_WCHAR_T ctype::__wmask_type - ctype::_M_convert_to_wmask( - const mask __attribute__((__unused__)) __m) const throw() + ctype::_M_convert_to_wmask(const mask __m) const throw() { - // DragonFly uses the same codes for 'char' as 'wchar_t', so this routine - // never gets called. - return __wmask_type(); - }; + __wmask_type __ret; + switch (__m) + { + case space: + __ret = wctype_l("space", (locale_t)_M_c_locale_ctype); + break; + case print: + __ret = wctype_l("print", (locale_t)_M_c_locale_ctype); + break; + case cntrl: + __ret = wctype_l("cntrl", (locale_t)_M_c_locale_ctype); + break; + case upper: + __ret = wctype_l("upper", (locale_t)_M_c_locale_ctype); + break; + case lower: + __ret = wctype_l("lower", (locale_t)_M_c_locale_ctype); + break; + case alpha: + __ret = wctype_l("alpha", (locale_t)_M_c_locale_ctype); + break; + case digit: + __ret = wctype_l("digit", (locale_t)_M_c_locale_ctype); + break; + case punct: + __ret = wctype_l("punct", (locale_t)_M_c_locale_ctype); + break; + case xdigit: + __ret = wctype_l("xdigit", (locale_t)_M_c_locale_ctype); + break; + case alnum: + __ret = wctype_l("alnum", (locale_t)_M_c_locale_ctype); + break; + case graph: + __ret = wctype_l("graph", (locale_t)_M_c_locale_ctype); + break; + case blank: + __ret = wctype_l("blank", (locale_t)_M_c_locale_ctype); + break; + default: + __ret = __wmask_type(); + } + return __ret; + } wchar_t ctype::do_toupper(wchar_t __c) const - { return towupper(__c); } + { return towupper_l(__c, (locale_t)_M_c_locale_ctype); } const wchar_t* ctype::do_toupper(wchar_t* __lo, const wchar_t* __hi) const @@ -71,7 +114,7 @@ { while (__lo < __hi) { - *__lo = towupper(*__lo); + *__lo = towupper_l(*__lo, (locale_t)_M_c_locale_ctype); ++__lo; } return __hi; @@ -79,7 +122,7 @@ wchar_t ctype::do_tolower(wchar_t __c) const - { return towlower(__c); } + { return towlower_l(__c, (locale_t)_M_c_locale_ctype); } const wchar_t* ctype::do_tolower(wchar_t* __lo, const wchar_t* __hi) const @@ -86,7 +129,7 @@ { while (__lo < __hi) { - *__lo = towlower(*__lo); + *__lo = towlower_l(*__lo, (locale_t)_M_c_locale_ctype); ++__lo; } return __hi; @@ -113,10 +156,12 @@ char ctype:: do_narrow(wchar_t __wc, char __dfault) const - { + { if (__wc >= 0 && __wc < 128 && _M_narrow_ok) return _M_narrow[__wc]; + __c_locale __old = (__c_locale)uselocale((locale_t)_M_c_locale_ctype); const int __c = wctob(__wc); + uselocale((locale_t)__old); return (__c == EOF ? __dfault : static_cast(__c)); } @@ -125,6 +170,7 @@ do_narrow(const wchar_t* __lo, const wchar_t* __hi, char __dfault, char* __dest) const { + __c_locale __old = (__c_locale)uselocale((locale_t)_M_c_locale_ctype); if (_M_narrow_ok) while (__lo < __hi) { @@ -146,6 +192,7 @@ ++__lo; ++__dest; } + uselocale((locale_t)__old); return __hi; } @@ -152,6 +199,7 @@ void ctype::_M_initialize_ctype() throw() { + __c_locale __old = (__c_locale)uselocale((locale_t)_M_c_locale_ctype); wint_t __i; for (__i = 0; __i < 128; ++__i) { @@ -165,9 +213,18 @@ _M_narrow_ok = true; else _M_narrow_ok = false; - for (size_t __i = 0; - __i < sizeof(_M_widen) / sizeof(wint_t); ++__i) - _M_widen[__i] = btowc(__i); + for (size_t __j = 0; + __j < sizeof(_M_widen) / sizeof(wint_t); ++__j) + _M_widen[__j] = btowc(__j); + + for (size_t __k = 0; __k <= 11; ++__k) + { + _M_bit[__k] = static_cast(_ISbit(__k)); + _M_wmask[__k] = _M_convert_to_wmask(_M_bit[__k]); + } + uselocale((locale_t)__old); } #endif // _GLIBCXX_USE_WCHAR_T -} + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace Index: libstdc++-v3/config/locale/dragonfly/monetary_members.cc =================================================================== --- libstdc++-v3/config/locale/dragonfly/monetary_members.cc (revision 0) +++ libstdc++-v3/config/locale/dragonfly/monetary_members.cc (working copy) @@ -0,0 +1,903 @@ +// std::moneypunct implementation details, DragonFly version -*- C++ -*- + +// Copyright (C) 2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +// +// ISO C++ 14882: 22.2.6.3.2 moneypunct virtual functions +// + +// Written by Benjamin Kosnik +// Modified for DragonFly by John Marino + +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +// This file might be compiled twice, but we only want to define the members +// of money_base once. +#if ! _GLIBCXX_USE_CXX11_ABI + + // Construct and return valid pattern consisting of some combination of: + // space none symbol sign value + money_base::pattern + money_base::_S_construct_pattern(char __precedes, char __space, + char __posn) throw() + { + pattern __ret; + + // This insanely complicated routine attempts to construct a valid + // pattern for use with moneypunct. A couple of invariants: + + // if (__precedes) symbol -> value + // else value -> symbol + + // if (__space) space + // else none + + // none == never first + // space never first or last + + // Any elegant implementations of this are welcome. + switch (__posn) + { + case 0: + case 1: + // 1 The sign precedes the value and symbol. + __ret.field[0] = sign; + if (__space) + { + // Pattern starts with sign. + if (__precedes) + { + __ret.field[1] = symbol; + __ret.field[3] = value; + } + else + { + __ret.field[1] = value; + __ret.field[3] = symbol; + } + __ret.field[2] = space; + } + else + { + // Pattern starts with sign and ends with none. + if (__precedes) + { + __ret.field[1] = symbol; + __ret.field[2] = value; + } + else + { + __ret.field[1] = value; + __ret.field[2] = symbol; + } + __ret.field[3] = none; + } + break; + case 2: + // 2 The sign follows the value and symbol. + if (__space) + { + // Pattern either ends with sign. + if (__precedes) + { + __ret.field[0] = symbol; + __ret.field[2] = value; + } + else + { + __ret.field[0] = value; + __ret.field[2] = symbol; + } + __ret.field[1] = space; + __ret.field[3] = sign; + } + else + { + // Pattern ends with sign then none. + if (__precedes) + { + __ret.field[0] = symbol; + __ret.field[1] = value; + } + else + { + __ret.field[0] = value; + __ret.field[1] = symbol; + } + __ret.field[2] = sign; + __ret.field[3] = none; + } + break; + case 3: + // 3 The sign immediately precedes the symbol. + if (__precedes) + { + __ret.field[0] = sign; + __ret.field[1] = symbol; + if (__space) + { + __ret.field[2] = space; + __ret.field[3] = value; + } + else + { + __ret.field[2] = value; + __ret.field[3] = none; + } + } + else + { + __ret.field[0] = value; + if (__space) + { + __ret.field[1] = space; + __ret.field[2] = sign; + __ret.field[3] = symbol; + } + else + { + __ret.field[1] = sign; + __ret.field[2] = symbol; + __ret.field[3] = none; + } + } + break; + case 4: + // 4 The sign immediately follows the symbol. + if (__precedes) + { + __ret.field[0] = symbol; + __ret.field[1] = sign; + if (__space) + { + __ret.field[2] = space; + __ret.field[3] = value; + } + else + { + __ret.field[2] = value; + __ret.field[3] = none; + } + } + else + { + __ret.field[0] = value; + if (__space) + { + __ret.field[1] = space; + __ret.field[2] = symbol; + __ret.field[3] = sign; + } + else + { + __ret.field[1] = symbol; + __ret.field[2] = sign; + __ret.field[3] = none; + } + } + break; + default: + __ret = pattern(); + } + return __ret; + } +#endif + + template<> + void + moneypunct::_M_initialize_moneypunct(__c_locale __cloc, + const char*) + { + if (!_M_data) + _M_data = new __moneypunct_cache; + + if (!__cloc) + { + // "C" locale + _M_data->_M_decimal_point = '.'; + _M_data->_M_thousands_sep = ','; + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_curr_symbol = ""; + _M_data->_M_curr_symbol_size = 0; + _M_data->_M_positive_sign = ""; + _M_data->_M_positive_sign_size = 0; + _M_data->_M_negative_sign = ""; + _M_data->_M_negative_sign_size = 0; + _M_data->_M_frac_digits = 0; + _M_data->_M_pos_format = money_base::_S_default_pattern; + _M_data->_M_neg_format = money_base::_S_default_pattern; + + for (size_t __i = 0; __i < money_base::_S_end; ++__i) + _M_data->_M_atoms[__i] = money_base::_S_atoms[__i]; + } + else + { + // Named locale. + lconv* lc = localeconv_l((locale_t) __cloc); + + // Check for NULL, which implies no fractional digits. + if (lc->mon_decimal_point == NULL || + lc->mon_decimal_point[0] == '\0') + { + // Like in "C" locale. + _M_data->_M_frac_digits = 0; + _M_data->_M_decimal_point = '.'; + } + else + { + _M_data->_M_decimal_point = lc->mon_decimal_point[0]; + _M_data->_M_frac_digits = lc->int_frac_digits; + } + + const char* __cgroup = lc->mon_grouping; + const char* __cpossign = lc->positive_sign; + const char* __cnegsign = lc->negative_sign; + // _Intl == true + const char* __ccurr = lc->int_curr_symbol; + + char* __group = 0; + char* __ps = 0; + char* __ns = 0; + const char __nposn = lc->int_n_sign_posn; + __try + { + size_t __len; + + // Check for NULL, which implies no grouping. + if (lc->mon_thousands_sep == NULL || + lc->mon_thousands_sep[0] == '\0') + { + // Like in "C" locale. + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_thousands_sep = ','; + } + else + { + _M_data->_M_thousands_sep = lc->mon_thousands_sep[0]; + + __len = strlen(__cgroup); + if (__len) + { + __group = new char[__len + 1]; + memcpy(__group, __cgroup, __len + 1); + _M_data->_M_grouping = __group; + } + else + { + _M_data->_M_grouping = ""; + _M_data->_M_use_grouping = false; + } + _M_data->_M_grouping_size = __len; + } + + __len = strlen(__cpossign); + if (__len) + { + __ps = new char[__len + 1]; + memcpy(__ps, __cpossign, __len + 1); + _M_data->_M_positive_sign = __ps; + } + else + _M_data->_M_positive_sign = ""; + _M_data->_M_positive_sign_size = __len; + + if (!__nposn) + { + _M_data->_M_negative_sign = "()"; + _M_data->_M_negative_sign_size = 2; + } + else + { + __len = strlen(__cnegsign); + if (__len) + { + __ns = new char[__len + 1]; + memcpy(__ns, __cnegsign, __len + 1); + _M_data->_M_negative_sign = __ns; + } + else + _M_data->_M_negative_sign = ""; + _M_data->_M_negative_sign_size = __len; + } + + __len = strlen(__ccurr); + if (__len) + { + char* __curr = new char[__len + 1]; + memcpy(__curr, __ccurr, __len + 1); + _M_data->_M_curr_symbol = __curr; + } + else + _M_data->_M_curr_symbol = ""; + _M_data->_M_curr_symbol_size = __len; + } + __catch(...) + { + delete _M_data; + _M_data = 0; + delete [] __group; + delete [] __ps; + delete [] __ns; + __throw_exception_again; + } + + char __pprecedes = lc->int_p_cs_precedes; + char __pspace = lc->int_p_sep_by_space; + char __pposn = lc->int_p_sign_posn; + _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, + __pposn); + char __nprecedes = lc->int_n_cs_precedes; + char __nspace = lc->int_n_sep_by_space; + _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, + __nposn); + } + } + + template<> + void + moneypunct::_M_initialize_moneypunct(__c_locale __cloc, + const char*) + { + if (!_M_data) + _M_data = new __moneypunct_cache; + + if (!__cloc) + { + // "C" locale + _M_data->_M_decimal_point = '.'; + _M_data->_M_thousands_sep = ','; + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_curr_symbol = ""; + _M_data->_M_curr_symbol_size = 0; + _M_data->_M_positive_sign = ""; + _M_data->_M_positive_sign_size = 0; + _M_data->_M_negative_sign = ""; + _M_data->_M_negative_sign_size = 0; + _M_data->_M_frac_digits = 0; + _M_data->_M_pos_format = money_base::_S_default_pattern; + _M_data->_M_neg_format = money_base::_S_default_pattern; + + for (size_t __i = 0; __i < money_base::_S_end; ++__i) + _M_data->_M_atoms[__i] = money_base::_S_atoms[__i]; + } + else + { + // Named locale. + lconv* lc = localeconv_l((locale_t) __cloc); + + // Check for NULL, which implies no fractional digits. + if (lc->mon_decimal_point == NULL || + lc->mon_decimal_point[0] == '\0') + { + // Like in "C" locale. + _M_data->_M_frac_digits = 0; + _M_data->_M_decimal_point = '.'; + } + else + { + _M_data->_M_decimal_point = lc->mon_decimal_point[0]; + _M_data->_M_frac_digits = lc->frac_digits; + } + + const char* __cgroup = lc->mon_grouping; + const char* __cpossign = lc->positive_sign; + const char* __cnegsign = lc->negative_sign; + // _Intl == false + const char* __ccurr = lc->currency_symbol; + + char* __group = 0; + char* __ps = 0; + char* __ns = 0; + const char __nposn = lc->n_sign_posn; + __try + { + size_t __len; + + // Check for NULL, which implies no grouping. + if (lc->mon_thousands_sep == NULL || + lc->mon_thousands_sep[0] == '\0') + { + // Like in "C" locale. + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_thousands_sep = ','; + } + else + { + _M_data->_M_thousands_sep = lc->mon_thousands_sep[0]; + + __len = strlen(__cgroup); + if (__len) + { + __group = new char[__len + 1]; + memcpy(__group, __cgroup, __len + 1); + _M_data->_M_grouping = __group; + } + else + { + _M_data->_M_grouping = ""; + _M_data->_M_use_grouping = false; + } + _M_data->_M_grouping_size = __len; + } + + __len = strlen(__cpossign); + if (__len) + { + __ps = new char[__len + 1]; + memcpy(__ps, __cpossign, __len + 1); + _M_data->_M_positive_sign = __ps; + } + else + _M_data->_M_positive_sign = ""; + _M_data->_M_positive_sign_size = __len; + + if (!__nposn) + { + _M_data->_M_negative_sign = "()"; + _M_data->_M_negative_sign_size = 2; + } + else + { + __len = strlen(__cnegsign); + if (__len) + { + __ns = new char[__len + 1]; + memcpy(__ns, __cnegsign, __len + 1); + _M_data->_M_negative_sign = __ns; + } + else + _M_data->_M_negative_sign = ""; + _M_data->_M_negative_sign_size = __len; + } + + __len = strlen(__ccurr); + if (__len) + { + char* __curr = new char[__len + 1]; + memcpy(__curr, __ccurr, __len + 1); + _M_data->_M_curr_symbol = __curr; + } + else + _M_data->_M_curr_symbol = ""; + _M_data->_M_curr_symbol_size = __len; + } + __catch(...) + { + delete _M_data; + _M_data = 0; + delete [] __group; + delete [] __ps; + delete [] __ns; + __throw_exception_again; + } + + char __pprecedes = lc->p_cs_precedes; + char __pspace = lc->p_sep_by_space; + char __pposn = lc->p_sign_posn; + _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, + __pposn); + char __nprecedes = lc->n_cs_precedes; + char __nspace = lc->n_sep_by_space; + _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, + __nposn); + } + } + + template<> + moneypunct::~moneypunct() + { + if (_M_data->_M_grouping_size) + delete [] _M_data->_M_grouping; + if (_M_data->_M_positive_sign_size) + delete [] _M_data->_M_positive_sign; + if (_M_data->_M_negative_sign_size + && strcmp(_M_data->_M_negative_sign, "()") != 0) + delete [] _M_data->_M_negative_sign; + if (_M_data->_M_curr_symbol_size) + delete [] _M_data->_M_curr_symbol; + delete _M_data; + } + + template<> + moneypunct::~moneypunct() + { + if (_M_data->_M_grouping_size) + delete [] _M_data->_M_grouping; + if (_M_data->_M_positive_sign_size) + delete [] _M_data->_M_positive_sign; + if (_M_data->_M_negative_sign_size + && strcmp(_M_data->_M_negative_sign, "()") != 0) + delete [] _M_data->_M_negative_sign; + if (_M_data->_M_curr_symbol_size) + delete [] _M_data->_M_curr_symbol; + delete _M_data; + } + +#ifdef _GLIBCXX_USE_WCHAR_T + template<> + void + moneypunct::_M_initialize_moneypunct(__c_locale __cloc, + const char*) + { + if (!_M_data) + _M_data = new __moneypunct_cache; + + if (!__cloc) + { + // "C" locale + _M_data->_M_decimal_point = L'.'; + _M_data->_M_thousands_sep = L','; + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_curr_symbol = L""; + _M_data->_M_curr_symbol_size = 0; + _M_data->_M_positive_sign = L""; + _M_data->_M_positive_sign_size = 0; + _M_data->_M_negative_sign = L""; + _M_data->_M_negative_sign_size = 0; + _M_data->_M_frac_digits = 0; + _M_data->_M_pos_format = money_base::_S_default_pattern; + _M_data->_M_neg_format = money_base::_S_default_pattern; + + // Use ctype::widen code without the facet... + for (size_t __i = 0; __i < money_base::_S_end; ++__i) + _M_data->_M_atoms[__i] = + static_cast(money_base::_S_atoms[__i]); + } + else + { + __c_locale __old = (__c_locale)uselocale((locale_t)__cloc); + // Named locale. + lconv* lc = localeconv_l((locale_t) __cloc); + + // Check for NULL, which implies no fractional digits. + if (lc->mon_decimal_point == NULL || + lc->mon_decimal_point[0] == '\0') + { + // Like in "C" locale. + _M_data->_M_frac_digits = 0; + _M_data->_M_decimal_point = L'.'; + } + else + { + _M_data->_M_frac_digits = lc->int_frac_digits; + _M_data->_M_decimal_point = (wchar_t)lc->mon_decimal_point[0]; + } + + const char* __cgroup = lc->mon_grouping; + const char* __cpossign = lc->positive_sign; + const char* __cnegsign = lc->negative_sign; + const char* __ccurr = lc->int_curr_symbol; + + char* __group = 0; + wchar_t* __wcs_ps = 0; + wchar_t* __wcs_ns = 0; + const char __nposn = lc->int_n_sign_posn; + __try + { + size_t __len; + + // Check for NULL, which implies no grouping. + if (lc->mon_thousands_sep == NULL || + lc->mon_thousands_sep[0] == '\0') + { + // Like in "C" locale. + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_thousands_sep = L','; + } + else + { + _M_data->_M_thousands_sep = + (wchar_t)lc->mon_thousands_sep[0]; + __len = strlen(__cgroup); + if (__len) + { + __group = new char[__len + 1]; + memcpy(__group, __cgroup, __len + 1); + _M_data->_M_grouping = __group; + } + else + { + _M_data->_M_grouping = ""; + _M_data->_M_use_grouping = false; + } + _M_data->_M_grouping_size = __len; + } + + mbstate_t __state; + __len = strlen(__cpossign); + if (__len) + { + memset(&__state, 0, sizeof(mbstate_t)); + __wcs_ps = new wchar_t[__len + 1]; + mbsrtowcs(__wcs_ps, &__cpossign, __len + 1, &__state); + _M_data->_M_positive_sign = __wcs_ps; + } + else + _M_data->_M_positive_sign = L""; + _M_data->_M_positive_sign_size = + wcslen(_M_data->_M_positive_sign); + + __len = strlen(__cnegsign); + if (!__nposn) + _M_data->_M_negative_sign = L"()"; + else if (__len) + { + memset(&__state, 0, sizeof(mbstate_t)); + __wcs_ns = new wchar_t[__len + 1]; + mbsrtowcs(__wcs_ns, &__cnegsign, __len + 1, &__state); + _M_data->_M_negative_sign = __wcs_ns; + } + else + _M_data->_M_negative_sign = L""; + _M_data->_M_negative_sign_size = + wcslen(_M_data->_M_negative_sign); + + // _Intl == true. + __len = strlen(__ccurr); + if (__len) + { + memset(&__state, 0, sizeof(mbstate_t)); + wchar_t* __wcs = new wchar_t[__len + 1]; + mbsrtowcs(__wcs, &__ccurr, __len + 1, &__state); + _M_data->_M_curr_symbol = __wcs; + } + else + _M_data->_M_curr_symbol = L""; + _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol); + } + __catch(...) + { + delete _M_data; + _M_data = 0; + delete [] __group; + delete [] __wcs_ps; + delete [] __wcs_ns; + uselocale((locale_t)__old); + __throw_exception_again; + } + + char __pprecedes = lc->int_p_cs_precedes; + char __pspace = lc->int_p_sep_by_space; + char __pposn = lc->int_p_sign_posn; + _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, + __pposn); + char __nprecedes = lc->int_n_cs_precedes; + char __nspace = lc->int_n_sep_by_space; + _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, + __nposn); + + uselocale((locale_t)__old); + } + } + + template<> + void + moneypunct::_M_initialize_moneypunct(__c_locale __cloc, + const char*) + { + if (!_M_data) + _M_data = new __moneypunct_cache; + + if (!__cloc) + { + // "C" locale + _M_data->_M_decimal_point = L'.'; + _M_data->_M_thousands_sep = L','; + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_curr_symbol = L""; + _M_data->_M_curr_symbol_size = 0; + _M_data->_M_positive_sign = L""; + _M_data->_M_positive_sign_size = 0; + _M_data->_M_negative_sign = L""; + _M_data->_M_negative_sign_size = 0; + _M_data->_M_frac_digits = 0; + _M_data->_M_pos_format = money_base::_S_default_pattern; + _M_data->_M_neg_format = money_base::_S_default_pattern; + + // Use ctype::widen code without the facet... + for (size_t __i = 0; __i < money_base::_S_end; ++__i) + _M_data->_M_atoms[__i] = + static_cast(money_base::_S_atoms[__i]); + } + else + { + __c_locale __old = (__c_locale)uselocale((locale_t)__cloc); + // Named locale. + lconv* lc = localeconv_l((locale_t) __cloc); + + // Check for NULL, which implies no fractional digits. + if (lc->mon_decimal_point == NULL || + lc->mon_decimal_point[0] == '\0') + { + // Like in "C" locale. + _M_data->_M_frac_digits = 0; + _M_data->_M_decimal_point = L'.'; + } + else + { + _M_data->_M_frac_digits = lc->frac_digits; + _M_data->_M_decimal_point = (wchar_t)lc->mon_decimal_point[0]; + } + + const char* __cgroup = lc->mon_grouping; + const char* __cpossign = lc->positive_sign; + const char* __cnegsign = lc->negative_sign; + const char* __ccurr = lc->currency_symbol; + + char* __group = 0; + wchar_t* __wcs_ps = 0; + wchar_t* __wcs_ns = 0; + const char __nposn = lc->n_sign_posn; + __try + { + size_t __len; + + // Check for NULL, which implies no grouping. + if (lc->mon_thousands_sep == NULL || + lc->mon_thousands_sep[0] == '\0') + { + // Like in "C" locale. + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_thousands_sep = L','; + } + else + { + _M_data->_M_thousands_sep = + (wchar_t)lc->mon_thousands_sep[0]; + __len = strlen(__cgroup); + if (__len) + { + __group = new char[__len + 1]; + memcpy(__group, __cgroup, __len + 1); + _M_data->_M_grouping = __group; + } + else + { + _M_data->_M_grouping = ""; + _M_data->_M_use_grouping = false; + } + _M_data->_M_grouping_size = __len; + } + + mbstate_t __state; + __len = strlen(__cpossign); + if (__len) + { + memset(&__state, 0, sizeof(mbstate_t)); + __wcs_ps = new wchar_t[__len + 1]; + mbsrtowcs(__wcs_ps, &__cpossign, __len + 1, &__state); + _M_data->_M_positive_sign = __wcs_ps; + } + else + _M_data->_M_positive_sign = L""; + _M_data->_M_positive_sign_size = + wcslen(_M_data->_M_positive_sign); + + __len = strlen(__cnegsign); + if (!__nposn) + _M_data->_M_negative_sign = L"()"; + else if (__len) + { + memset(&__state, 0, sizeof(mbstate_t)); + __wcs_ns = new wchar_t[__len + 1]; + mbsrtowcs(__wcs_ns, &__cnegsign, __len + 1, &__state); + _M_data->_M_negative_sign = __wcs_ns; + } + else + _M_data->_M_negative_sign = L""; + _M_data->_M_negative_sign_size = + wcslen(_M_data->_M_negative_sign); + + // _Intl == true. + __len = strlen(__ccurr); + if (__len) + { + memset(&__state, 0, sizeof(mbstate_t)); + wchar_t* __wcs = new wchar_t[__len + 1]; + mbsrtowcs(__wcs, &__ccurr, __len + 1, &__state); + _M_data->_M_curr_symbol = __wcs; + } + else + _M_data->_M_curr_symbol = L""; + _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol); + } + __catch(...) + { + delete _M_data; + _M_data = 0; + delete [] __group; + delete [] __wcs_ps; + delete [] __wcs_ns; + uselocale((locale_t)__old); + __throw_exception_again; + } + + char __pprecedes = lc->p_cs_precedes; + char __pspace = lc->p_sep_by_space; + char __pposn = lc->p_sign_posn; + _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, + __pposn); + char __nprecedes = lc->n_cs_precedes; + char __nspace = lc->n_sep_by_space; + _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, + __nposn); + + uselocale((locale_t)__old); + } + } + + template<> + moneypunct::~moneypunct() + { + if (_M_data->_M_grouping_size) + delete [] _M_data->_M_grouping; + if (_M_data->_M_positive_sign_size) + delete [] _M_data->_M_positive_sign; + if (_M_data->_M_negative_sign_size + && wcscmp(_M_data->_M_negative_sign, L"()") != 0) + delete [] _M_data->_M_negative_sign; + if (_M_data->_M_curr_symbol_size) + delete [] _M_data->_M_curr_symbol; + delete _M_data; + } + + template<> + moneypunct::~moneypunct() + { + if (_M_data->_M_grouping_size) + delete [] _M_data->_M_grouping; + if (_M_data->_M_positive_sign_size) + delete [] _M_data->_M_positive_sign; + if (_M_data->_M_negative_sign_size + && wcscmp(_M_data->_M_negative_sign, L"()") != 0) + delete [] _M_data->_M_negative_sign; + if (_M_data->_M_curr_symbol_size) + delete [] _M_data->_M_curr_symbol; + delete _M_data; + } +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace Index: libstdc++-v3/config/locale/dragonfly/numeric_members.cc =================================================================== --- libstdc++-v3/config/locale/dragonfly/numeric_members.cc (revision 0) +++ libstdc++-v3/config/locale/dragonfly/numeric_members.cc (working copy) @@ -0,0 +1,235 @@ +// std::numpunct implementation details, DragonFly version -*- C++ -*- + +// Copyright (C) 2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +// +// ISO C++ 14882: 22.2.3.1.2 numpunct virtual functions +// + +// Written by Benjamin Kosnik +// Modified for DragonFly by John Marino + +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template<> + void + numpunct::_M_initialize_numpunct(__c_locale __cloc) + { + if (!_M_data) + _M_data = new __numpunct_cache; + + if (!__cloc) + { + // "C" locale + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + + _M_data->_M_decimal_point = '.'; + _M_data->_M_thousands_sep = ','; + + for (size_t __i = 0; __i < __num_base::_S_oend; ++__i) + _M_data->_M_atoms_out[__i] = __num_base::_S_atoms_out[__i]; + + for (size_t __j = 0; __j < __num_base::_S_iend; ++__j) + _M_data->_M_atoms_in[__j] = __num_base::_S_atoms_in[__j]; + } + else + { + // Named locale. + lconv* lc = localeconv_l((locale_t) __cloc); + + // Decimal point should always be defined, but check null anyway + if (lc->decimal_point == NULL) + { + // Not defined, so use "C" locale default + _M_data->_M_decimal_point = '.'; + } + else + { + _M_data->_M_decimal_point = lc->decimal_point[0]; + } + // Check for NULL, which implies no grouping. + if (lc->thousands_sep == NULL || lc->thousands_sep[0] == '\0') + { + // Like in "C" locale. + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_thousands_sep = ','; + } + else + { + _M_data->_M_thousands_sep = lc->thousands_sep[0]; + + const char* __src = lc->grouping; + const size_t __len = strlen(__src); + if (__len) + { + __try + { + char* __dst = new char[__len + 1]; + memcpy(__dst, __src, __len + 1); + _M_data->_M_grouping = __dst; + _M_data->_M_use_grouping = true; + } + __catch(...) + { + delete _M_data; + _M_data = 0; + __throw_exception_again; + } + } + else + { + _M_data->_M_grouping = ""; + _M_data->_M_use_grouping = false; + } + _M_data->_M_grouping_size = __len; + } + } + + // NB: There is no way to extact this info from posix locales. + // _M_truename = __nl_langinfo_l(YESSTR, __cloc); + _M_data->_M_truename = "true"; + _M_data->_M_truename_size = 4; + // _M_falsename = __nl_langinfo_l(NOSTR, __cloc); + _M_data->_M_falsename = "false"; + _M_data->_M_falsename_size = 5; + } + + template<> + numpunct::~numpunct() + { + if (_M_data->_M_grouping_size) + delete [] _M_data->_M_grouping; + delete _M_data; + } + +#ifdef _GLIBCXX_USE_WCHAR_T + template<> + void + numpunct::_M_initialize_numpunct(__c_locale __cloc) + { + if (!_M_data) + _M_data = new __numpunct_cache; + + if (!__cloc) + { + // "C" locale + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + + _M_data->_M_decimal_point = L'.'; + _M_data->_M_thousands_sep = L','; + + // Use ctype::widen code without the facet... + for (size_t __i = 0; __i < __num_base::_S_oend; ++__i) + _M_data->_M_atoms_out[__i] = + static_cast(__num_base::_S_atoms_out[__i]); + + for (size_t __j = 0; __j < __num_base::_S_iend; ++__j) + _M_data->_M_atoms_in[__j] = + static_cast(__num_base::_S_atoms_in[__j]); + } + else + { + // Named locale. + lconv* lc = localeconv_l((locale_t) __cloc); + + // Decimal point should always be defined, but check null anyway + if (lc->decimal_point == NULL) + { + // Not defined, so use "C" locale default + _M_data->_M_decimal_point = L'.'; + } + else + { + _M_data->_M_decimal_point = (wchar_t)lc->decimal_point[0]; + } + // Check for NULL, which implies no grouping. + if (lc->thousands_sep == NULL || lc->thousands_sep[0] == '\0') + { + // Like in "C" locale. + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_thousands_sep = L','; + } + else + { + _M_data->_M_thousands_sep = (wchar_t)lc->thousands_sep[0]; + + const char* __src = lc->grouping; + const size_t __len = strlen(__src); + if (__len) + { + __try + { + char* __dst = new char[__len + 1]; + memcpy(__dst, __src, __len + 1); + _M_data->_M_grouping = __dst; + } + __catch(...) + { + delete _M_data; + _M_data = 0; + __throw_exception_again; + } + } + else + { + _M_data->_M_grouping = ""; + _M_data->_M_use_grouping = false; + } + _M_data->_M_grouping_size = __len; + } + } + + // NB: There is no way to extact this info from posix locales. + // _M_truename = __nl_langinfo_l(YESSTR, __cloc); + _M_data->_M_truename = L"true"; + _M_data->_M_truename_size = 4; + // _M_falsename = __nl_langinfo_l(NOSTR, __cloc); + _M_data->_M_falsename = L"false"; + _M_data->_M_falsename_size = 5; + } + + template<> + numpunct::~numpunct() + { + if (_M_data->_M_grouping_size) + delete [] _M_data->_M_grouping; + delete _M_data; + } + #endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace Index: libstdc++-v3/config/locale/dragonfly/time_members.cc =================================================================== --- libstdc++-v3/config/locale/dragonfly/time_members.cc (revision 0) +++ libstdc++-v3/config/locale/dragonfly/time_members.cc (working copy) @@ -0,0 +1,404 @@ +// std::time_get, std::time_put implementation, DragonFly version -*- C++ -*- + +// Copyright (C) 2001-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +// +// ISO C++ 14882: 22.2.5.1.2 - time_get virtual functions +// ISO C++ 14882: 22.2.5.3.2 - time_put virtual functions +// + +// Written by Benjamin Kosnik +// Modified for DragonFly by John Marino + +#include +#include +#include +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template<> + void + __timepunct:: + _M_put(char* __s, size_t __maxlen, const char* __format, + const tm* __tm) const throw() + { + const size_t __len = strftime_l(__s, __maxlen, __format, __tm, + (locale_t)_M_c_locale_timepunct); + // Make sure __s is null terminated. + if (__len == 0) + __s[0] = '\0'; + } + + template<> + void + __timepunct::_M_initialize_timepunct(__c_locale __cloc) + { + if (!_M_data) + _M_data = new __timepunct_cache; + + if (!__cloc) + { + // "C" locale + _M_c_locale_timepunct = _S_get_c_locale(); + + _M_data->_M_date_format = "%m/%d/%y"; + _M_data->_M_date_era_format = "%m/%d/%y"; + _M_data->_M_time_format = "%H:%M:%S"; + _M_data->_M_time_era_format = "%H:%M:%S"; + _M_data->_M_date_time_format = ""; + _M_data->_M_date_time_era_format = ""; + _M_data->_M_am = "AM"; + _M_data->_M_pm = "PM"; + _M_data->_M_am_pm_format = ""; + + // Day names, starting with "C"'s Sunday. + _M_data->_M_day1 = "Sunday"; + _M_data->_M_day2 = "Monday"; + _M_data->_M_day3 = "Tuesday"; + _M_data->_M_day4 = "Wednesday"; + _M_data->_M_day5 = "Thursday"; + _M_data->_M_day6 = "Friday"; + _M_data->_M_day7 = "Saturday"; + + // Abbreviated day names, starting with "C"'s Sun. + _M_data->_M_aday1 = "Sun"; + _M_data->_M_aday2 = "Mon"; + _M_data->_M_aday3 = "Tue"; + _M_data->_M_aday4 = "Wed"; + _M_data->_M_aday5 = "Thu"; + _M_data->_M_aday6 = "Fri"; + _M_data->_M_aday7 = "Sat"; + + // Month names, starting with "C"'s January. + _M_data->_M_month01 = "January"; + _M_data->_M_month02 = "February"; + _M_data->_M_month03 = "March"; + _M_data->_M_month04 = "April"; + _M_data->_M_month05 = "May"; + _M_data->_M_month06 = "June"; + _M_data->_M_month07 = "July"; + _M_data->_M_month08 = "August"; + _M_data->_M_month09 = "September"; + _M_data->_M_month10 = "October"; + _M_data->_M_month11 = "November"; + _M_data->_M_month12 = "December"; + + // Abbreviated month names, starting with "C"'s Jan. + _M_data->_M_amonth01 = "Jan"; + _M_data->_M_amonth02 = "Feb"; + _M_data->_M_amonth03 = "Mar"; + _M_data->_M_amonth04 = "Apr"; + _M_data->_M_amonth05 = "May"; + _M_data->_M_amonth06 = "Jun"; + _M_data->_M_amonth07 = "Jul"; + _M_data->_M_amonth08 = "Aug"; + _M_data->_M_amonth09 = "Sep"; + _M_data->_M_amonth10 = "Oct"; + _M_data->_M_amonth11 = "Nov"; + _M_data->_M_amonth12 = "Dec"; + } + else + { + _M_c_locale_timepunct = _S_clone_c_locale(__cloc); + + _M_data->_M_date_format = nl_langinfo_l(D_FMT, (locale_t)__cloc); + _M_data->_M_date_era_format = nl_langinfo_l(ERA_D_FMT, + (locale_t)__cloc); + _M_data->_M_time_format = nl_langinfo_l(T_FMT, (locale_t)__cloc); + _M_data->_M_time_era_format = nl_langinfo_l(ERA_T_FMT, + (locale_t)__cloc); + _M_data->_M_date_time_format = nl_langinfo_l(D_T_FMT, + (locale_t)__cloc); + _M_data->_M_date_time_era_format = nl_langinfo_l(ERA_D_T_FMT, + (locale_t)__cloc); + _M_data->_M_am = nl_langinfo_l(AM_STR, (locale_t)__cloc); + _M_data->_M_pm = nl_langinfo_l(PM_STR, (locale_t)__cloc); + _M_data->_M_am_pm_format = nl_langinfo_l(T_FMT_AMPM, + (locale_t)__cloc); + + // Day names, starting with "C"'s Sunday. + _M_data->_M_day1 = nl_langinfo_l(DAY_1, (locale_t)__cloc); + _M_data->_M_day2 = nl_langinfo_l(DAY_2, (locale_t)__cloc); + _M_data->_M_day3 = nl_langinfo_l(DAY_3, (locale_t)__cloc); + _M_data->_M_day4 = nl_langinfo_l(DAY_4, (locale_t)__cloc); + _M_data->_M_day5 = nl_langinfo_l(DAY_5, (locale_t)__cloc); + _M_data->_M_day6 = nl_langinfo_l(DAY_6, (locale_t)__cloc); + _M_data->_M_day7 = nl_langinfo_l(DAY_7, (locale_t)__cloc); + + // Abbreviated day names, starting with "C"'s Sun. + _M_data->_M_aday1 = nl_langinfo_l(ABDAY_1, (locale_t)__cloc); + _M_data->_M_aday2 = nl_langinfo_l(ABDAY_2, (locale_t)__cloc); + _M_data->_M_aday3 = nl_langinfo_l(ABDAY_3, (locale_t)__cloc); + _M_data->_M_aday4 = nl_langinfo_l(ABDAY_4, (locale_t)__cloc); + _M_data->_M_aday5 = nl_langinfo_l(ABDAY_5, (locale_t)__cloc); + _M_data->_M_aday6 = nl_langinfo_l(ABDAY_6, (locale_t)__cloc); + _M_data->_M_aday7 = nl_langinfo_l(ABDAY_7, (locale_t)__cloc); + + // Month names, starting with "C"'s January. + _M_data->_M_month01 = nl_langinfo_l(MON_1, (locale_t)__cloc); + _M_data->_M_month02 = nl_langinfo_l(MON_2, (locale_t)__cloc); + _M_data->_M_month03 = nl_langinfo_l(MON_3, (locale_t)__cloc); + _M_data->_M_month04 = nl_langinfo_l(MON_4, (locale_t)__cloc); + _M_data->_M_month05 = nl_langinfo_l(MON_5, (locale_t)__cloc); + _M_data->_M_month06 = nl_langinfo_l(MON_6, (locale_t)__cloc); + _M_data->_M_month07 = nl_langinfo_l(MON_7, (locale_t)__cloc); + _M_data->_M_month08 = nl_langinfo_l(MON_8, (locale_t)__cloc); + _M_data->_M_month09 = nl_langinfo_l(MON_9, (locale_t)__cloc); + _M_data->_M_month10 = nl_langinfo_l(MON_10, (locale_t)__cloc); + _M_data->_M_month11 = nl_langinfo_l(MON_11, (locale_t)__cloc); + _M_data->_M_month12 = nl_langinfo_l(MON_12, (locale_t)__cloc); + + // Abbreviated month names, starting with "C"'s Jan. + _M_data->_M_amonth01 = nl_langinfo_l(ABMON_1, (locale_t)__cloc); + _M_data->_M_amonth02 = nl_langinfo_l(ABMON_2, (locale_t)__cloc); + _M_data->_M_amonth03 = nl_langinfo_l(ABMON_3, (locale_t)__cloc); + _M_data->_M_amonth04 = nl_langinfo_l(ABMON_4, (locale_t)__cloc); + _M_data->_M_amonth05 = nl_langinfo_l(ABMON_5, (locale_t)__cloc); + _M_data->_M_amonth06 = nl_langinfo_l(ABMON_6, (locale_t)__cloc); + _M_data->_M_amonth07 = nl_langinfo_l(ABMON_7, (locale_t)__cloc); + _M_data->_M_amonth08 = nl_langinfo_l(ABMON_8, (locale_t)__cloc); + _M_data->_M_amonth09 = nl_langinfo_l(ABMON_9, (locale_t)__cloc); + _M_data->_M_amonth10 = nl_langinfo_l(ABMON_10, (locale_t)__cloc); + _M_data->_M_amonth11 = nl_langinfo_l(ABMON_11, (locale_t)__cloc); + _M_data->_M_amonth12 = nl_langinfo_l(ABMON_12, (locale_t)__cloc); + } + } + +#ifdef _GLIBCXX_USE_WCHAR_T + template<> + void + __timepunct:: + _M_put(wchar_t* __s, size_t __maxlen, const wchar_t* __format, + const tm* __tm) const throw() + { + const size_t __len = wcsftime_l(__s, __maxlen, __format, __tm, + (locale_t)_M_c_locale_timepunct); + // Make sure __s is null terminated. + if (__len == 0) + __s[0] = L'\0'; + } + +#define WIDE_LANGINFO(M,FMT) \ + fmtlen = mbstowcs_l (holder, nl_langinfo_l(FMT, (locale_t)__cloc), \ + 128, (locale_t)__cloc); \ + langstring = new wchar_t[fmtlen + 1]; \ + wcsncpy (langstring, holder, fmtlen); \ + langstring[fmtlen] = L'\0'; \ + _M_data->M = langstring; + + template<> + void + __timepunct::_M_initialize_timepunct(__c_locale __cloc) + { + if (!_M_data) + _M_data = new __timepunct_cache; + + if (!__cloc) + { + // "C" locale + _M_c_locale_timepunct = _S_get_c_locale(); + + _M_data->_M_date_format = L"%m/%d/%y"; + _M_data->_M_date_era_format = L"%m/%d/%y"; + _M_data->_M_time_format = L"%H:%M:%S"; + _M_data->_M_time_era_format = L"%H:%M:%S"; + _M_data->_M_date_time_format = L""; + _M_data->_M_date_time_era_format = L""; + _M_data->_M_am = L"AM"; + _M_data->_M_pm = L"PM"; + _M_data->_M_am_pm_format = L""; + + // Day names, starting with "C"'s Sunday. + _M_data->_M_day1 = L"Sunday"; + _M_data->_M_day2 = L"Monday"; + _M_data->_M_day3 = L"Tuesday"; + _M_data->_M_day4 = L"Wednesday"; + _M_data->_M_day5 = L"Thursday"; + _M_data->_M_day6 = L"Friday"; + _M_data->_M_day7 = L"Saturday"; + + // Abbreviated day names, starting with "C"'s Sun. + _M_data->_M_aday1 = L"Sun"; + _M_data->_M_aday2 = L"Mon"; + _M_data->_M_aday3 = L"Tue"; + _M_data->_M_aday4 = L"Wed"; + _M_data->_M_aday5 = L"Thu"; + _M_data->_M_aday6 = L"Fri"; + _M_data->_M_aday7 = L"Sat"; + + // Month names, starting with "C"'s January. + _M_data->_M_month01 = L"January"; + _M_data->_M_month02 = L"February"; + _M_data->_M_month03 = L"March"; + _M_data->_M_month04 = L"April"; + _M_data->_M_month05 = L"May"; + _M_data->_M_month06 = L"June"; + _M_data->_M_month07 = L"July"; + _M_data->_M_month08 = L"August"; + _M_data->_M_month09 = L"September"; + _M_data->_M_month10 = L"October"; + _M_data->_M_month11 = L"November"; + _M_data->_M_month12 = L"December"; + + // Abbreviated month names, starting with "C"'s Jan. + _M_data->_M_amonth01 = L"Jan"; + _M_data->_M_amonth02 = L"Feb"; + _M_data->_M_amonth03 = L"Mar"; + _M_data->_M_amonth04 = L"Apr"; + _M_data->_M_amonth05 = L"May"; + _M_data->_M_amonth06 = L"Jun"; + _M_data->_M_amonth07 = L"Jul"; + _M_data->_M_amonth08 = L"Aug"; + _M_data->_M_amonth09 = L"Sep"; + _M_data->_M_amonth10 = L"Oct"; + _M_data->_M_amonth11 = L"Nov"; + _M_data->_M_amonth12 = L"Dec"; + } + else + { + wchar_t *langstring = 0; + wchar_t holder[128]; + size_t fmtlen; + + _M_c_locale_timepunct = _S_clone_c_locale(__cloc); + + WIDE_LANGINFO(_M_date_format, D_FMT) + WIDE_LANGINFO(_M_date_era_format, ERA_D_FMT) + WIDE_LANGINFO(_M_time_format, T_FMT) + WIDE_LANGINFO(_M_time_era_format, ERA_T_FMT) + WIDE_LANGINFO(_M_date_time_format, D_T_FMT) + WIDE_LANGINFO(_M_date_time_era_format, ERA_D_T_FMT) + WIDE_LANGINFO(_M_am, AM_STR) + WIDE_LANGINFO(_M_pm, PM_STR) + WIDE_LANGINFO(_M_am_pm_format, T_FMT_AMPM) + + // Day names, starting with "C"'s Sunday. + WIDE_LANGINFO(_M_day1, DAY_1) + WIDE_LANGINFO(_M_day2, DAY_2) + WIDE_LANGINFO(_M_day3, DAY_3) + WIDE_LANGINFO(_M_day4, DAY_4) + WIDE_LANGINFO(_M_day5, DAY_5) + WIDE_LANGINFO(_M_day6, DAY_6) + WIDE_LANGINFO(_M_day7, DAY_7) + + // Abbreviated day names, starting with "C"'s Sun. + WIDE_LANGINFO(_M_aday1, ABDAY_1) + WIDE_LANGINFO(_M_aday2, ABDAY_2) + WIDE_LANGINFO(_M_aday3, ABDAY_3) + WIDE_LANGINFO(_M_aday4, ABDAY_4) + WIDE_LANGINFO(_M_aday5, ABDAY_5) + WIDE_LANGINFO(_M_aday6, ABDAY_6) + WIDE_LANGINFO(_M_aday7, ABDAY_7) + + // Month names, starting with "C"'s January. + WIDE_LANGINFO(_M_month01, MON_1) + WIDE_LANGINFO(_M_month02, MON_2) + WIDE_LANGINFO(_M_month03, MON_3) + WIDE_LANGINFO(_M_month04, MON_4) + WIDE_LANGINFO(_M_month05, MON_5) + WIDE_LANGINFO(_M_month06, MON_6) + WIDE_LANGINFO(_M_month07, MON_7) + WIDE_LANGINFO(_M_month08, MON_8) + WIDE_LANGINFO(_M_month09, MON_9) + WIDE_LANGINFO(_M_month10, MON_10) + WIDE_LANGINFO(_M_month11, MON_11) + WIDE_LANGINFO(_M_month12, MON_12) + + // Abbreviated month names, starting with "C"'s Jan. + WIDE_LANGINFO(_M_amonth01, ABMON_1) + WIDE_LANGINFO(_M_amonth02, ABMON_2) + WIDE_LANGINFO(_M_amonth03, ABMON_3) + WIDE_LANGINFO(_M_amonth04, ABMON_4) + WIDE_LANGINFO(_M_amonth05, ABMON_5) + WIDE_LANGINFO(_M_amonth06, ABMON_6) + WIDE_LANGINFO(_M_amonth07, ABMON_7) + WIDE_LANGINFO(_M_amonth08, ABMON_8) + WIDE_LANGINFO(_M_amonth09, ABMON_9) + WIDE_LANGINFO(_M_amonth10, ABMON_10) + WIDE_LANGINFO(_M_amonth11, ABMON_11) + WIDE_LANGINFO(_M_amonth12, ABMON_12) + } + } + + template<> + __timepunct::~__timepunct() + { + delete [] _M_data->_M_date_format; + delete [] _M_data->_M_date_era_format; + delete [] _M_data->_M_time_format; + delete [] _M_data->_M_time_era_format; + delete [] _M_data->_M_date_time_format; + delete [] _M_data->_M_date_time_era_format; + delete [] _M_data->_M_am; + delete [] _M_data->_M_pm; + delete [] _M_data->_M_am_pm_format; + delete [] _M_data->_M_day1; + delete [] _M_data->_M_day2; + delete [] _M_data->_M_day3; + delete [] _M_data->_M_day4; + delete [] _M_data->_M_day5; + delete [] _M_data->_M_day6; + delete [] _M_data->_M_day7; + delete [] _M_data->_M_aday1; + delete [] _M_data->_M_aday2; + delete [] _M_data->_M_aday3; + delete [] _M_data->_M_aday4; + delete [] _M_data->_M_aday5; + delete [] _M_data->_M_aday6; + delete [] _M_data->_M_aday7; + delete [] _M_data->_M_month01; + delete [] _M_data->_M_month02; + delete [] _M_data->_M_month03; + delete [] _M_data->_M_month04; + delete [] _M_data->_M_month05; + delete [] _M_data->_M_month06; + delete [] _M_data->_M_month07; + delete [] _M_data->_M_month08; + delete [] _M_data->_M_month09; + delete [] _M_data->_M_month10; + delete [] _M_data->_M_month11; + delete [] _M_data->_M_month12; + delete [] _M_data->_M_amonth01; + delete [] _M_data->_M_amonth02; + delete [] _M_data->_M_amonth03; + delete [] _M_data->_M_amonth04; + delete [] _M_data->_M_amonth05; + delete [] _M_data->_M_amonth06; + delete [] _M_data->_M_amonth07; + delete [] _M_data->_M_amonth08; + delete [] _M_data->_M_amonth09; + delete [] _M_data->_M_amonth10; + delete [] _M_data->_M_amonth11; + delete [] _M_data->_M_amonth12; + delete _M_data; + } + +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace Index: libstdc++-v3/config/locale/dragonfly/time_members.h =================================================================== --- libstdc++-v3/config/locale/dragonfly/time_members.h (revision 0) +++ libstdc++-v3/config/locale/dragonfly/time_members.h (working copy) @@ -0,0 +1,95 @@ +// std::time_get, std::time_put implementation, DragonFly version -*- C++ -*- + +// Copyright (C) 2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/time_members.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{locale} + */ + +// +// ISO C++ 14882: 22.2.5.1.2 - time_get functions +// ISO C++ 14882: 22.2.5.3.2 - time_put functions +// + +// Written by Benjamin Kosnik +// Modified for DragonFly by John Marino + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template + __timepunct<_CharT>::__timepunct(size_t __refs) + : facet(__refs), _M_data(0), _M_c_locale_timepunct(0), + _M_name_timepunct(_S_get_c_name()) + { _M_initialize_timepunct(); } + + template + __timepunct<_CharT>::__timepunct(__cache_type* __cache, size_t __refs) + : facet(__refs), _M_data(__cache), _M_c_locale_timepunct(0), + _M_name_timepunct(_S_get_c_name()) + { _M_initialize_timepunct(); } + + template + __timepunct<_CharT>::__timepunct(__c_locale __cloc, const char* __s, + size_t __refs) + : facet(__refs), _M_data(0), _M_c_locale_timepunct(0), + _M_name_timepunct(0) + { + if (__builtin_strcmp(__s, _S_get_c_name()) != 0) + { + const size_t __len = __builtin_strlen(__s) + 1; + char* __tmp = new char[__len]; + __builtin_memcpy(__tmp, __s, __len); + _M_name_timepunct = __tmp; + } + else + _M_name_timepunct = _S_get_c_name(); + + __try + { _M_initialize_timepunct(__cloc); } + __catch(...) + { + if (_M_name_timepunct != _S_get_c_name()) + delete [] _M_name_timepunct; + __throw_exception_again; + } + } + + template + __timepunct<_CharT>::~__timepunct() + { + if (_M_name_timepunct != _S_get_c_name()) + delete [] _M_name_timepunct; + delete _M_data; + _S_destroy_c_locale(_M_c_locale_timepunct); + } + + // specialization + template<> + __timepunct::~__timepunct(); + + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace Index: libstdc++-v3/config/os/bsd/dragonfly/ctype_configure_char.cc =================================================================== --- libstdc++-v3/config/os/bsd/dragonfly/ctype_configure_char.cc (revision 226444) +++ libstdc++-v3/config/os/bsd/dragonfly/ctype_configure_char.cc (working copy) @@ -40,29 +40,57 @@ const ctype_base::mask* ctype::classic_table() throw() - { return 0; } + { return NULL; } ctype::ctype(__c_locale, const mask* __table, bool __del, size_t __refs) - : facet(__refs), _M_del(__table != 0 && __del), - _M_toupper(NULL), _M_tolower(NULL), - _M_table(__table ? __table : classic_table()) - { + : facet(__refs), _M_c_locale_ctype(_S_get_c_locale()), + _M_del(__table != 0 && __del), _M_widen_ok(0), _M_narrow_ok(0) + { + char* __old = setlocale(LC_CTYPE, NULL); + char* __sav = NULL; + if (strcmp(__old, "C")) + { + const size_t __len = strlen(__old) + 1; + __sav = new char[__len]; + memcpy(__sav, __old, __len); + setlocale(LC_CTYPE, "C"); + } + _M_toupper = NULL; + _M_tolower = NULL; + _M_table = __table ? __table : classic_table(); + if (__sav) + { + setlocale(LC_CTYPE, __sav); + delete [] __sav; + } memset(_M_widen, 0, sizeof(_M_widen)); - _M_widen_ok = 0; memset(_M_narrow, 0, sizeof(_M_narrow)); - _M_narrow_ok = 0; } ctype::ctype(const mask* __table, bool __del, size_t __refs) - : facet(__refs), _M_del(__table != 0 && __del), - _M_toupper(NULL), _M_tolower(NULL), - _M_table(__table ? __table : classic_table()) - { + : facet(__refs), _M_c_locale_ctype(_S_get_c_locale()), + _M_del(__table != 0 && __del), _M_widen_ok(0), _M_narrow_ok(0) + { + char* __old = setlocale(LC_CTYPE, NULL); + char* __sav = NULL; + if (strcmp(__old, "C")) + { + const size_t __len = strlen(__old) + 1; + __sav = new char[__len]; + memcpy(__sav, __old, __len); + setlocale(LC_CTYPE, "C"); + } + _M_toupper = NULL; + _M_tolower = NULL; + _M_table = __table ? __table : classic_table(); + if (__sav) + { + setlocale(LC_CTYPE, __sav); + delete [] __sav; + } memset(_M_widen, 0, sizeof(_M_widen)); - _M_widen_ok = 0; memset(_M_narrow, 0, sizeof(_M_narrow)); - _M_narrow_ok = 0; } char Index: libstdc++-v3/configure =================================================================== --- libstdc++-v3/configure (revision 226444) +++ libstdc++-v3/configure (working copy) @@ -15986,17 +15986,17 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: dragonfly" >&5 $as_echo "dragonfly" >&6; } - CLOCALE_H=config/locale/generic/c_locale.h + CLOCALE_H=config/locale/dragonfly/c_locale.h CLOCALE_CC=config/locale/dragonfly/c_locale.cc - CCODECVT_CC=config/locale/generic/codecvt_members.cc - CCOLLATE_CC=config/locale/generic/collate_members.cc + CCODECVT_CC=config/locale/dragonfly/codecvt_members.cc + CCOLLATE_CC=config/locale/dragonfly/collate_members.cc CCTYPE_CC=config/locale/dragonfly/ctype_members.cc CMESSAGES_H=config/locale/generic/messages_members.h CMESSAGES_CC=config/locale/generic/messages_members.cc - CMONEY_CC=config/locale/generic/monetary_members.cc - CNUMERIC_CC=config/locale/generic/numeric_members.cc - CTIME_H=config/locale/generic/time_members.h - CTIME_CC=config/locale/generic/time_members.cc + CMONEY_CC=config/locale/dragonfly/monetary_members.cc + CNUMERIC_CC=config/locale/dragonfly/numeric_members.cc + CTIME_H=config/locale/dragonfly/time_members.h + CTIME_CC=config/locale/dragonfly/time_members.cc CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h ;; diff -ur generic/c_locale.cc dragonfly/c_locale.cc --- generic/c_locale.cc 2015-02-13 08:19:54.000000000 +0100 +++ dragonfly/c_locale.cc 2015-07-31 17:10:46.000000000 +0200 @@ -1,6 +1,6 @@ -// Wrapper for underlying C-language localization -*- C++ -*- +// localization implementation details, DragonFly version -*- C++ -*- -// Copyright (C) 2001-2015 Free Software Foundation, Inc. +// Copyright (C) 2014-2015 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the @@ -27,18 +27,14 @@ // // Written by Benjamin Kosnik +// Modified for DragonFly by John Marino -#include // For errno -#include // For isinf, finite, finitef, fabs -#include // For strof, strtold -#include -#include +#include #include +#include #include - -#ifdef _GLIBCXX_HAVE_IEEEFP_H -#include -#endif +#include +#include namespace std _GLIBCXX_VISIBILITY(default) { @@ -47,40 +43,10 @@ template<> void __convert_to_v(const char* __s, float& __v, ios_base::iostate& __err, - const __c_locale&) throw() + const __c_locale& __cloc) throw() { - // Assumes __s formatted for "C" locale. - char* __old = setlocale(LC_ALL, 0); - const size_t __len = strlen(__old) + 1; - char* __sav = new char[__len]; - memcpy(__sav, __old, __len); - setlocale(LC_ALL, "C"); char* __sanity; - bool __overflow = false; - -#if !__FLT_HAS_INFINITY__ - errno = 0; -#endif - -#ifdef _GLIBCXX_HAVE_STRTOF - __v = strtof(__s, &__sanity); -#else - double __d = strtod(__s, &__sanity); - __v = static_cast(__d); -#ifdef _GLIBCXX_HAVE_FINITEF - if (!finitef (__v)) - __overflow = true; -#elif defined (_GLIBCXX_HAVE_FINITE) - if (!finite (static_cast (__v))) - __overflow = true; -#elif defined (_GLIBCXX_HAVE_ISINF) - if (isinf (static_cast (__v))) - __overflow = true; -#else - if (fabs(__d) > numeric_limits::max()) - __overflow = true; -#endif -#endif // _GLIBCXX_HAVE_STRTOF + __v = strtof_l(__s, &__sanity, (locale_t)__cloc); // _GLIBCXX_RESOLVE_LIB_DEFECTS // 23. Num_get overflow result. @@ -89,44 +55,25 @@ __v = 0.0f; __err = ios_base::failbit; } - else if (__overflow -#if __FLT_HAS_INFINITY__ - || __v == numeric_limits::infinity() - || __v == -numeric_limits::infinity() -#else - || ((__v > 1.0f || __v < -1.0f) && errno == ERANGE) -#endif - ) + else if (__v == numeric_limits::infinity()) { - if (__v > 0.0f) - __v = numeric_limits::max(); - else - __v = -numeric_limits::max(); + __v = numeric_limits::max(); + __err = ios_base::failbit; + } + else if (__v == -numeric_limits::infinity()) + { + __v = -numeric_limits::max(); __err = ios_base::failbit; } - - setlocale(LC_ALL, __sav); - delete [] __sav; } template<> void __convert_to_v(const char* __s, double& __v, ios_base::iostate& __err, - const __c_locale&) throw() + const __c_locale& __cloc) throw() { - // Assumes __s formatted for "C" locale. - char* __old = setlocale(LC_ALL, 0); - const size_t __len = strlen(__old) + 1; - char* __sav = new char[__len]; - memcpy(__sav, __old, __len); - setlocale(LC_ALL, "C"); char* __sanity; - -#if !__DBL_HAS_INFINITY__ - errno = 0; -#endif - - __v = strtod(__s, &__sanity); + __v = strtod_l(__s, &__sanity, (locale_t)__cloc); // _GLIBCXX_RESOLVE_LIB_DEFECTS // 23. Num_get overflow result. @@ -135,100 +82,86 @@ __v = 0.0; __err = ios_base::failbit; } - else if ( -#if __DBL_HAS_INFINITY__ - __v == numeric_limits::infinity() - || __v == -numeric_limits::infinity()) -#else - (__v > 1.0 || __v < -1.0) && errno == ERANGE) -#endif + else if (__v == numeric_limits::infinity()) { - if (__v > 0.0) - __v = numeric_limits::max(); - else - __v = -numeric_limits::max(); + __v = numeric_limits::max(); + __err = ios_base::failbit; + } + else if (__v == -numeric_limits::infinity()) + { + __v = -numeric_limits::max(); __err = ios_base::failbit; } - - setlocale(LC_ALL, __sav); - delete [] __sav; } template<> void - __convert_to_v(const char* __s, long double& __v, - ios_base::iostate& __err, const __c_locale&) throw() + __convert_to_v(const char* __s, long double& __v, ios_base::iostate& __err, + const __c_locale& __cloc) throw() { - // Assumes __s formatted for "C" locale. - char* __old = setlocale(LC_ALL, 0); - const size_t __len = strlen(__old) + 1; - char* __sav = new char[__len]; - memcpy(__sav, __old, __len); - setlocale(LC_ALL, "C"); - -#if !__LDBL_HAS_INFINITY__ - errno = 0; -#endif - -#if defined(_GLIBCXX_HAVE_STRTOLD) && !defined(_GLIBCXX_HAVE_BROKEN_STRTOLD) char* __sanity; - __v = strtold(__s, &__sanity); + __v = strtold_l(__s, &__sanity, (locale_t)__cloc); // _GLIBCXX_RESOLVE_LIB_DEFECTS // 23. Num_get overflow result. if (__sanity == __s || *__sanity != '\0') -#else - typedef char_traits::int_type int_type; - int __p = sscanf(__s, "%Lf", &__v); - - if (!__p || static_cast(__p) == char_traits::eof()) -#endif { __v = 0.0l; __err = ios_base::failbit; } - else if ( -#if __LDBL_HAS_INFINITY__ - __v == numeric_limits::infinity() - || __v == -numeric_limits::infinity()) -#else - (__v > 1.0l || __v < -1.0l) && errno == ERANGE) -#endif + else if (__v == numeric_limits::infinity()) { - if (__v > 0.0l) - __v = numeric_limits::max(); - else - __v = -numeric_limits::max(); + __v = numeric_limits::max(); + __err = ios_base::failbit; + } + else if (__v == -numeric_limits::infinity()) + { + __v = -numeric_limits::max(); __err = ios_base::failbit; } - - setlocale(LC_ALL, __sav); - delete [] __sav; } void locale::facet::_S_create_c_locale(__c_locale& __cloc, const char* __s, - __c_locale) + __c_locale __old) { - // 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")); + __cloc = (__c_locale)newlocale(LC_ALL_MASK, __s, (locale_t)__old); + if (!__cloc) + { + // This named locale is not supported by the underlying OS. + __throw_runtime_error(__N("locale::facet::_S_create_c_locale " + "name not valid")); + } } void locale::facet::_S_destroy_c_locale(__c_locale& __cloc) - { __cloc = 0; } + { + if (__cloc && _S_get_c_locale() != __cloc) + freelocale((locale_t)__cloc); + } __c_locale - locale::facet::_S_clone_c_locale(__c_locale&) throw() - { return __c_locale(); } + locale::facet::_S_clone_c_locale(__c_locale& __cloc) throw() + { return (__c_locale)duplocale((locale_t)__cloc); } __c_locale - locale::facet::_S_lc_ctype_c_locale(__c_locale, const char*) - { return __c_locale(); } + locale::facet::_S_lc_ctype_c_locale(__c_locale __cloc, const char* __s) + { + __c_locale __dup = (__c_locale)duplocale((locale_t)__cloc); + if (__dup == __c_locale(0)) + __throw_runtime_error(__N("locale::facet::_S_lc_ctype_c_locale " + "duplocale error")); + __c_locale __changed = (__c_locale)newlocale(LC_CTYPE_MASK, __s, + (locale_t)__dup); + if (__changed == __c_locale(0)) + { + freelocale((locale_t)__dup); + __throw_runtime_error(__N("locale::facet::_S_lc_ctype_c_locale " + "newlocale error")); + } + return __changed; + } _GLIBCXX_END_NAMESPACE_VERSION } // namespace @@ -263,5 +196,5 @@ #ifdef _GLIBCXX_LONG_DOUBLE_COMPAT #define _GLIBCXX_LDBL_COMPAT(dbl, ldbl) \ extern "C" void ldbl (void) __attribute__ ((alias (#dbl))) -_GLIBCXX_LDBL_COMPAT(_ZSt14__convert_to_vIdEvPKcRT_RSt12_Ios_IostateRKPi, _ZSt14__convert_to_vIeEvPKcRT_RSt12_Ios_IostateRKPi); +_GLIBCXX_LDBL_COMPAT(_ZSt14__convert_to_vIdEvPKcRT_RSt12_Ios_IostateRKP15__locale_struct, _ZSt14__convert_to_vIeEvPKcRT_RSt12_Ios_IostateRKP15__locale_struct); #endif // _GLIBCXX_LONG_DOUBLE_COMPAT diff -ur generic/c_locale.h dragonfly/c_locale.h --- generic/c_locale.h 2015-02-13 08:19:54.000000000 +0100 +++ dragonfly/c_locale.h 2015-07-31 17:10:45.000000000 +0200 @@ -1,4 +1,4 @@ -// Wrapper for underlying C-language localization -*- C++ -*- +// localization implementation details, DragonFly version -*- C++ -*- // Copyright (C) 2001-2015 Free Software Foundation, Inc. // @@ -32,6 +32,7 @@ // // Written by Benjamin Kosnik +// Modified for DragonFly by John Marino #ifndef _GLIBCXX_CXX_LOCALE_H #define _GLIBCXX_CXX_LOCALE_H 1 @@ -53,19 +54,11 @@ // fall back to the unsafe vsprintf which, in general, can be dangerous // and should be avoided. inline int - __convert_from_v(const __c_locale&, char* __out, - const int __size __attribute__((__unused__)), + __convert_from_v(const __c_locale& __cloc, char* __out, + const int __size __attribute__ ((__unused__)), const char* __fmt, ...) { - char* __old = std::setlocale(LC_NUMERIC, 0); - char* __sav = 0; - if (__builtin_strcmp(__old, "C")) - { - const size_t __len = __builtin_strlen(__old) + 1; - __sav = new char[__len]; - __builtin_memcpy(__sav, __old, __len); - std::setlocale(LC_NUMERIC, "C"); - } + __c_locale __old = (__c_locale)uselocale((locale_t)__cloc); __builtin_va_list __args; __builtin_va_start(__args, __fmt); @@ -78,11 +71,7 @@ __builtin_va_end(__args); - if (__sav) - { - std::setlocale(LC_NUMERIC, __sav); - delete [] __sav; - } + uselocale((locale_t)__old); return __ret; } Only in generic: c++locale_internal.h diff -ur generic/codecvt_members.cc dragonfly/codecvt_members.cc --- generic/codecvt_members.cc 2015-02-13 08:19:54.000000000 +0100 +++ dragonfly/codecvt_members.cc 2015-07-31 17:10:45.000000000 +0200 @@ -1,6 +1,6 @@ -// std::codecvt implementation details, generic version -*- C++ -*- +// std::codecvt implementation details, DragonFly version -*- C++ -*- -// Copyright (C) 2002-2015 Free Software Foundation, Inc. +// Copyright (C) 2015 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the @@ -27,11 +27,12 @@ // // Written by Benjamin Kosnik +// Modified for DragonFly by John Marino #include +#include #include // For MB_CUR_MAX #include // For MB_LEN_MAX -#include namespace std _GLIBCXX_VISIBILITY(default) { @@ -47,60 +48,66 @@ extern_type*& __to_next) const { result __ret = ok; - // The conversion must be done using a temporary destination buffer - // since it is not possible to pass the size of the buffer to wcrtomb state_type __tmp_state(__state); - // The conversion must be done by calling wcrtomb in a loop rather - // than using wcsrtombs because wcsrtombs assumes that the input is - // zero-terminated. - - // Either we can upper bound the total number of external characters to - // something smaller than __to_end - __to or the conversion must be done - // using a temporary destination buffer since it is not possible to - // pass the size of the buffer to wcrtomb - if (MB_CUR_MAX * (__from_end - __from) - (__to_end - __to) <= 0) - while (__from < __from_end) - { - const size_t __conv = wcrtomb(__to, *__from, &__tmp_state); - if (__conv == static_cast(-1)) - { - __ret = error; - break; - } - __state = __tmp_state; - __to += __conv; - __from++; - } - else + __c_locale __old = (__c_locale)uselocale((locale_t)_M_c_locale_codecvt); + + // wcsnrtombs is *very* fast but stops if encounters NUL characters: + // in case we fall back to wcrtomb and then continue, in a loop. + // NB: wcsnrtombs is a GNU extension + for (__from_next = __from, __to_next = __to; + __from_next < __from_end && __to_next < __to_end + && __ret == ok;) { - extern_type __buf[MB_LEN_MAX]; - while (__from < __from_end && __to < __to_end) + const intern_type* __from_chunk_end = wmemchr(__from_next, L'\0', + __from_end - __from_next); + if (!__from_chunk_end) + __from_chunk_end = __from_end; + + __from = __from_next; + const size_t __conv = wcsnrtombs(__to_next, &__from_next, + __from_chunk_end - __from_next, + __to_end - __to_next, &__state); + if (__conv == static_cast(-1)) { - const size_t __conv = wcrtomb(__buf, *__from, &__tmp_state); - if (__conv == static_cast(-1)) - { - __ret = error; - break; - } - else if (__conv > static_cast(__to_end - __to)) + // In case of error, in order to stop at the exact place we + // have to start again from the beginning with a series of + // wcrtomb. + for (; __from < __from_next; ++__from) + __to_next += wcrtomb(__to_next, *__from, &__tmp_state); + __state = __tmp_state; + __ret = error; + } + else if (__from_next && __from_next < __from_chunk_end) + { + __to_next += __conv; + __ret = partial; + } + else + { + __from_next = __from_chunk_end; + __to_next += __conv; + } + + if (__from_next < __from_end && __ret == ok) + { + extern_type __buf[MB_LEN_MAX]; + __tmp_state = __state; + const size_t __conv2 = wcrtomb(__buf, *__from_next, &__tmp_state); + if (__conv2 > static_cast(__to_end - __to_next)) + __ret = partial; + else { - __ret = partial; - break; + memcpy(__to_next, __buf, __conv2); + __state = __tmp_state; + __to_next += __conv2; + ++__from_next; } - - memcpy(__to, __buf, __conv); - __state = __tmp_state; - __to += __conv; - __from++; } } - if (__ret == ok && __from < __from_end) - __ret = partial; + uselocale((locale_t)__old); - __from_next = __from; - __to_next = __to; return __ret; } @@ -112,47 +119,73 @@ intern_type*& __to_next) const { result __ret = ok; - // This temporary state object is necessary so __state won't be modified - // if [__from, __from_end) is a partial multibyte character. state_type __tmp_state(__state); - // Conversion must be done by calling mbrtowc in a loop rather than - // by calling mbsrtowcs because mbsrtowcs assumes that the input - // sequence is zero-terminated. - while (__from < __from_end && __to < __to_end) + __c_locale __old = (__c_locale)uselocale((locale_t)_M_c_locale_codecvt); + + // mbsnrtowcs is *very* fast but stops if encounters NUL characters: + // in case we store a L'\0' and then continue, in a loop. + // NB: mbsnrtowcs is a GNU extension + for (__from_next = __from, __to_next = __to; + __from_next < __from_end && __to_next < __to_end + && __ret == ok;) { - size_t __conv = mbrtowc(__to, __from, __from_end - __from, - &__tmp_state); + const extern_type* __from_chunk_end; + __from_chunk_end = static_cast(memchr(__from_next, '\0', + __from_end + - __from_next)); + if (!__from_chunk_end) + __from_chunk_end = __from_end; + + __from = __from_next; + size_t __conv = mbsnrtowcs(__to_next, &__from_next, + __from_chunk_end - __from_next, + __to_end - __to_next, &__state); if (__conv == static_cast(-1)) { + // In case of error, in order to stop at the exact place we + // have to start again from the beginning with a series of + // mbrtowc. + for (;; ++__to_next, __from += __conv) + { + __conv = mbrtowc(__to_next, __from, __from_end - __from, + &__tmp_state); + if (__conv == static_cast(-1) + || __conv == static_cast(-2)) + break; + } + __from_next = __from; + __state = __tmp_state; __ret = error; - break; } - else if (__conv == static_cast(-2)) + else if (__from_next && __from_next < __from_chunk_end) { - // It is unclear what to return in this case (see DR 382). + // It is unclear what to return in this case (see DR 382). + __to_next += __conv; __ret = partial; - break; } - else if (__conv == 0) + else { - // XXX Probably wrong for stateful encodings - __conv = 1; - *__to = L'\0'; + __from_next = __from_chunk_end; + __to_next += __conv; } - __state = __tmp_state; - __to++; - __from += __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; + } } - // It is not clear that __from < __from_end implies __ret != ok - // (see DR 382). - if (__ret == ok && __from < __from_end) - __ret = partial; + uselocale((locale_t)__old); - __from_next = __from; - __to_next = __to; return __ret; } @@ -163,8 +196,10 @@ // XXX This implementation assumes that the encoding is // stateless and is either single-byte or variable-width. int __ret = 0; + __c_locale __old = (__c_locale)uselocale((locale_t)_M_c_locale_codecvt); if (MB_CUR_MAX == 1) __ret = 1; + uselocale((locale_t)__old); return __ret; } @@ -172,8 +207,10 @@ codecvt:: do_max_length() const throw() { + __c_locale __old = (__c_locale)uselocale((locale_t)_M_c_locale_codecvt); // XXX Probably wrong for stateful encodings. int __ret = MB_CUR_MAX; + uselocale((locale_t)__old); return __ret; } @@ -185,32 +222,64 @@ int __ret = 0; state_type __tmp_state(__state); + __c_locale __old = (__c_locale)uselocale((locale_t)_M_c_locale_codecvt); + + // mbsnrtowcs is *very* fast but stops if encounters NUL characters: + // in case we advance past it and then continue, in a loop. + // NB: mbsnrtowcs is a GNU extension + + // A dummy internal buffer is needed in order for mbsnrtocws to consider + // its fourth parameter (it wouldn't with NULL as first parameter). + wchar_t* __to = static_cast(__builtin_alloca(sizeof(wchar_t) + * __max)); while (__from < __end && __max) { - size_t __conv = mbrtowc(0, __from, __end - __from, &__tmp_state); + const extern_type* __from_chunk_end; + __from_chunk_end = static_cast(memchr(__from, '\0', + __end + - __from)); + if (!__from_chunk_end) + __from_chunk_end = __end; + + const extern_type* __tmp_from = __from; + size_t __conv = mbsnrtowcs(__to, &__from, + __from_chunk_end - __from, + __max, &__state); if (__conv == static_cast(-1)) { - // Invalid source character - break; - } - else if (__conv == static_cast(-2)) - { - // Remainder of input does not form a complete destination - // character. + // In case of error, in order to stop at the exact place we + // have to start again from the beginning with a series of + // mbrtowc. + for (__from = __tmp_from;; __from += __conv) + { + __conv = mbrtowc(0, __from, __end - __from, + &__tmp_state); + if (__conv == static_cast(-1) + || __conv == static_cast(-2)) + break; + } + __state = __tmp_state; + __ret += __from - __tmp_from; break; } - else if (__conv == 0) + if (!__from) + __from = __from_chunk_end; + + __ret += __from - __tmp_from; + __max -= __conv; + + if (__from < __end && __max) { // XXX Probably wrong for stateful encodings - __conv = 1; + __tmp_state = __state; + ++__from; + ++__ret; + --__max; } - - __state = __tmp_state; - __from += __conv; - __ret += __conv; - __max--; } + uselocale((locale_t)__old); + return __ret; } #endif diff -ur generic/collate_members.cc dragonfly/collate_members.cc --- generic/collate_members.cc 2015-02-13 08:19:54.000000000 +0100 +++ dragonfly/collate_members.cc 2015-07-31 17:10:45.000000000 +0200 @@ -1,6 +1,6 @@ -// std::collate implementation details, generic version -*- C++ -*- +// std::collate implementation details, DragonFly version -*- C++ -*- -// Copyright (C) 2001-2015 Free Software Foundation, Inc. +// Copyright (C) 2015 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the @@ -27,6 +27,7 @@ // // Written by Benjamin Kosnik +// Modified for DragonFly by John Marino #include #include @@ -42,7 +43,7 @@ collate::_M_compare(const char* __one, const char* __two) const throw() { - int __cmp = strcoll(__one, __two); + int __cmp = strcoll_l(__one, __two, (locale_t)_M_c_locale_collate); return (__cmp >> (8 * sizeof (int) - 2)) | (__cmp != 0); } @@ -50,7 +51,7 @@ size_t collate::_M_transform(char* __to, const char* __from, size_t __n) const throw() - { return strxfrm(__to, __from, __n); } + { return strxfrm_l(__to, __from, __n, (locale_t)_M_c_locale_collate); } #ifdef _GLIBCXX_USE_WCHAR_T template<> @@ -58,7 +59,7 @@ collate::_M_compare(const wchar_t* __one, const wchar_t* __two) const throw() { - int __cmp = wcscoll(__one, __two); + int __cmp = wcscoll_l(__one, __two, (locale_t)_M_c_locale_collate); return (__cmp >> (8 * sizeof (int) - 2)) | (__cmp != 0); } @@ -66,7 +67,7 @@ size_t collate::_M_transform(wchar_t* __to, const wchar_t* __from, size_t __n) const throw() - { return wcsxfrm(__to, __from, __n); } + { return wcsxfrm_l(__to, __from, __n, (locale_t)_M_c_locale_collate); } #endif _GLIBCXX_END_NAMESPACE_VERSION diff -ur generic/ctype_members.cc dragonfly/ctype_members.cc --- generic/ctype_members.cc 2015-02-13 08:19:54.000000000 +0100 +++ dragonfly/ctype_members.cc 2015-07-31 17:10:46.000000000 +0200 @@ -1,6 +1,6 @@ -// std::ctype implementation details, generic version -*- C++ -*- +// std::ctype implementation details, DragonFly version -*- C++ -*- -// Copyright (C) 2001-2015 Free Software Foundation, Inc. +// Copyright (C) 2014-2015 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the @@ -27,12 +27,16 @@ // // Written by Benjamin Kosnik +// Modified for DragonFly by John Marino #include -#include #include #include +#ifndef _ISbit +#define _ISbit(bit) ((bit) < 8 ? ((1 << (bit)) << 8) : ((1 << (bit)) >> 8)) +#endif + namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -41,7 +45,7 @@ // various /config/os/* files. ctype_byname::ctype_byname(const char* __s, size_t __refs) : ctype(0, false, __refs) - { + { if (std::strcmp(__s, "C") != 0 && std::strcmp(__s, "POSIX") != 0) { this->_S_destroy_c_locale(this->_M_c_locale_ctype); @@ -60,59 +64,57 @@ switch (__m) { case space: - __ret = wctype("space"); + __ret = wctype_l("space", (locale_t)_M_c_locale_ctype); break; case print: - __ret = wctype("print"); + __ret = wctype_l("print", (locale_t)_M_c_locale_ctype); break; case cntrl: - __ret = wctype("cntrl"); + __ret = wctype_l("cntrl", (locale_t)_M_c_locale_ctype); break; case upper: - __ret = wctype("upper"); + __ret = wctype_l("upper", (locale_t)_M_c_locale_ctype); break; case lower: - __ret = wctype("lower"); + __ret = wctype_l("lower", (locale_t)_M_c_locale_ctype); break; case alpha: - __ret = wctype("alpha"); + __ret = wctype_l("alpha", (locale_t)_M_c_locale_ctype); break; case digit: - __ret = wctype("digit"); + __ret = wctype_l("digit", (locale_t)_M_c_locale_ctype); break; case punct: - __ret = wctype("punct"); + __ret = wctype_l("punct", (locale_t)_M_c_locale_ctype); break; case xdigit: - __ret = wctype("xdigit"); + __ret = wctype_l("xdigit", (locale_t)_M_c_locale_ctype); break; case alnum: - __ret = wctype("alnum"); + __ret = wctype_l("alnum", (locale_t)_M_c_locale_ctype); break; case graph: - __ret = wctype("graph"); + __ret = wctype_l("graph", (locale_t)_M_c_locale_ctype); + break; + case blank: + __ret = wctype_l("blank", (locale_t)_M_c_locale_ctype); break; default: - // For some targets ctype_base::blank == ctype_base::space so check - // here to avoid a duplicate case error. - if (__m == blank) - __ret = wctype("blank"); - else - __ret = __wmask_type(); + __ret = __wmask_type(); } return __ret; - }; + } wchar_t ctype::do_toupper(wchar_t __c) const - { return towupper(__c); } + { return towupper_l(__c, (locale_t)_M_c_locale_ctype); } const wchar_t* ctype::do_toupper(wchar_t* __lo, const wchar_t* __hi) const { while (__lo < __hi) { - *__lo = towupper(*__lo); + *__lo = towupper_l(*__lo, (locale_t)_M_c_locale_ctype); ++__lo; } return __hi; @@ -120,78 +122,24 @@ wchar_t ctype::do_tolower(wchar_t __c) const - { return towlower(__c); } + { return towlower_l(__c, (locale_t)_M_c_locale_ctype); } const wchar_t* ctype::do_tolower(wchar_t* __lo, const wchar_t* __hi) const { while (__lo < __hi) { - *__lo = towlower(*__lo); + *__lo = towlower_l(*__lo, (locale_t)_M_c_locale_ctype); ++__lo; } return __hi; } - bool - ctype:: - do_is(mask __m, char_type __c) const - { - bool __ret = false; - // Generically, 15 (instead of 11) since we don't know the numerical - // encoding of the various categories in /usr/include/ctype.h. - const size_t __bitmasksize = 15; - for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur) - if (__m & _M_bit[__bitcur] - && iswctype(__c, _M_wmask[__bitcur])) - { - __ret = true; - break; - } - return __ret; - } - - const wchar_t* - ctype:: - do_is(const wchar_t* __lo, const wchar_t* __hi, mask* __vec) const - { - for (;__lo < __hi; ++__vec, ++__lo) - { - // Generically, 15 (instead of 11) since we don't know the numerical - // encoding of the various categories in /usr/include/ctype.h. - const size_t __bitmasksize = 15; - mask __m = 0; - for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur) - if (iswctype(*__lo, _M_wmask[__bitcur])) - __m |= _M_bit[__bitcur]; - *__vec = __m; - } - return __hi; - } - - const wchar_t* - ctype:: - do_scan_is(mask __m, const wchar_t* __lo, const wchar_t* __hi) const - { - while (__lo < __hi && !this->do_is(__m, *__lo)) - ++__lo; - return __lo; - } - - const wchar_t* - ctype:: - do_scan_not(mask __m, const char_type* __lo, const char_type* __hi) const - { - while (__lo < __hi && this->do_is(__m, *__lo) != 0) - ++__lo; - return __lo; - } - wchar_t ctype:: do_widen(char __c) const { return _M_widen[static_cast(__c)]; } - + const char* ctype:: do_widen(const char* __lo, const char* __hi, wchar_t* __dest) const @@ -208,10 +156,12 @@ char ctype:: do_narrow(wchar_t __wc, char __dfault) const - { + { if (__wc >= 0 && __wc < 128 && _M_narrow_ok) return _M_narrow[__wc]; + __c_locale __old = (__c_locale)uselocale((locale_t)_M_c_locale_ctype); const int __c = wctob(__wc); + uselocale((locale_t)__old); return (__c == EOF ? __dfault : static_cast(__c)); } @@ -220,6 +170,7 @@ do_narrow(const wchar_t* __lo, const wchar_t* __hi, char __dfault, char* __dest) const { + __c_locale __old = (__c_locale)uselocale((locale_t)_M_c_locale_ctype); if (_M_narrow_ok) while (__lo < __hi) { @@ -241,12 +192,14 @@ ++__lo; ++__dest; } + uselocale((locale_t)__old); return __hi; } void ctype::_M_initialize_ctype() throw() { + __c_locale __old = (__c_locale)uselocale((locale_t)_M_c_locale_ctype); wint_t __i; for (__i = 0; __i < 128; ++__i) { @@ -260,15 +213,16 @@ _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 __i = 0; __i <= 15; ++__i) - { - _M_bit[__i] = static_cast(1 << __i); - _M_wmask[__i] = _M_convert_to_wmask(_M_bit[__i]); - } + for (size_t __j = 0; + __j < sizeof(_M_widen) / sizeof(wint_t); ++__j) + _M_widen[__j] = btowc(__j); + + for (size_t __k = 0; __k <= 11; ++__k) + { + _M_bit[__k] = static_cast(_ISbit(__k)); + _M_wmask[__k] = _M_convert_to_wmask(_M_bit[__k]); + } + uselocale((locale_t)__old); } #endif // _GLIBCXX_USE_WCHAR_T Only in generic: messages_members.cc Only in generic: messages_members.h diff -ur generic/monetary_members.cc dragonfly/monetary_members.cc --- generic/monetary_members.cc 2015-02-13 08:19:54.000000000 +0100 +++ dragonfly/monetary_members.cc 2015-07-31 17:10:45.000000000 +0200 @@ -1,6 +1,6 @@ -// std::moneypunct implementation details, generic version -*- C++ -*- +// std::moneypunct implementation details, DragonFly version -*- C++ -*- -// Copyright (C) 2001-2015 Free Software Foundation, Inc. +// Copyright (C) 2015 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the @@ -27,8 +27,11 @@ // // Written by Benjamin Kosnik +// Modified for DragonFly by John Marino #include +#include +#include namespace std _GLIBCXX_VISIBILITY(default) { @@ -41,134 +44,859 @@ // Construct and return valid pattern consisting of some combination of: // space none symbol sign value money_base::pattern - money_base::_S_construct_pattern(char, char, char) throw() - { return _S_default_pattern; } + money_base::_S_construct_pattern(char __precedes, char __space, + char __posn) throw() + { + pattern __ret; + + // This insanely complicated routine attempts to construct a valid + // pattern for use with moneypunct. A couple of invariants: + + // if (__precedes) symbol -> value + // else value -> symbol + + // if (__space) space + // else none + + // none == never first + // space never first or last + + // Any elegant implementations of this are welcome. + switch (__posn) + { + case 0: + case 1: + // 1 The sign precedes the value and symbol. + __ret.field[0] = sign; + if (__space) + { + // Pattern starts with sign. + if (__precedes) + { + __ret.field[1] = symbol; + __ret.field[3] = value; + } + else + { + __ret.field[1] = value; + __ret.field[3] = symbol; + } + __ret.field[2] = space; + } + else + { + // Pattern starts with sign and ends with none. + if (__precedes) + { + __ret.field[1] = symbol; + __ret.field[2] = value; + } + else + { + __ret.field[1] = value; + __ret.field[2] = symbol; + } + __ret.field[3] = none; + } + break; + case 2: + // 2 The sign follows the value and symbol. + if (__space) + { + // Pattern either ends with sign. + if (__precedes) + { + __ret.field[0] = symbol; + __ret.field[2] = value; + } + else + { + __ret.field[0] = value; + __ret.field[2] = symbol; + } + __ret.field[1] = space; + __ret.field[3] = sign; + } + else + { + // Pattern ends with sign then none. + if (__precedes) + { + __ret.field[0] = symbol; + __ret.field[1] = value; + } + else + { + __ret.field[0] = value; + __ret.field[1] = symbol; + } + __ret.field[2] = sign; + __ret.field[3] = none; + } + break; + case 3: + // 3 The sign immediately precedes the symbol. + if (__precedes) + { + __ret.field[0] = sign; + __ret.field[1] = symbol; + if (__space) + { + __ret.field[2] = space; + __ret.field[3] = value; + } + else + { + __ret.field[2] = value; + __ret.field[3] = none; + } + } + else + { + __ret.field[0] = value; + if (__space) + { + __ret.field[1] = space; + __ret.field[2] = sign; + __ret.field[3] = symbol; + } + else + { + __ret.field[1] = sign; + __ret.field[2] = symbol; + __ret.field[3] = none; + } + } + break; + case 4: + // 4 The sign immediately follows the symbol. + if (__precedes) + { + __ret.field[0] = symbol; + __ret.field[1] = sign; + if (__space) + { + __ret.field[2] = space; + __ret.field[3] = value; + } + else + { + __ret.field[2] = value; + __ret.field[3] = none; + } + } + else + { + __ret.field[0] = value; + if (__space) + { + __ret.field[1] = space; + __ret.field[2] = symbol; + __ret.field[3] = sign; + } + else + { + __ret.field[1] = symbol; + __ret.field[2] = sign; + __ret.field[3] = none; + } + } + break; + default: + __ret = pattern(); + } + return __ret; + } #endif template<> void - moneypunct::_M_initialize_moneypunct(__c_locale, const char*) + moneypunct::_M_initialize_moneypunct(__c_locale __cloc, + const char*) { - // "C" locale. if (!_M_data) _M_data = new __moneypunct_cache; - _M_data->_M_decimal_point = '.'; - _M_data->_M_thousands_sep = ','; - _M_data->_M_grouping = ""; - _M_data->_M_grouping_size = 0; - _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]; + if (!__cloc) + { + // "C" locale + _M_data->_M_decimal_point = '.'; + _M_data->_M_thousands_sep = ','; + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_curr_symbol = ""; + _M_data->_M_curr_symbol_size = 0; + _M_data->_M_positive_sign = ""; + _M_data->_M_positive_sign_size = 0; + _M_data->_M_negative_sign = ""; + _M_data->_M_negative_sign_size = 0; + _M_data->_M_frac_digits = 0; + _M_data->_M_pos_format = money_base::_S_default_pattern; + _M_data->_M_neg_format = money_base::_S_default_pattern; + + for (size_t __i = 0; __i < money_base::_S_end; ++__i) + _M_data->_M_atoms[__i] = money_base::_S_atoms[__i]; + } + else + { + // Named locale. + lconv* lc = localeconv_l((locale_t) __cloc); + + // Check for NULL, which implies no fractional digits. + if (lc->mon_decimal_point == NULL || + lc->mon_decimal_point[0] == '\0') + { + // Like in "C" locale. + _M_data->_M_frac_digits = 0; + _M_data->_M_decimal_point = '.'; + } + else + { + _M_data->_M_decimal_point = lc->mon_decimal_point[0]; + _M_data->_M_frac_digits = lc->int_frac_digits; + } + + const char* __cgroup = lc->mon_grouping; + const char* __cpossign = lc->positive_sign; + const char* __cnegsign = lc->negative_sign; + // _Intl == true + const char* __ccurr = lc->int_curr_symbol; + + char* __group = 0; + char* __ps = 0; + char* __ns = 0; + const char __nposn = lc->int_n_sign_posn; + __try + { + size_t __len; + + // Check for NULL, which implies no grouping. + if (lc->mon_thousands_sep == NULL || + lc->mon_thousands_sep[0] == '\0') + { + // Like in "C" locale. + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_thousands_sep = ','; + } + else + { + _M_data->_M_thousands_sep = lc->mon_thousands_sep[0]; + + __len = strlen(__cgroup); + if (__len) + { + __group = new char[__len + 1]; + memcpy(__group, __cgroup, __len + 1); + _M_data->_M_grouping = __group; + } + else + { + _M_data->_M_grouping = ""; + _M_data->_M_use_grouping = false; + } + _M_data->_M_grouping_size = __len; + } + + __len = strlen(__cpossign); + if (__len) + { + __ps = new char[__len + 1]; + memcpy(__ps, __cpossign, __len + 1); + _M_data->_M_positive_sign = __ps; + } + else + _M_data->_M_positive_sign = ""; + _M_data->_M_positive_sign_size = __len; + + if (!__nposn) + { + _M_data->_M_negative_sign = "()"; + _M_data->_M_negative_sign_size = 2; + } + else + { + __len = strlen(__cnegsign); + if (__len) + { + __ns = new char[__len + 1]; + memcpy(__ns, __cnegsign, __len + 1); + _M_data->_M_negative_sign = __ns; + } + else + _M_data->_M_negative_sign = ""; + _M_data->_M_negative_sign_size = __len; + } + + __len = strlen(__ccurr); + if (__len) + { + char* __curr = new char[__len + 1]; + memcpy(__curr, __ccurr, __len + 1); + _M_data->_M_curr_symbol = __curr; + } + else + _M_data->_M_curr_symbol = ""; + _M_data->_M_curr_symbol_size = __len; + } + __catch(...) + { + delete _M_data; + _M_data = 0; + delete [] __group; + delete [] __ps; + delete [] __ns; + __throw_exception_again; + } + + char __pprecedes = lc->int_p_cs_precedes; + char __pspace = lc->int_p_sep_by_space; + char __pposn = lc->int_p_sign_posn; + _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, + __pposn); + char __nprecedes = lc->int_n_cs_precedes; + char __nspace = lc->int_n_sep_by_space; + _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, + __nposn); + } } template<> void - moneypunct::_M_initialize_moneypunct(__c_locale, const char*) + moneypunct::_M_initialize_moneypunct(__c_locale __cloc, + const char*) { - // "C" locale. if (!_M_data) _M_data = new __moneypunct_cache; - _M_data->_M_decimal_point = '.'; - _M_data->_M_thousands_sep = ','; - _M_data->_M_grouping = ""; - _M_data->_M_grouping_size = 0; - _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]; + if (!__cloc) + { + // "C" locale + _M_data->_M_decimal_point = '.'; + _M_data->_M_thousands_sep = ','; + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_curr_symbol = ""; + _M_data->_M_curr_symbol_size = 0; + _M_data->_M_positive_sign = ""; + _M_data->_M_positive_sign_size = 0; + _M_data->_M_negative_sign = ""; + _M_data->_M_negative_sign_size = 0; + _M_data->_M_frac_digits = 0; + _M_data->_M_pos_format = money_base::_S_default_pattern; + _M_data->_M_neg_format = money_base::_S_default_pattern; + + for (size_t __i = 0; __i < money_base::_S_end; ++__i) + _M_data->_M_atoms[__i] = money_base::_S_atoms[__i]; + } + else + { + // Named locale. + lconv* lc = localeconv_l((locale_t) __cloc); + + // Check for NULL, which implies no fractional digits. + if (lc->mon_decimal_point == NULL || + lc->mon_decimal_point[0] == '\0') + { + // Like in "C" locale. + _M_data->_M_frac_digits = 0; + _M_data->_M_decimal_point = '.'; + } + else + { + _M_data->_M_decimal_point = lc->mon_decimal_point[0]; + _M_data->_M_frac_digits = lc->frac_digits; + } + + const char* __cgroup = lc->mon_grouping; + const char* __cpossign = lc->positive_sign; + const char* __cnegsign = lc->negative_sign; + // _Intl == false + const char* __ccurr = lc->currency_symbol; + + char* __group = 0; + char* __ps = 0; + char* __ns = 0; + const char __nposn = lc->n_sign_posn; + __try + { + size_t __len; + + // Check for NULL, which implies no grouping. + if (lc->mon_thousands_sep == NULL || + lc->mon_thousands_sep[0] == '\0') + { + // Like in "C" locale. + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_thousands_sep = ','; + } + else + { + _M_data->_M_thousands_sep = lc->mon_thousands_sep[0]; + + __len = strlen(__cgroup); + if (__len) + { + __group = new char[__len + 1]; + memcpy(__group, __cgroup, __len + 1); + _M_data->_M_grouping = __group; + } + else + { + _M_data->_M_grouping = ""; + _M_data->_M_use_grouping = false; + } + _M_data->_M_grouping_size = __len; + } + + __len = strlen(__cpossign); + if (__len) + { + __ps = new char[__len + 1]; + memcpy(__ps, __cpossign, __len + 1); + _M_data->_M_positive_sign = __ps; + } + else + _M_data->_M_positive_sign = ""; + _M_data->_M_positive_sign_size = __len; + + if (!__nposn) + { + _M_data->_M_negative_sign = "()"; + _M_data->_M_negative_sign_size = 2; + } + else + { + __len = strlen(__cnegsign); + if (__len) + { + __ns = new char[__len + 1]; + memcpy(__ns, __cnegsign, __len + 1); + _M_data->_M_negative_sign = __ns; + } + else + _M_data->_M_negative_sign = ""; + _M_data->_M_negative_sign_size = __len; + } + + __len = strlen(__ccurr); + if (__len) + { + char* __curr = new char[__len + 1]; + memcpy(__curr, __ccurr, __len + 1); + _M_data->_M_curr_symbol = __curr; + } + else + _M_data->_M_curr_symbol = ""; + _M_data->_M_curr_symbol_size = __len; + } + __catch(...) + { + delete _M_data; + _M_data = 0; + delete [] __group; + delete [] __ps; + delete [] __ns; + __throw_exception_again; + } + + char __pprecedes = lc->p_cs_precedes; + char __pspace = lc->p_sep_by_space; + char __pposn = lc->p_sign_posn; + _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, + __pposn); + char __nprecedes = lc->n_cs_precedes; + char __nspace = lc->n_sep_by_space; + _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, + __nposn); + } } template<> moneypunct::~moneypunct() - { delete _M_data; } + { + if (_M_data->_M_grouping_size) + delete [] _M_data->_M_grouping; + if (_M_data->_M_positive_sign_size) + delete [] _M_data->_M_positive_sign; + if (_M_data->_M_negative_sign_size + && strcmp(_M_data->_M_negative_sign, "()") != 0) + delete [] _M_data->_M_negative_sign; + if (_M_data->_M_curr_symbol_size) + delete [] _M_data->_M_curr_symbol; + delete _M_data; + } template<> moneypunct::~moneypunct() - { delete _M_data; } + { + if (_M_data->_M_grouping_size) + delete [] _M_data->_M_grouping; + if (_M_data->_M_positive_sign_size) + delete [] _M_data->_M_positive_sign; + if (_M_data->_M_negative_sign_size + && strcmp(_M_data->_M_negative_sign, "()") != 0) + delete [] _M_data->_M_negative_sign; + if (_M_data->_M_curr_symbol_size) + delete [] _M_data->_M_curr_symbol; + delete _M_data; + } #ifdef _GLIBCXX_USE_WCHAR_T template<> void - moneypunct::_M_initialize_moneypunct(__c_locale, + moneypunct::_M_initialize_moneypunct(__c_locale __cloc, const char*) { - // "C" locale if (!_M_data) _M_data = new __moneypunct_cache; - _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_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; - - for (size_t __i = 0; __i < money_base::_S_end; ++__i) - _M_data->_M_atoms[__i] = - static_cast(money_base::_S_atoms[__i]); + if (!__cloc) + { + // "C" locale + _M_data->_M_decimal_point = L'.'; + _M_data->_M_thousands_sep = L','; + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_curr_symbol = L""; + _M_data->_M_curr_symbol_size = 0; + _M_data->_M_positive_sign = L""; + _M_data->_M_positive_sign_size = 0; + _M_data->_M_negative_sign = L""; + _M_data->_M_negative_sign_size = 0; + _M_data->_M_frac_digits = 0; + _M_data->_M_pos_format = money_base::_S_default_pattern; + _M_data->_M_neg_format = money_base::_S_default_pattern; + + // Use ctype::widen code without the facet... + for (size_t __i = 0; __i < money_base::_S_end; ++__i) + _M_data->_M_atoms[__i] = + static_cast(money_base::_S_atoms[__i]); + } + else + { + __c_locale __old = (__c_locale)uselocale((locale_t)__cloc); + // Named locale. + lconv* lc = localeconv_l((locale_t) __cloc); + + // Check for NULL, which implies no fractional digits. + if (lc->mon_decimal_point == NULL || + lc->mon_decimal_point[0] == '\0') + { + // Like in "C" locale. + _M_data->_M_frac_digits = 0; + _M_data->_M_decimal_point = L'.'; + } + else + { + _M_data->_M_frac_digits = lc->int_frac_digits; + _M_data->_M_decimal_point = (wchar_t)lc->mon_decimal_point[0]; + } + + const char* __cgroup = lc->mon_grouping; + const char* __cpossign = lc->positive_sign; + const char* __cnegsign = lc->negative_sign; + const char* __ccurr = lc->int_curr_symbol; + + char* __group = 0; + wchar_t* __wcs_ps = 0; + wchar_t* __wcs_ns = 0; + const char __nposn = lc->int_n_sign_posn; + __try + { + size_t __len; + + // Check for NULL, which implies no grouping. + if (lc->mon_thousands_sep == NULL || + lc->mon_thousands_sep[0] == '\0') + { + // Like in "C" locale. + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_thousands_sep = L','; + } + else + { + _M_data->_M_thousands_sep = + (wchar_t)lc->mon_thousands_sep[0]; + __len = strlen(__cgroup); + if (__len) + { + __group = new char[__len + 1]; + memcpy(__group, __cgroup, __len + 1); + _M_data->_M_grouping = __group; + } + else + { + _M_data->_M_grouping = ""; + _M_data->_M_use_grouping = false; + } + _M_data->_M_grouping_size = __len; + } + + mbstate_t __state; + __len = strlen(__cpossign); + if (__len) + { + memset(&__state, 0, sizeof(mbstate_t)); + __wcs_ps = new wchar_t[__len + 1]; + mbsrtowcs(__wcs_ps, &__cpossign, __len + 1, &__state); + _M_data->_M_positive_sign = __wcs_ps; + } + else + _M_data->_M_positive_sign = L""; + _M_data->_M_positive_sign_size = + wcslen(_M_data->_M_positive_sign); + + __len = strlen(__cnegsign); + if (!__nposn) + _M_data->_M_negative_sign = L"()"; + else if (__len) + { + memset(&__state, 0, sizeof(mbstate_t)); + __wcs_ns = new wchar_t[__len + 1]; + mbsrtowcs(__wcs_ns, &__cnegsign, __len + 1, &__state); + _M_data->_M_negative_sign = __wcs_ns; + } + else + _M_data->_M_negative_sign = L""; + _M_data->_M_negative_sign_size = + wcslen(_M_data->_M_negative_sign); + + // _Intl == true. + __len = strlen(__ccurr); + if (__len) + { + memset(&__state, 0, sizeof(mbstate_t)); + wchar_t* __wcs = new wchar_t[__len + 1]; + mbsrtowcs(__wcs, &__ccurr, __len + 1, &__state); + _M_data->_M_curr_symbol = __wcs; + } + else + _M_data->_M_curr_symbol = L""; + _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol); + } + __catch(...) + { + delete _M_data; + _M_data = 0; + delete [] __group; + delete [] __wcs_ps; + delete [] __wcs_ns; + uselocale((locale_t)__old); + __throw_exception_again; + } + + char __pprecedes = lc->int_p_cs_precedes; + char __pspace = lc->int_p_sep_by_space; + char __pposn = lc->int_p_sign_posn; + _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, + __pposn); + char __nprecedes = lc->int_n_cs_precedes; + char __nspace = lc->int_n_sep_by_space; + _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, + __nposn); + + uselocale((locale_t)__old); + } } template<> - void - moneypunct::_M_initialize_moneypunct(__c_locale, - const char*) - { - // "C" locale - if (!_M_data) - _M_data = new __moneypunct_cache; + void + moneypunct::_M_initialize_moneypunct(__c_locale __cloc, + const char*) + { + if (!_M_data) + _M_data = new __moneypunct_cache; + + if (!__cloc) + { + // "C" locale + _M_data->_M_decimal_point = L'.'; + _M_data->_M_thousands_sep = L','; + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_curr_symbol = L""; + _M_data->_M_curr_symbol_size = 0; + _M_data->_M_positive_sign = L""; + _M_data->_M_positive_sign_size = 0; + _M_data->_M_negative_sign = L""; + _M_data->_M_negative_sign_size = 0; + _M_data->_M_frac_digits = 0; + _M_data->_M_pos_format = money_base::_S_default_pattern; + _M_data->_M_neg_format = money_base::_S_default_pattern; + + // Use ctype::widen code without the facet... + for (size_t __i = 0; __i < money_base::_S_end; ++__i) + _M_data->_M_atoms[__i] = + static_cast(money_base::_S_atoms[__i]); + } + else + { + __c_locale __old = (__c_locale)uselocale((locale_t)__cloc); + // Named locale. + lconv* lc = localeconv_l((locale_t) __cloc); + + // Check for NULL, which implies no fractional digits. + if (lc->mon_decimal_point == NULL || + lc->mon_decimal_point[0] == '\0') + { + // Like in "C" locale. + _M_data->_M_frac_digits = 0; + _M_data->_M_decimal_point = L'.'; + } + else + { + _M_data->_M_frac_digits = lc->frac_digits; + _M_data->_M_decimal_point = (wchar_t)lc->mon_decimal_point[0]; + } + + const char* __cgroup = lc->mon_grouping; + const char* __cpossign = lc->positive_sign; + const char* __cnegsign = lc->negative_sign; + const char* __ccurr = lc->currency_symbol; + + char* __group = 0; + wchar_t* __wcs_ps = 0; + wchar_t* __wcs_ns = 0; + const char __nposn = lc->n_sign_posn; + __try + { + size_t __len; + + // Check for NULL, which implies no grouping. + if (lc->mon_thousands_sep == NULL || + lc->mon_thousands_sep[0] == '\0') + { + // Like in "C" locale. + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_thousands_sep = L','; + } + else + { + _M_data->_M_thousands_sep = + (wchar_t)lc->mon_thousands_sep[0]; + __len = strlen(__cgroup); + if (__len) + { + __group = new char[__len + 1]; + memcpy(__group, __cgroup, __len + 1); + _M_data->_M_grouping = __group; + } + else + { + _M_data->_M_grouping = ""; + _M_data->_M_use_grouping = false; + } + _M_data->_M_grouping_size = __len; + } + + mbstate_t __state; + __len = strlen(__cpossign); + if (__len) + { + memset(&__state, 0, sizeof(mbstate_t)); + __wcs_ps = new wchar_t[__len + 1]; + mbsrtowcs(__wcs_ps, &__cpossign, __len + 1, &__state); + _M_data->_M_positive_sign = __wcs_ps; + } + else + _M_data->_M_positive_sign = L""; + _M_data->_M_positive_sign_size = + wcslen(_M_data->_M_positive_sign); + + __len = strlen(__cnegsign); + if (!__nposn) + _M_data->_M_negative_sign = L"()"; + else if (__len) + { + memset(&__state, 0, sizeof(mbstate_t)); + __wcs_ns = new wchar_t[__len + 1]; + mbsrtowcs(__wcs_ns, &__cnegsign, __len + 1, &__state); + _M_data->_M_negative_sign = __wcs_ns; + } + else + _M_data->_M_negative_sign = L""; + _M_data->_M_negative_sign_size = + wcslen(_M_data->_M_negative_sign); + + // _Intl == true. + __len = strlen(__ccurr); + if (__len) + { + memset(&__state, 0, sizeof(mbstate_t)); + wchar_t* __wcs = new wchar_t[__len + 1]; + mbsrtowcs(__wcs, &__ccurr, __len + 1, &__state); + _M_data->_M_curr_symbol = __wcs; + } + else + _M_data->_M_curr_symbol = L""; + _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol); + } + __catch(...) + { + delete _M_data; + _M_data = 0; + delete [] __group; + delete [] __wcs_ps; + delete [] __wcs_ns; + uselocale((locale_t)__old); + __throw_exception_again; + } + + char __pprecedes = lc->p_cs_precedes; + char __pspace = lc->p_sep_by_space; + char __pposn = lc->p_sign_posn; + _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, + __pposn); + char __nprecedes = lc->n_cs_precedes; + char __nspace = lc->n_sep_by_space; + _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, + __nposn); - _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_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; - - for (size_t __i = 0; __i < money_base::_S_end; ++__i) - _M_data->_M_atoms[__i] = - static_cast(money_base::_S_atoms[__i]); + uselocale((locale_t)__old); + } } template<> moneypunct::~moneypunct() - { delete _M_data; } + { + if (_M_data->_M_grouping_size) + delete [] _M_data->_M_grouping; + if (_M_data->_M_positive_sign_size) + delete [] _M_data->_M_positive_sign; + if (_M_data->_M_negative_sign_size + && wcscmp(_M_data->_M_negative_sign, L"()") != 0) + delete [] _M_data->_M_negative_sign; + if (_M_data->_M_curr_symbol_size) + delete [] _M_data->_M_curr_symbol; + delete _M_data; + } template<> moneypunct::~moneypunct() - { delete _M_data; } + { + 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 diff -ur generic/numeric_members.cc dragonfly/numeric_members.cc --- generic/numeric_members.cc 2015-02-13 08:19:54.000000000 +0100 +++ dragonfly/numeric_members.cc 2015-07-31 17:10:45.000000000 +0200 @@ -1,6 +1,6 @@ -// std::numpunct implementation details, generic version -*- C++ -*- +// std::numpunct implementation details, DragonFly version -*- C++ -*- -// Copyright (C) 2001-2015 Free Software Foundation, Inc. +// Copyright (C) 2015 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the @@ -27,8 +27,11 @@ // // Written by Benjamin Kosnik +// Modified for DragonFly by John Marino #include +#include +#include namespace std _GLIBCXX_VISIBILITY(default) { @@ -36,71 +39,197 @@ template<> void - numpunct::_M_initialize_numpunct(__c_locale) + numpunct::_M_initialize_numpunct(__c_locale __cloc) { - // "C" locale if (!_M_data) _M_data = new __numpunct_cache; - _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 __i = 0; __i < __num_base::_S_iend; ++__i) - _M_data->_M_atoms_in[__i] = __num_base::_S_atoms_in[__i]; + if (!__cloc) + { + // "C" locale + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + + _M_data->_M_decimal_point = '.'; + _M_data->_M_thousands_sep = ','; + + for (size_t __i = 0; __i < __num_base::_S_oend; ++__i) + _M_data->_M_atoms_out[__i] = __num_base::_S_atoms_out[__i]; + + for (size_t __j = 0; __j < __num_base::_S_iend; ++__j) + _M_data->_M_atoms_in[__j] = __num_base::_S_atoms_in[__j]; + } + else + { + // Named locale. + lconv* lc = localeconv_l((locale_t) __cloc); + + // Decimal point should always be defined, but check null anyway + if (lc->decimal_point == NULL) + { + // Not defined, so use "C" locale default + _M_data->_M_decimal_point = '.'; + } + else + { + _M_data->_M_decimal_point = lc->decimal_point[0]; + } + // Check for NULL, which implies no grouping. + if (lc->thousands_sep == NULL || lc->thousands_sep[0] == '\0') + { + // Like in "C" locale. + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_thousands_sep = ','; + } + else + { + _M_data->_M_thousands_sep = lc->thousands_sep[0]; + + const char* __src = lc->grouping; + const size_t __len = strlen(__src); + if (__len) + { + __try + { + char* __dst = new char[__len + 1]; + memcpy(__dst, __src, __len + 1); + _M_data->_M_grouping = __dst; + _M_data->_M_use_grouping = true; + } + __catch(...) + { + delete _M_data; + _M_data = 0; + __throw_exception_again; + } + } + else + { + _M_data->_M_grouping = ""; + _M_data->_M_use_grouping = false; + } + _M_data->_M_grouping_size = __len; + } + } + // NB: There is no way to extact this info from posix locales. + // _M_truename = __nl_langinfo_l(YESSTR, __cloc); _M_data->_M_truename = "true"; _M_data->_M_truename_size = 4; + // _M_falsename = __nl_langinfo_l(NOSTR, __cloc); _M_data->_M_falsename = "false"; _M_data->_M_falsename_size = 5; } - + template<> numpunct::~numpunct() - { delete _M_data; } - + { + if (_M_data->_M_grouping_size) + delete [] _M_data->_M_grouping; + delete _M_data; + } + #ifdef _GLIBCXX_USE_WCHAR_T template<> void - numpunct::_M_initialize_numpunct(__c_locale) + numpunct::_M_initialize_numpunct(__c_locale __cloc) { - // "C" locale if (!_M_data) _M_data = new __numpunct_cache; - _M_data->_M_grouping = ""; - _M_data->_M_grouping_size = 0; - _M_data->_M_use_grouping = false; - - _M_data->_M_decimal_point = L'.'; - _M_data->_M_thousands_sep = L','; - - // Use ctype::widen code without the facet... - for (size_t __i = 0; __i < __num_base::_S_oend; ++__i) - _M_data->_M_atoms_out[__i] = - static_cast(__num_base::_S_atoms_out[__i]); - - for (size_t __i = 0; __i < __num_base::_S_iend; ++__i) - _M_data->_M_atoms_in[__i] = - static_cast(__num_base::_S_atoms_in[__i]); + if (!__cloc) + { + // "C" locale + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + + _M_data->_M_decimal_point = L'.'; + _M_data->_M_thousands_sep = L','; + + // Use ctype::widen code without the facet... + for (size_t __i = 0; __i < __num_base::_S_oend; ++__i) + _M_data->_M_atoms_out[__i] = + static_cast(__num_base::_S_atoms_out[__i]); + + for (size_t __j = 0; __j < __num_base::_S_iend; ++__j) + _M_data->_M_atoms_in[__j] = + static_cast(__num_base::_S_atoms_in[__j]); + } + else + { + // Named locale. + lconv* lc = localeconv_l((locale_t) __cloc); + + // Decimal point should always be defined, but check null anyway + if (lc->decimal_point == NULL) + { + // Not defined, so use "C" locale default + _M_data->_M_decimal_point = L'.'; + } + else + { + _M_data->_M_decimal_point = (wchar_t)lc->decimal_point[0]; + } + // Check for NULL, which implies no grouping. + if (lc->thousands_sep == NULL || lc->thousands_sep[0] == '\0') + { + // Like in "C" locale. + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_thousands_sep = L','; + } + else + { + _M_data->_M_thousands_sep = (wchar_t)lc->thousands_sep[0]; + + const char* __src = lc->grouping; + const size_t __len = strlen(__src); + if (__len) + { + __try + { + char* __dst = new char[__len + 1]; + memcpy(__dst, __src, __len + 1); + _M_data->_M_grouping = __dst; + } + __catch(...) + { + delete _M_data; + _M_data = 0; + __throw_exception_again; + } + } + else + { + _M_data->_M_grouping = ""; + _M_data->_M_use_grouping = false; + } + _M_data->_M_grouping_size = __len; + } + } + // NB: There is no way to extact this info from posix locales. + // _M_truename = __nl_langinfo_l(YESSTR, __cloc); _M_data->_M_truename = L"true"; _M_data->_M_truename_size = 4; + // _M_falsename = __nl_langinfo_l(NOSTR, __cloc); _M_data->_M_falsename = L"false"; _M_data->_M_falsename_size = 5; } template<> numpunct::~numpunct() - { delete _M_data; } -#endif + { + if (_M_data->_M_grouping_size) + delete [] _M_data->_M_grouping; + delete _M_data; + } + #endif _GLIBCXX_END_NAMESPACE_VERSION } // namespace - diff -ur generic/time_members.cc dragonfly/time_members.cc --- generic/time_members.cc 2015-02-13 08:19:54.000000000 +0100 +++ dragonfly/time_members.cc 2015-07-31 17:10:45.000000000 +0200 @@ -1,4 +1,4 @@ -// std::time_get, std::time_put implementation, generic version -*- C++ -*- +// std::time_get, std::time_put implementation, DragonFly version -*- C++ -*- // Copyright (C) 2001-2015 Free Software Foundation, Inc. // @@ -28,10 +28,14 @@ // // Written by Benjamin Kosnik +// Modified for DragonFly by John Marino #include -#include -#include +#include +#include +#include +#include +#include namespace std _GLIBCXX_VISIBILITY(default) { @@ -40,171 +44,360 @@ template<> void __timepunct:: - _M_put(char* __s, size_t __maxlen, const char* __format, + _M_put(char* __s, size_t __maxlen, const char* __format, const tm* __tm) const throw() { - char* __old = setlocale(LC_ALL, 0); - const size_t __llen = strlen(__old) + 1; - char* __sav = new char[__llen]; - memcpy(__sav, __old, __llen); - setlocale(LC_ALL, _M_name_timepunct); - const size_t __len = strftime(__s, __maxlen, __format, __tm); - setlocale(LC_ALL, __sav); - delete [] __sav; + const size_t __len = strftime_l(__s, __maxlen, __format, __tm, + (locale_t)_M_c_locale_timepunct); // Make sure __s is null terminated. if (__len == 0) __s[0] = '\0'; } - template<> + template<> void - __timepunct::_M_initialize_timepunct(__c_locale) + __timepunct::_M_initialize_timepunct(__c_locale __cloc) { - // "C" locale. if (!_M_data) _M_data = new __timepunct_cache; - _M_data->_M_date_format = "%m/%d/%y"; - _M_data->_M_date_era_format = "%m/%d/%y"; - _M_data->_M_time_format = "%H:%M:%S"; - _M_data->_M_time_era_format = "%H:%M:%S"; - _M_data->_M_date_time_format = ""; - _M_data->_M_date_time_era_format = ""; - _M_data->_M_am = "AM"; - _M_data->_M_pm = "PM"; - _M_data->_M_am_pm_format = ""; - - // Day names, starting with "C"'s Sunday. - _M_data->_M_day1 = "Sunday"; - _M_data->_M_day2 = "Monday"; - _M_data->_M_day3 = "Tuesday"; - _M_data->_M_day4 = "Wednesday"; - _M_data->_M_day5 = "Thursday"; - _M_data->_M_day6 = "Friday"; - _M_data->_M_day7 = "Saturday"; - - // Abbreviated day names, starting with "C"'s Sun. - _M_data->_M_aday1 = "Sun"; - _M_data->_M_aday2 = "Mon"; - _M_data->_M_aday3 = "Tue"; - _M_data->_M_aday4 = "Wed"; - _M_data->_M_aday5 = "Thu"; - _M_data->_M_aday6 = "Fri"; - _M_data->_M_aday7 = "Sat"; - - // Month names, starting with "C"'s January. - _M_data->_M_month01 = "January"; - _M_data->_M_month02 = "February"; - _M_data->_M_month03 = "March"; - _M_data->_M_month04 = "April"; - _M_data->_M_month05 = "May"; - _M_data->_M_month06 = "June"; - _M_data->_M_month07 = "July"; - _M_data->_M_month08 = "August"; - _M_data->_M_month09 = "September"; - _M_data->_M_month10 = "October"; - _M_data->_M_month11 = "November"; - _M_data->_M_month12 = "December"; - - // Abbreviated month names, starting with "C"'s Jan. - _M_data->_M_amonth01 = "Jan"; - _M_data->_M_amonth02 = "Feb"; - _M_data->_M_amonth03 = "Mar"; - _M_data->_M_amonth04 = "Apr"; - _M_data->_M_amonth05 = "May"; - _M_data->_M_amonth06 = "Jun"; - _M_data->_M_amonth07 = "Jul"; - _M_data->_M_amonth08 = "Aug"; - _M_data->_M_amonth09 = "Sep"; - _M_data->_M_amonth10 = "Oct"; - _M_data->_M_amonth11 = "Nov"; - _M_data->_M_amonth12 = "Dec"; + if (!__cloc) + { + // "C" locale + _M_c_locale_timepunct = _S_get_c_locale(); + + _M_data->_M_date_format = "%m/%d/%y"; + _M_data->_M_date_era_format = "%m/%d/%y"; + _M_data->_M_time_format = "%H:%M:%S"; + _M_data->_M_time_era_format = "%H:%M:%S"; + _M_data->_M_date_time_format = ""; + _M_data->_M_date_time_era_format = ""; + _M_data->_M_am = "AM"; + _M_data->_M_pm = "PM"; + _M_data->_M_am_pm_format = ""; + + // Day names, starting with "C"'s Sunday. + _M_data->_M_day1 = "Sunday"; + _M_data->_M_day2 = "Monday"; + _M_data->_M_day3 = "Tuesday"; + _M_data->_M_day4 = "Wednesday"; + _M_data->_M_day5 = "Thursday"; + _M_data->_M_day6 = "Friday"; + _M_data->_M_day7 = "Saturday"; + + // Abbreviated day names, starting with "C"'s Sun. + _M_data->_M_aday1 = "Sun"; + _M_data->_M_aday2 = "Mon"; + _M_data->_M_aday3 = "Tue"; + _M_data->_M_aday4 = "Wed"; + _M_data->_M_aday5 = "Thu"; + _M_data->_M_aday6 = "Fri"; + _M_data->_M_aday7 = "Sat"; + + // Month names, starting with "C"'s January. + _M_data->_M_month01 = "January"; + _M_data->_M_month02 = "February"; + _M_data->_M_month03 = "March"; + _M_data->_M_month04 = "April"; + _M_data->_M_month05 = "May"; + _M_data->_M_month06 = "June"; + _M_data->_M_month07 = "July"; + _M_data->_M_month08 = "August"; + _M_data->_M_month09 = "September"; + _M_data->_M_month10 = "October"; + _M_data->_M_month11 = "November"; + _M_data->_M_month12 = "December"; + + // Abbreviated month names, starting with "C"'s Jan. + _M_data->_M_amonth01 = "Jan"; + _M_data->_M_amonth02 = "Feb"; + _M_data->_M_amonth03 = "Mar"; + _M_data->_M_amonth04 = "Apr"; + _M_data->_M_amonth05 = "May"; + _M_data->_M_amonth06 = "Jun"; + _M_data->_M_amonth07 = "Jul"; + _M_data->_M_amonth08 = "Aug"; + _M_data->_M_amonth09 = "Sep"; + _M_data->_M_amonth10 = "Oct"; + _M_data->_M_amonth11 = "Nov"; + _M_data->_M_amonth12 = "Dec"; + } + else + { + _M_c_locale_timepunct = _S_clone_c_locale(__cloc); + + _M_data->_M_date_format = nl_langinfo_l(D_FMT, (locale_t)__cloc); + _M_data->_M_date_era_format = nl_langinfo_l(ERA_D_FMT, + (locale_t)__cloc); + _M_data->_M_time_format = nl_langinfo_l(T_FMT, (locale_t)__cloc); + _M_data->_M_time_era_format = nl_langinfo_l(ERA_T_FMT, + (locale_t)__cloc); + _M_data->_M_date_time_format = nl_langinfo_l(D_T_FMT, + (locale_t)__cloc); + _M_data->_M_date_time_era_format = nl_langinfo_l(ERA_D_T_FMT, + (locale_t)__cloc); + _M_data->_M_am = nl_langinfo_l(AM_STR, (locale_t)__cloc); + _M_data->_M_pm = nl_langinfo_l(PM_STR, (locale_t)__cloc); + _M_data->_M_am_pm_format = nl_langinfo_l(T_FMT_AMPM, + (locale_t)__cloc); + + // Day names, starting with "C"'s Sunday. + _M_data->_M_day1 = nl_langinfo_l(DAY_1, (locale_t)__cloc); + _M_data->_M_day2 = nl_langinfo_l(DAY_2, (locale_t)__cloc); + _M_data->_M_day3 = nl_langinfo_l(DAY_3, (locale_t)__cloc); + _M_data->_M_day4 = nl_langinfo_l(DAY_4, (locale_t)__cloc); + _M_data->_M_day5 = nl_langinfo_l(DAY_5, (locale_t)__cloc); + _M_data->_M_day6 = nl_langinfo_l(DAY_6, (locale_t)__cloc); + _M_data->_M_day7 = nl_langinfo_l(DAY_7, (locale_t)__cloc); + + // Abbreviated day names, starting with "C"'s Sun. + _M_data->_M_aday1 = nl_langinfo_l(ABDAY_1, (locale_t)__cloc); + _M_data->_M_aday2 = nl_langinfo_l(ABDAY_2, (locale_t)__cloc); + _M_data->_M_aday3 = nl_langinfo_l(ABDAY_3, (locale_t)__cloc); + _M_data->_M_aday4 = nl_langinfo_l(ABDAY_4, (locale_t)__cloc); + _M_data->_M_aday5 = nl_langinfo_l(ABDAY_5, (locale_t)__cloc); + _M_data->_M_aday6 = nl_langinfo_l(ABDAY_6, (locale_t)__cloc); + _M_data->_M_aday7 = nl_langinfo_l(ABDAY_7, (locale_t)__cloc); + + // Month names, starting with "C"'s January. + _M_data->_M_month01 = nl_langinfo_l(MON_1, (locale_t)__cloc); + _M_data->_M_month02 = nl_langinfo_l(MON_2, (locale_t)__cloc); + _M_data->_M_month03 = nl_langinfo_l(MON_3, (locale_t)__cloc); + _M_data->_M_month04 = nl_langinfo_l(MON_4, (locale_t)__cloc); + _M_data->_M_month05 = nl_langinfo_l(MON_5, (locale_t)__cloc); + _M_data->_M_month06 = nl_langinfo_l(MON_6, (locale_t)__cloc); + _M_data->_M_month07 = nl_langinfo_l(MON_7, (locale_t)__cloc); + _M_data->_M_month08 = nl_langinfo_l(MON_8, (locale_t)__cloc); + _M_data->_M_month09 = nl_langinfo_l(MON_9, (locale_t)__cloc); + _M_data->_M_month10 = nl_langinfo_l(MON_10, (locale_t)__cloc); + _M_data->_M_month11 = nl_langinfo_l(MON_11, (locale_t)__cloc); + _M_data->_M_month12 = nl_langinfo_l(MON_12, (locale_t)__cloc); + + // Abbreviated month names, starting with "C"'s Jan. + _M_data->_M_amonth01 = nl_langinfo_l(ABMON_1, (locale_t)__cloc); + _M_data->_M_amonth02 = nl_langinfo_l(ABMON_2, (locale_t)__cloc); + _M_data->_M_amonth03 = nl_langinfo_l(ABMON_3, (locale_t)__cloc); + _M_data->_M_amonth04 = nl_langinfo_l(ABMON_4, (locale_t)__cloc); + _M_data->_M_amonth05 = nl_langinfo_l(ABMON_5, (locale_t)__cloc); + _M_data->_M_amonth06 = nl_langinfo_l(ABMON_6, (locale_t)__cloc); + _M_data->_M_amonth07 = nl_langinfo_l(ABMON_7, (locale_t)__cloc); + _M_data->_M_amonth08 = nl_langinfo_l(ABMON_8, (locale_t)__cloc); + _M_data->_M_amonth09 = nl_langinfo_l(ABMON_9, (locale_t)__cloc); + _M_data->_M_amonth10 = nl_langinfo_l(ABMON_10, (locale_t)__cloc); + _M_data->_M_amonth11 = nl_langinfo_l(ABMON_11, (locale_t)__cloc); + _M_data->_M_amonth12 = nl_langinfo_l(ABMON_12, (locale_t)__cloc); + } } #ifdef _GLIBCXX_USE_WCHAR_T template<> void __timepunct:: - _M_put(wchar_t* __s, size_t __maxlen, const wchar_t* __format, + _M_put(wchar_t* __s, size_t __maxlen, const wchar_t* __format, const tm* __tm) const throw() { - char* __old = setlocale(LC_ALL, 0); - const size_t __llen = strlen(__old) + 1; - char* __sav = new char[__llen]; - memcpy(__sav, __old, __llen); - setlocale(LC_ALL, _M_name_timepunct); - const size_t __len = wcsftime(__s, __maxlen, __format, __tm); - setlocale(LC_ALL, __sav); - delete [] __sav; + const size_t __len = wcsftime_l(__s, __maxlen, __format, __tm, + (locale_t)_M_c_locale_timepunct); // Make sure __s is null terminated. if (__len == 0) __s[0] = L'\0'; } - template<> +#define WIDE_LANGINFO(M,FMT) \ + fmtlen = mbstowcs_l (holder, nl_langinfo_l(FMT, (locale_t)__cloc), \ + 128, (locale_t)__cloc); \ + langstring = new wchar_t[fmtlen + 1]; \ + wcsncpy (langstring, holder, fmtlen); \ + langstring[fmtlen] = L'\0'; \ + _M_data->M = langstring; + + template<> void - __timepunct::_M_initialize_timepunct(__c_locale) + __timepunct::_M_initialize_timepunct(__c_locale __cloc) { - // "C" locale. if (!_M_data) _M_data = new __timepunct_cache; - _M_data->_M_date_format = L"%m/%d/%y"; - _M_data->_M_date_era_format = L"%m/%d/%y"; - _M_data->_M_time_format = L"%H:%M:%S"; - _M_data->_M_time_era_format = L"%H:%M:%S"; - _M_data->_M_date_time_format = L""; - _M_data->_M_date_time_era_format = L""; - _M_data->_M_am = L"AM"; - _M_data->_M_pm = L"PM"; - _M_data->_M_am_pm_format = L""; - - // Day names, starting with "C"'s Sunday. - _M_data->_M_day1 = L"Sunday"; - _M_data->_M_day2 = L"Monday"; - _M_data->_M_day3 = L"Tuesday"; - _M_data->_M_day4 = L"Wednesday"; - _M_data->_M_day5 = L"Thursday"; - _M_data->_M_day6 = L"Friday"; - _M_data->_M_day7 = L"Saturday"; - - // Abbreviated day names, starting with "C"'s Sun. - _M_data->_M_aday1 = L"Sun"; - _M_data->_M_aday2 = L"Mon"; - _M_data->_M_aday3 = L"Tue"; - _M_data->_M_aday4 = L"Wed"; - _M_data->_M_aday5 = L"Thu"; - _M_data->_M_aday6 = L"Fri"; - _M_data->_M_aday7 = L"Sat"; - - // Month names, starting with "C"'s January. - _M_data->_M_month01 = L"January"; - _M_data->_M_month02 = L"February"; - _M_data->_M_month03 = L"March"; - _M_data->_M_month04 = L"April"; - _M_data->_M_month05 = L"May"; - _M_data->_M_month06 = L"June"; - _M_data->_M_month07 = L"July"; - _M_data->_M_month08 = L"August"; - _M_data->_M_month09 = L"September"; - _M_data->_M_month10 = L"October"; - _M_data->_M_month11 = L"November"; - _M_data->_M_month12 = L"December"; - - // Abbreviated month names, starting with "C"'s Jan. - _M_data->_M_amonth01 = L"Jan"; - _M_data->_M_amonth02 = L"Feb"; - _M_data->_M_amonth03 = L"Mar"; - _M_data->_M_amonth04 = L"Apr"; - _M_data->_M_amonth05 = L"May"; - _M_data->_M_amonth06 = L"Jun"; - _M_data->_M_amonth07 = L"Jul"; - _M_data->_M_amonth08 = L"Aug"; - _M_data->_M_amonth09 = L"Sep"; - _M_data->_M_amonth10 = L"Oct"; - _M_data->_M_amonth11 = L"Nov"; - _M_data->_M_amonth12 = L"Dec"; + if (!__cloc) + { + // "C" locale + _M_c_locale_timepunct = _S_get_c_locale(); + + _M_data->_M_date_format = L"%m/%d/%y"; + _M_data->_M_date_era_format = L"%m/%d/%y"; + _M_data->_M_time_format = L"%H:%M:%S"; + _M_data->_M_time_era_format = L"%H:%M:%S"; + _M_data->_M_date_time_format = L""; + _M_data->_M_date_time_era_format = L""; + _M_data->_M_am = L"AM"; + _M_data->_M_pm = L"PM"; + _M_data->_M_am_pm_format = L""; + + // Day names, starting with "C"'s Sunday. + _M_data->_M_day1 = L"Sunday"; + _M_data->_M_day2 = L"Monday"; + _M_data->_M_day3 = L"Tuesday"; + _M_data->_M_day4 = L"Wednesday"; + _M_data->_M_day5 = L"Thursday"; + _M_data->_M_day6 = L"Friday"; + _M_data->_M_day7 = L"Saturday"; + + // Abbreviated day names, starting with "C"'s Sun. + _M_data->_M_aday1 = L"Sun"; + _M_data->_M_aday2 = L"Mon"; + _M_data->_M_aday3 = L"Tue"; + _M_data->_M_aday4 = L"Wed"; + _M_data->_M_aday5 = L"Thu"; + _M_data->_M_aday6 = L"Fri"; + _M_data->_M_aday7 = L"Sat"; + + // Month names, starting with "C"'s January. + _M_data->_M_month01 = L"January"; + _M_data->_M_month02 = L"February"; + _M_data->_M_month03 = L"March"; + _M_data->_M_month04 = L"April"; + _M_data->_M_month05 = L"May"; + _M_data->_M_month06 = L"June"; + _M_data->_M_month07 = L"July"; + _M_data->_M_month08 = L"August"; + _M_data->_M_month09 = L"September"; + _M_data->_M_month10 = L"October"; + _M_data->_M_month11 = L"November"; + _M_data->_M_month12 = L"December"; + + // Abbreviated month names, starting with "C"'s Jan. + _M_data->_M_amonth01 = L"Jan"; + _M_data->_M_amonth02 = L"Feb"; + _M_data->_M_amonth03 = L"Mar"; + _M_data->_M_amonth04 = L"Apr"; + _M_data->_M_amonth05 = L"May"; + _M_data->_M_amonth06 = L"Jun"; + _M_data->_M_amonth07 = L"Jul"; + _M_data->_M_amonth08 = L"Aug"; + _M_data->_M_amonth09 = L"Sep"; + _M_data->_M_amonth10 = L"Oct"; + _M_data->_M_amonth11 = L"Nov"; + _M_data->_M_amonth12 = L"Dec"; + } + else + { + wchar_t *langstring = 0; + wchar_t holder[128]; + size_t fmtlen; + + _M_c_locale_timepunct = _S_clone_c_locale(__cloc); + + WIDE_LANGINFO(_M_date_format, D_FMT) + WIDE_LANGINFO(_M_date_era_format, ERA_D_FMT) + WIDE_LANGINFO(_M_time_format, T_FMT) + WIDE_LANGINFO(_M_time_era_format, ERA_T_FMT) + WIDE_LANGINFO(_M_date_time_format, D_T_FMT) + WIDE_LANGINFO(_M_date_time_era_format, ERA_D_T_FMT) + WIDE_LANGINFO(_M_am, AM_STR) + WIDE_LANGINFO(_M_pm, PM_STR) + WIDE_LANGINFO(_M_am_pm_format, T_FMT_AMPM) + + // Day names, starting with "C"'s Sunday. + WIDE_LANGINFO(_M_day1, DAY_1) + WIDE_LANGINFO(_M_day2, DAY_2) + WIDE_LANGINFO(_M_day3, DAY_3) + WIDE_LANGINFO(_M_day4, DAY_4) + WIDE_LANGINFO(_M_day5, DAY_5) + WIDE_LANGINFO(_M_day6, DAY_6) + WIDE_LANGINFO(_M_day7, DAY_7) + + // Abbreviated day names, starting with "C"'s Sun. + WIDE_LANGINFO(_M_aday1, ABDAY_1) + WIDE_LANGINFO(_M_aday2, ABDAY_2) + WIDE_LANGINFO(_M_aday3, ABDAY_3) + WIDE_LANGINFO(_M_aday4, ABDAY_4) + WIDE_LANGINFO(_M_aday5, ABDAY_5) + WIDE_LANGINFO(_M_aday6, ABDAY_6) + WIDE_LANGINFO(_M_aday7, ABDAY_7) + + // Month names, starting with "C"'s January. + WIDE_LANGINFO(_M_month01, MON_1) + WIDE_LANGINFO(_M_month02, MON_2) + WIDE_LANGINFO(_M_month03, MON_3) + WIDE_LANGINFO(_M_month04, MON_4) + WIDE_LANGINFO(_M_month05, MON_5) + WIDE_LANGINFO(_M_month06, MON_6) + WIDE_LANGINFO(_M_month07, MON_7) + WIDE_LANGINFO(_M_month08, MON_8) + WIDE_LANGINFO(_M_month09, MON_9) + WIDE_LANGINFO(_M_month10, MON_10) + WIDE_LANGINFO(_M_month11, MON_11) + WIDE_LANGINFO(_M_month12, MON_12) + + // Abbreviated month names, starting with "C"'s Jan. + WIDE_LANGINFO(_M_amonth01, ABMON_1) + WIDE_LANGINFO(_M_amonth02, ABMON_2) + WIDE_LANGINFO(_M_amonth03, ABMON_3) + WIDE_LANGINFO(_M_amonth04, ABMON_4) + WIDE_LANGINFO(_M_amonth05, ABMON_5) + WIDE_LANGINFO(_M_amonth06, ABMON_6) + WIDE_LANGINFO(_M_amonth07, ABMON_7) + WIDE_LANGINFO(_M_amonth08, ABMON_8) + WIDE_LANGINFO(_M_amonth09, ABMON_9) + WIDE_LANGINFO(_M_amonth10, ABMON_10) + WIDE_LANGINFO(_M_amonth11, ABMON_11) + WIDE_LANGINFO(_M_amonth12, ABMON_12) + } } + + template<> + __timepunct::~__timepunct() + { + delete [] _M_data->_M_date_format; + delete [] _M_data->_M_date_era_format; + delete [] _M_data->_M_time_format; + delete [] _M_data->_M_time_era_format; + delete [] _M_data->_M_date_time_format; + delete [] _M_data->_M_date_time_era_format; + delete [] _M_data->_M_am; + delete [] _M_data->_M_pm; + delete [] _M_data->_M_am_pm_format; + delete [] _M_data->_M_day1; + delete [] _M_data->_M_day2; + delete [] _M_data->_M_day3; + delete [] _M_data->_M_day4; + delete [] _M_data->_M_day5; + delete [] _M_data->_M_day6; + delete [] _M_data->_M_day7; + delete [] _M_data->_M_aday1; + delete [] _M_data->_M_aday2; + delete [] _M_data->_M_aday3; + delete [] _M_data->_M_aday4; + delete [] _M_data->_M_aday5; + delete [] _M_data->_M_aday6; + delete [] _M_data->_M_aday7; + delete [] _M_data->_M_month01; + delete [] _M_data->_M_month02; + delete [] _M_data->_M_month03; + delete [] _M_data->_M_month04; + delete [] _M_data->_M_month05; + delete [] _M_data->_M_month06; + delete [] _M_data->_M_month07; + delete [] _M_data->_M_month08; + delete [] _M_data->_M_month09; + delete [] _M_data->_M_month10; + delete [] _M_data->_M_month11; + delete [] _M_data->_M_month12; + delete [] _M_data->_M_amonth01; + delete [] _M_data->_M_amonth02; + delete [] _M_data->_M_amonth03; + delete [] _M_data->_M_amonth04; + delete [] _M_data->_M_amonth05; + delete [] _M_data->_M_amonth06; + delete [] _M_data->_M_amonth07; + delete [] _M_data->_M_amonth08; + delete [] _M_data->_M_amonth09; + delete [] _M_data->_M_amonth10; + delete [] _M_data->_M_amonth11; + delete [] _M_data->_M_amonth12; + delete _M_data; + } + #endif _GLIBCXX_END_NAMESPACE_VERSION diff -ur generic/time_members.h dragonfly/time_members.h --- generic/time_members.h 2015-02-13 08:19:54.000000000 +0100 +++ dragonfly/time_members.h 2015-07-31 17:10:45.000000000 +0200 @@ -1,6 +1,6 @@ -// std::time_get, std::time_put implementation, generic version -*- C++ -*- +// std::time_get, std::time_put implementation, DragonFly version -*- C++ -*- -// Copyright (C) 2001-2015 Free Software Foundation, Inc. +// Copyright (C) 2015 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the @@ -33,6 +33,7 @@ // // Written by Benjamin Kosnik +// Modified for DragonFly by John Marino namespace std _GLIBCXX_VISIBILITY(default) { @@ -40,24 +41,21 @@ template __timepunct<_CharT>::__timepunct(size_t __refs) - : facet(__refs), _M_data(0) - { - _M_name_timepunct = _S_get_c_name(); - _M_initialize_timepunct(); - } + : facet(__refs), _M_data(0), _M_c_locale_timepunct(0), + _M_name_timepunct(_S_get_c_name()) + { _M_initialize_timepunct(); } template __timepunct<_CharT>::__timepunct(__cache_type* __cache, size_t __refs) - : facet(__refs), _M_data(__cache) - { - _M_name_timepunct = _S_get_c_name(); - _M_initialize_timepunct(); - } + : facet(__refs), _M_data(__cache), _M_c_locale_timepunct(0), + _M_name_timepunct(_S_get_c_name()) + { _M_initialize_timepunct(); } template - __timepunct<_CharT>::__timepunct(__c_locale __cloc, const char* __s, + __timepunct<_CharT>::__timepunct(__c_locale __cloc, const char* __s, size_t __refs) - : facet(__refs), _M_data(0) + : facet(__refs), _M_data(0), _M_c_locale_timepunct(0), + _M_name_timepunct(0) { if (__builtin_strcmp(__s, _S_get_c_name()) != 0) { @@ -84,9 +82,14 @@ { if (_M_name_timepunct != _S_get_c_name()) delete [] _M_name_timepunct; - delete _M_data; + delete _M_data; _S_destroy_c_locale(_M_c_locale_timepunct); } + // specialization + template<> + __timepunct::~__timepunct(); + + _GLIBCXX_END_NAMESPACE_VERSION } // namespace