From ac2bb4377005f9bd117fee3155c9ece00f4d5b27 Mon Sep 17 00:00:00 2001 From: Paolo Carlini Date: Tue, 5 Jan 2010 20:05:20 +0000 Subject: [PATCH] re PR libstdc++/38081 (time_get<>::do_get_weekday does not always recognize full names of weekdays) 2010-01-05 Paolo Carlini PR libstdc++/38081 * include/bits/locale_facets_nonio.h (time_get<>:: _M_extract_wday_or_month): New, declare. * include/bits/locale_facets_nonio.tcc (time_get<>:: _M_extract_wday_or_month): Define. (time_get<>::do_get_weekday, time_get<>::do_get_monthname): Use it. * config/abi/pre/gnu.ver: Export new symbols. * doc/xml/manual/prerequisites.xml: Add ru_RU.UTF-8 and ru_RU.ISO-8859-5. * testsuite/lib/libstdc++.exp: Adjust. * testsuite/22_locale/time_get/get_weekday/char/38081-1.cc: New. * testsuite/22_locale/time_get/get_weekday/char/38081-2.cc: Likewise. From-SVN: r155659 --- libstdc++-v3/ChangeLog | 15 ++ libstdc++-v3/config/abi/pre/gnu.ver | 22 ++- libstdc++-v3/doc/xml/manual/prerequisites.xml | 2 + .../include/bits/locale_facets_nonio.h | 11 +- .../include/bits/locale_facets_nonio.tcc | 135 +++++++++++------- .../time_get/get_weekday/char/38081-1.cc | 86 +++++++++++ .../time_get/get_weekday/char/38081-2.cc | 98 +++++++++++++ libstdc++-v3/testsuite/lib/libstdc++.exp | 4 +- 8 files changed, 314 insertions(+), 59 deletions(-) create mode 100644 libstdc++-v3/testsuite/22_locale/time_get/get_weekday/char/38081-1.cc create mode 100644 libstdc++-v3/testsuite/22_locale/time_get/get_weekday/char/38081-2.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 5b2e5d7a9e0..f15f43de076 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,18 @@ +2010-01-05 Paolo Carlini + + PR libstdc++/38081 + * include/bits/locale_facets_nonio.h (time_get<>:: + _M_extract_wday_or_month): New, declare. + * include/bits/locale_facets_nonio.tcc (time_get<>:: + _M_extract_wday_or_month): Define. + (time_get<>::do_get_weekday, time_get<>::do_get_monthname): Use it. + * config/abi/pre/gnu.ver: Export new symbols. + * doc/xml/manual/prerequisites.xml: Add ru_RU.UTF-8 and + ru_RU.ISO-8859-5. + * testsuite/lib/libstdc++.exp: Adjust. + * testsuite/22_locale/time_get/get_weekday/char/38081-1.cc: New. + * testsuite/22_locale/time_get/get_weekday/char/38081-2.cc: Likewise. + 2010-01-05 Rainer Orth * configure: Regenerate. diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver index 2d4b0c3c363..c67898404fb 100644 --- a/libstdc++-v3/config/abi/pre/gnu.ver +++ b/libstdc++-v3/config/abi/pre/gnu.ver @@ -1,6 +1,6 @@ ## Linker script for GNU versioning (GNU ld 2.13.91+ only.) ## -## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 +## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 ## Free Software Foundation, Inc. ## ## This file is part of the GNU ISO C++ Library. This library is free @@ -149,7 +149,7 @@ GLIBCXX_3.4 { std::th[a-h]*; std::th[j-q]*; std::th[s-z]*; - std::t[i-n]*; +# std::t[i-n]*; std::tr1::h[^a]*; std::t[s-z]*; # std::[A-Zu-z]*; @@ -459,6 +459,21 @@ GLIBCXX_3.4 { # std::money_put _ZNKSt9money_putI[cw]St19ostreambuf_iteratorI[cw]St11char_traitsI[cw]EEE*; + # std::time_get + _ZNSt8time_get*; + _ZNKSt8time_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE[0-9]*; + _ZNKSt8time_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE1[0-9]*; + + # std::time_get_byname + _ZNSt15time_get_byname*; + + # std::time_put + _ZNSt8time_put*; + _ZNKSt8time_put*; + + # std::time_put_byname + _ZNSt15time_put_byname*; + # std::numeric_limits _ZNSt14numeric_limitsI[^g]E*; @@ -1081,6 +1096,9 @@ GLIBCXX_3.4.14 { _ZSt25__throw_bad_function_callv; + # std::time_get::_M_extract_wday_or_month + _ZNKSt8time_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE24_M_extract_wday_or_month*; + } GLIBCXX_3.4.13; # Symbols in the support library (libsupc++) have their own tag. diff --git a/libstdc++-v3/doc/xml/manual/prerequisites.xml b/libstdc++-v3/doc/xml/manual/prerequisites.xml index 20a04786533..6a55e0c531d 100644 --- a/libstdc++-v3/doc/xml/manual/prerequisites.xml +++ b/libstdc++-v3/doc/xml/manual/prerequisites.xml @@ -86,6 +86,8 @@ fr_FR@euro ISO-8859-15 is_IS UTF-8 it_IT ISO-8859-1 ja_JP.eucjp EUC-JP +ru_RU.ISO-8859-5 ISO-8859-5 +ru_RU.UTF-8 UTF-8 se_NO.UTF-8 UTF-8 ta_IN UTF-8 zh_TW BIG5 diff --git a/libstdc++-v3/include/bits/locale_facets_nonio.h b/libstdc++-v3/include/bits/locale_facets_nonio.h index e1518287a68..525a53326a9 100644 --- a/libstdc++-v3/include/bits/locale_facets_nonio.h +++ b/libstdc++-v3/include/bits/locale_facets_nonio.h @@ -1,6 +1,6 @@ // Locale support -*- C++ -*- -// Copyright (C) 2007, 2009 Free Software Foundation, Inc. +// Copyright (C) 2007, 2008, 2009, 2010 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 @@ -652,13 +652,18 @@ _GLIBCXX_BEGIN_NAMESPACE(std) int __min, int __max, size_t __len, ios_base& __io, ios_base::iostate& __err) const; - // Extract day or month name, or any unique array of string - // literals in a const _CharT* array. + // Extract any unique array of string literals in a const _CharT* array. iter_type _M_extract_name(iter_type __beg, iter_type __end, int& __member, const _CharT** __names, size_t __indexlen, ios_base& __io, ios_base::iostate& __err) const; + // Extract day or month name in a const _CharT* array. + iter_type + _M_extract_wday_or_month(iter_type __beg, iter_type __end, int& __member, + const _CharT** __names, size_t __indexlen, + ios_base& __io, ios_base::iostate& __err) const; + // Extract on a component-by-component basis, via __format argument. iter_type _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io, diff --git a/libstdc++-v3/include/bits/locale_facets_nonio.tcc b/libstdc++-v3/include/bits/locale_facets_nonio.tcc index 96feeafc759..73cd7470fb0 100644 --- a/libstdc++-v3/include/bits/locale_facets_nonio.tcc +++ b/libstdc++-v3/include/bits/locale_facets_nonio.tcc @@ -1,6 +1,6 @@ // Locale support -*- C++ -*- -// Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc. +// Copyright (C) 2007, 2008, 2009, 2010 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 @@ -947,6 +947,77 @@ _GLIBCXX_END_LDBL_NAMESPACE return __beg; } + template + _InIter + time_get<_CharT, _InIter>:: + _M_extract_wday_or_month(iter_type __beg, iter_type __end, int& __member, + const _CharT** __names, size_t __indexlen, + ios_base& __io, ios_base::iostate& __err) const + { + typedef char_traits<_CharT> __traits_type; + const locale& __loc = __io._M_getloc(); + const ctype<_CharT>& __ctype = use_facet >(__loc); + + int* __matches = static_cast(__builtin_alloca(2 * sizeof(int) + * __indexlen)); + size_t __nmatches = 0; + size_t* __matches_lengths = 0; + size_t __pos = 0; + + if (__beg != __end) + { + const char_type __c = *__beg; + for (size_t __i = 0; __i < 2 * __indexlen; ++__i) + if (__c == __names[__i][0] + || __c == __ctype.toupper(__names[__i][0])) + __matches[__nmatches++] = __i; + } + + if (__nmatches) + { + ++__beg, ++__pos; + + __matches_lengths + = static_cast(__builtin_alloca(sizeof(size_t) + * __nmatches)); + for (size_t __i = 0; __i < __nmatches; ++__i) + __matches_lengths[__i] + = __traits_type::length(__names[__matches[__i]]); + } + + for (; __beg != __end; ++__beg, ++__pos) + { + size_t __nskipped = 0; + const char_type __c = *__beg; + for (size_t __i = 0; __i < __nmatches;) + { + const char_type* __name = __names[__matches[__i]]; + if (__pos >= __matches_lengths[__i]) + ++__nskipped, ++__i; + else if (!(__name[__pos] == __c)) + { + --__nmatches; + __matches[__i] = __matches[__nmatches]; + __matches_lengths[__i] = __matches_lengths[__nmatches]; + } + else + ++__i; + } + if (__nskipped == __nmatches) + break; + } + + if ((__nmatches == 1 && __matches_lengths[0] == __pos) + || (__nmatches == 2 && (__matches_lengths[0] == __pos + || __matches_lengths[1] == __pos))) + __member = (__matches[0] >= __indexlen + ? __matches[0] - __indexlen : __matches[0]); + else + __err |= ios_base::failbit; + + return __beg; + } + template _InIter time_get<_CharT, _InIter>:: @@ -991,35 +1062,14 @@ _GLIBCXX_END_LDBL_NAMESPACE const locale& __loc = __io._M_getloc(); const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); const ctype<_CharT>& __ctype = use_facet >(__loc); - const char_type* __days[7]; + const char_type* __days[14]; __tp._M_days_abbreviated(__days); + __tp._M_days(__days + 7); int __tmpwday; ios_base::iostate __tmperr = ios_base::goodbit; - __beg = _M_extract_name(__beg, __end, __tmpwday, __days, 7, - __io, __tmperr); - - // Check to see if non-abbreviated name exists, and extract. - // NB: Assumes both _M_days and _M_days_abbreviated organized in - // exact same order, first to last, such that the resulting - // __days array with the same index points to a day, and that - // day's abbreviated form. - // NB: Also assumes that an abbreviated name is a subset of the name. - if (!__tmperr && __beg != __end) - { - size_t __pos = __traits_type::length(__days[__tmpwday]); - __tp._M_days(__days); - const char_type* __name = __days[__tmpwday]; - if (__name[__pos] == *__beg) - { - // Extract the rest of it. - const size_t __len = __traits_type::length(__name); - while (__pos < __len && __beg != __end - && __name[__pos] == *__beg) - ++__beg, ++__pos; - if (__len != __pos) - __tmperr |= ios_base::failbit; - } - } + + __beg = _M_extract_wday_or_month(__beg, __end, __tmpwday, __days, 7, + __io, __tmperr); if (!__tmperr) __tm->tm_wday = __tmpwday; else @@ -1040,35 +1090,14 @@ _GLIBCXX_END_LDBL_NAMESPACE const locale& __loc = __io._M_getloc(); const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); const ctype<_CharT>& __ctype = use_facet >(__loc); - const char_type* __months[12]; + const char_type* __months[24]; __tp._M_months_abbreviated(__months); + __tp._M_months(__months + 12); int __tmpmon; ios_base::iostate __tmperr = ios_base::goodbit; - __beg = _M_extract_name(__beg, __end, __tmpmon, __months, 12, - __io, __tmperr); - - // Check to see if non-abbreviated name exists, and extract. - // NB: Assumes both _M_months and _M_months_abbreviated organized in - // exact same order, first to last, such that the resulting - // __months array with the same index points to a month, and that - // month's abbreviated form. - // NB: Also assumes that an abbreviated name is a subset of the name. - if (!__tmperr && __beg != __end) - { - size_t __pos = __traits_type::length(__months[__tmpmon]); - __tp._M_months(__months); - const char_type* __name = __months[__tmpmon]; - if (__name[__pos] == *__beg) - { - // Extract the rest of it. - const size_t __len = __traits_type::length(__name); - while (__pos < __len && __beg != __end - && __name[__pos] == *__beg) - ++__beg, ++__pos; - if (__len != __pos) - __tmperr |= ios_base::failbit; - } - } + + __beg = _M_extract_wday_or_month(__beg, __end, __tmpmon, __months, 12, + __io, __tmperr); if (!__tmperr) __tm->tm_mon = __tmpmon; else diff --git a/libstdc++-v3/testsuite/22_locale/time_get/get_weekday/char/38081-1.cc b/libstdc++-v3/testsuite/22_locale/time_get/get_weekday/char/38081-1.cc new file mode 100644 index 00000000000..e237dcccbe9 --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/time_get/get_weekday/char/38081-1.cc @@ -0,0 +1,86 @@ +// { dg-require-namedlocale "" } + +// Copyright (C) 2010 Free Software Foundation +// +// 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. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 22.2.5.1.1 time_get members + +#include +#include +#include +#include + +// libstdc++/38081 +void test01() +{ + using namespace std; + bool test __attribute__((unused)) = true; + + typedef istreambuf_iterator iterator_type; + + // basic construction + locale loc("ru_RU.ISO-8859-5"); + + // create an ostream-derived object, cache the time_get facet + iterator_type end; + + istringstream iss; + iss.imbue(loc); + const time_get& tim_get = use_facet >(iss.getloc()); + + const ios_base::iostate good = ios_base::goodbit; + ios_base::iostate errorstate = good; + + // iter_type + // get_weekday(iter_type, iter_type, ios_base&, + // ios_base::iostate&, tm*) const + + iss.str("\xbf\xdd\xd4"); + iterator_type is_it01(iss); + tm time01; + memset(&time01, -1, sizeof(tm)); + errorstate = good; + tim_get.get_weekday(is_it01, end, iss, errorstate, &time01); + VERIFY( time01.tm_wday == 1 ); + VERIFY( errorstate == ios_base::eofbit ); + + iss.str("\xbf\xde\xdd\xd5\xd4\xd5\xdb\xec\xdd\xd8\xda"); + iterator_type is_it02(iss); + tm time02; + memset(&time02, -1, sizeof(tm)); + errorstate = good; + tim_get.get_weekday(is_it02, end, iss, errorstate, &time02); + VERIFY( time02.tm_wday == 1 ); + VERIFY( errorstate == ios_base::eofbit ); + + iss.str("\xbf\xdd\xd4\xd5\xd4\xd5\xdb\xec\xdd\xd8\xda"); + iterator_type is_it03(iss); + tm time03; + memset(&time03, -1, sizeof(tm)); + errorstate = good; + iterator_type ret = tim_get.get_weekday(is_it03, end, iss, + errorstate, &time03); + VERIFY( time03.tm_wday == 1 ); + VERIFY( errorstate == ios_base::goodbit ); + VERIFY( *ret == '\xd5' ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/22_locale/time_get/get_weekday/char/38081-2.cc b/libstdc++-v3/testsuite/22_locale/time_get/get_weekday/char/38081-2.cc new file mode 100644 index 00000000000..6f8806895df --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/time_get/get_weekday/char/38081-2.cc @@ -0,0 +1,98 @@ +// 2010-01-05 Paolo Carlini + +// Copyright (C) 2010 Free Software Foundation +// +// 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. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 22.2.5.1.1 time_get members + +#include +#include +#include +#include + +void test01() +{ + using namespace std; + bool test __attribute__((unused)) = true; + + typedef istreambuf_iterator iterator_type; + + // basic construction + locale loc("ru_RU.UTF8"); + + // create an ostream-derived object, cache the time_get facet + iterator_type end; + + istringstream iss; + iss.imbue(loc); + const time_get& tim_get = use_facet >(iss.getloc()); + + const ios_base::iostate good = ios_base::goodbit; + ios_base::iostate errorstate = good; + + // iter_type + // get_weekday(iter_type, iter_type, ios_base&, + // ios_base::iostate&, tm*) const + + const char* awdays[7] = { "\u0412\u0441\u043A", + "\u041F\u043D\u0434", + "\u0412\u0442\u0440", + "\u0421\u0440\u0434", + "\u0427\u0442\u0432", + "\u041F\u0442\u043D", + "\u0421\u0431\u0442" }; + + for (unsigned i = 0; i < 7; ++i) + { + iss.str(awdays[i]); + iterator_type is_it01(iss); + tm time01; + memset(&time01, -1, sizeof(tm)); + errorstate = good; + tim_get.get_weekday(is_it01, end, iss, errorstate, &time01); + VERIFY( time01.tm_wday == i ); + VERIFY( errorstate == ios_base::eofbit ); + } + + const char* wdays[7] = { "\u0412\u043E\u0441\u043A\u0440\u0435" + "\u0441\u0435\u043D\u044C\u0435", + "\u041F\u043E\u043D\u0435\u0434\u0435" + "\u043B\u044C\u043D\u0438\u043A", + "\u0412\u0442\u043E\u0440\u043D\u0438\u043A", + "\u0421\u0440\u0435\u0434\u0430", + "\u0427\u0435\u0442\u0432\u0435\u0440\u0433", + "\u041F\u044F\u0442\u043D\u0438\u0446\u0430", + "\u0421\u0443\u0431\u0431\u043E\u0442\u0430" }; + + for (unsigned i = 0; i < 7; ++i) + { + iss.str(wdays[i]); + iterator_type is_it01(iss); + tm time01; + memset(&time01, -1, sizeof(tm)); + errorstate = good; + tim_get.get_weekday(is_it01, end, iss, errorstate, &time01); + VERIFY( time01.tm_wday == i ); + VERIFY( errorstate == ios_base::eofbit ); + } +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/lib/libstdc++.exp b/libstdc++-v3/testsuite/lib/libstdc++.exp index ab4ab2434f3..09cae6d8077 100644 --- a/libstdc++-v3/testsuite/lib/libstdc++.exp +++ b/libstdc++-v3/testsuite/lib/libstdc++.exp @@ -1,6 +1,6 @@ # libstdc++ "tool init file" for DejaGNU -# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 +# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 # Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or modify @@ -883,6 +883,8 @@ proc check_v3_target_namedlocale { } { puts $f " locale(\"is_IS.UTF-8\");" puts $f " locale(\"it_IT\");" puts $f " locale(\"ja_JP.eucjp\");" + puts $f " locale(\"ru_RU.ISO-8859-5\");" + puts $f " locale(\"ru_RU.UTF-8\");" puts $f " locale(\"se_NO.UTF-8\");" puts $f " locale(\"ta_IN\");" puts $f " locale(\"zh_TW\");" -- 2.30.2