1 // Locale support -*- C++ -*-
 
    3 // Copyright (C) 1997-2014 Free Software Foundation, Inc.
 
    5 // This file is part of the GNU ISO C++ Library.  This library is free
 
    6 // software; you can redistribute it and/or modify it under the
 
    7 // terms of the GNU General Public License as published by the
 
    8 // Free Software Foundation; either version 3, or (at your option)
 
   11 // This library is distributed in the hope that it will be useful,
 
   12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
 
   13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
   14 // GNU General Public License for more details.
 
   16 // Under Section 7 of GPL version 3, you are granted additional
 
   17 // permissions described in the GCC Runtime Library Exception, version
 
   18 // 3.1, as published by the Free Software Foundation.
 
   20 // You should have received a copy of the GNU General Public License and
 
   21 // a copy of the GCC Runtime Library Exception along with this program;
 
   22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
   23 // <http://www.gnu.org/licenses/>.
 
   25 /** @file bits/locale_facets.tcc
 
   26  *  This is an internal header file, included by other library headers.
 
   27  *  Do not attempt to use it directly. @headername{locale}
 
   30 #ifndef _LOCALE_FACETS_TCC
 
   31 #define _LOCALE_FACETS_TCC 1
 
   33 #pragma GCC system_header
 
   35 namespace std _GLIBCXX_VISIBILITY(default)
 
   37 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   39   // Routine to access a cache for the facet.  If the cache didn't
 
   40   // exist before, it gets constructed on the fly.
 
   41   template<typename _Facet>
 
   45       operator() (const locale& __loc) const;
 
   49   template<typename _CharT>
 
   50     struct __use_cache<__numpunct_cache<_CharT> >
 
   52       const __numpunct_cache<_CharT>*
 
   53       operator() (const locale& __loc) const
 
   55    const size_t __i = numpunct<_CharT>::id._M_id();
 
   56    const locale::facet** __caches = __loc._M_impl->_M_caches;
 
   59        __numpunct_cache<_CharT>* __tmp = 0;
 
   62        __tmp = new __numpunct_cache<_CharT>;
 
   63        __tmp->_M_cache(__loc);
 
   68        __throw_exception_again;
 
   70        __loc._M_impl->_M_install_cache(__tmp, __i);
 
   72    return static_cast<const __numpunct_cache<_CharT>*>(__caches[__i]);
 
   76   template<typename _CharT>
 
   78     __numpunct_cache<_CharT>::_M_cache(const locale& __loc)
 
   82       const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
 
   85       _CharT* __truename = 0;
 
   86       _CharT* __falsename = 0;
 
   89      _M_grouping_size = __np.grouping().size();
 
   90      __grouping = new char[_M_grouping_size];
 
   91      __np.grouping().copy(__grouping, _M_grouping_size);
 
   92      _M_grouping = __grouping;
 
   93      _M_use_grouping = (_M_grouping_size
 
   94                 && static_cast<signed char>(_M_grouping[0]) > 0
 
   96                 != __gnu_cxx::__numeric_traits<char>::__max));
 
   98      _M_truename_size = __np.truename().size();
 
   99      __truename = new _CharT[_M_truename_size];
 
  100      __np.truename().copy(__truename, _M_truename_size);
 
  101      _M_truename = __truename;
 
  103      _M_falsename_size = __np.falsename().size();
 
  104      __falsename = new _CharT[_M_falsename_size];
 
  105      __np.falsename().copy(__falsename, _M_falsename_size);
 
  106      _M_falsename = __falsename;
 
  108      _M_decimal_point = __np.decimal_point();
 
  109      _M_thousands_sep = __np.thousands_sep();
 
  111      const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
 
  112      __ct.widen(__num_base::_S_atoms_out,
 
  113             __num_base::_S_atoms_out
 
  114             + __num_base::_S_oend, _M_atoms_out);
 
  115      __ct.widen(__num_base::_S_atoms_in,
 
  116             __num_base::_S_atoms_in
 
  117             + __num_base::_S_iend, _M_atoms_in);
 
  121      delete [] __grouping;
 
  122      delete [] __truename;
 
  123      delete [] __falsename;
 
  124      __throw_exception_again;
 
  128   // Used by both numeric and monetary facets.
 
  129   // Check to make sure that the __grouping_tmp string constructed in
 
  130   // money_get or num_get matches the canonical grouping for a given
 
  132   // __grouping_tmp is parsed L to R
 
  133   // 1,222,444 == __grouping_tmp of "\1\3\3"
 
  134   // __grouping is parsed R to L
 
  135   // 1,222,444 == __grouping of "\3" == "\3\3\3"
 
  137   __verify_grouping(const char* __grouping, size_t __grouping_size,
 
  138            const string& __grouping_tmp) throw ();
 
  140 _GLIBCXX_BEGIN_NAMESPACE_LDBL
 
  142   template<typename _CharT, typename _InIter>
 
  144     num_get<_CharT, _InIter>::
 
  145     _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io,
 
  146             ios_base::iostate& __err, string& __xtrc) const
 
  148       typedef char_traits<_CharT>          __traits_type;
 
  149       typedef __numpunct_cache<_CharT>                  __cache_type;
 
  150       __use_cache<__cache_type> __uc;
 
  151       const locale& __loc = __io._M_getloc();
 
  152       const __cache_type* __lc = __uc(__loc);
 
  153       const _CharT* __lit = __lc->_M_atoms_in;
 
  154       char_type __c = char_type();
 
  156       // True if __beg becomes equal to __end.
 
  157       bool __testeof = __beg == __end;
 
  159       // First check for sign.
 
  163      const bool __plus = __c == __lit[__num_base::_S_iplus];
 
  164      if ((__plus || __c == __lit[__num_base::_S_iminus])
 
  165          && !(__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
 
  166          && !(__c == __lc->_M_decimal_point))
 
  168          __xtrc += __plus ? '+' : '-';
 
  169          if (++__beg != __end)
 
  176       // Next, look for leading zeros.
 
  177       bool __found_mantissa = false;
 
  181      if ((__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
 
  182          || __c == __lc->_M_decimal_point)
 
  184      else if (__c == __lit[__num_base::_S_izero])
 
  186          if (!__found_mantissa)
 
  189          __found_mantissa = true;
 
  193          if (++__beg != __end)
 
  202       // Only need acceptable digits for floating point numbers.
 
  203       bool __found_dec = false;
 
  204       bool __found_sci = false;
 
  205       string __found_grouping;
 
  206       if (__lc->_M_use_grouping)
 
  207    __found_grouping.reserve(32);
 
  208       const char_type* __lit_zero = __lit + __num_base::_S_izero;
 
  210       if (!__lc->_M_allocated)
 
  214        const int __digit = _M_find(__lit_zero, 10, __c);
 
  217        __xtrc += '0' + __digit;
 
  218        __found_mantissa = true;
 
  220        else if (__c == __lc->_M_decimal_point
 
  221             && !__found_dec && !__found_sci)
 
  226        else if ((__c == __lit[__num_base::_S_ie] 
 
  227              || __c == __lit[__num_base::_S_iE])
 
  228             && !__found_sci && __found_mantissa)
 
  230        // Scientific notation.
 
  234        // Remove optional plus or minus sign, if they exist.
 
  235        if (++__beg != __end)
 
  238            const bool __plus = __c == __lit[__num_base::_S_iplus];
 
  239            if (__plus || __c == __lit[__num_base::_S_iminus])
 
  240              __xtrc += __plus ? '+' : '-';
 
  253        if (++__beg != __end)
 
  261        // According to 22.2.2.1.2, p8-9, first look for thousands_sep
 
  262        // and decimal_point.
 
  263        if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
 
  265        if (!__found_dec && !__found_sci)
 
  267            // NB: Thousands separator at the beginning of a string
 
  268            // is a no-no, as is two consecutive thousands separators.
 
  271            __found_grouping += static_cast<char>(__sep_pos);
 
  276            // NB: __convert_to_v will not assign __v and will
 
  285        else if (__c == __lc->_M_decimal_point)
 
  287        if (!__found_dec && !__found_sci)
 
  289            // If no grouping chars are seen, no grouping check
 
  290            // is applied. Therefore __found_grouping is adjusted
 
  291            // only if decimal_point comes after some thousands_sep.
 
  292            if (__found_grouping.size())
 
  293              __found_grouping += static_cast<char>(__sep_pos);
 
  302        const char_type* __q =
 
  303          __traits_type::find(__lit_zero, 10, __c);
 
  306            __xtrc += '0' + (__q - __lit_zero);
 
  307            __found_mantissa = true;
 
  310        else if ((__c == __lit[__num_base::_S_ie] 
 
  311              || __c == __lit[__num_base::_S_iE])
 
  312             && !__found_sci && __found_mantissa)
 
  314            // Scientific notation.
 
  315            if (__found_grouping.size() && !__found_dec)
 
  316              __found_grouping += static_cast<char>(__sep_pos);
 
  320            // Remove optional plus or minus sign, if they exist.
 
  321            if (++__beg != __end)
 
  324            const bool __plus = __c == __lit[__num_base::_S_iplus];
 
  325            if ((__plus || __c == __lit[__num_base::_S_iminus])
 
  326                && !(__lc->_M_use_grouping
 
  327                 && __c == __lc->_M_thousands_sep)
 
  328                && !(__c == __lc->_M_decimal_point))
 
  329              __xtrc += __plus ? '+' : '-';
 
  343        if (++__beg != __end)
 
  349       // Digit grouping is checked. If grouping and found_grouping don't
 
  350       // match, then get very very upset, and set failbit.
 
  351       if (__found_grouping.size())
 
  353           // Add the ending grouping if a decimal or 'e'/'E' wasn't found.
 
  354      if (!__found_dec && !__found_sci)
 
  355        __found_grouping += static_cast<char>(__sep_pos);
 
  357           if (!std::__verify_grouping(__lc->_M_grouping, 
 
  358                      __lc->_M_grouping_size,
 
  360        __err = ios_base::failbit;
 
  366   template<typename _CharT, typename _InIter>
 
  367     template<typename _ValueT>
 
  369       num_get<_CharT, _InIter>::
 
  370       _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io,
 
  371             ios_base::iostate& __err, _ValueT& __v) const
 
  373         typedef char_traits<_CharT>                 __traits_type;
 
  374    using __gnu_cxx::__add_unsigned;
 
  375    typedef typename __add_unsigned<_ValueT>::__type __unsigned_type;
 
  376    typedef __numpunct_cache<_CharT>                     __cache_type;
 
  377    __use_cache<__cache_type> __uc;
 
  378    const locale& __loc = __io._M_getloc();
 
  379    const __cache_type* __lc = __uc(__loc);
 
  380    const _CharT* __lit = __lc->_M_atoms_in;
 
  381    char_type __c = char_type();
 
  383    // NB: Iff __basefield == 0, __base can change based on contents.
 
  384    const ios_base::fmtflags __basefield = __io.flags()
 
  385                                           & ios_base::basefield;
 
  386    const bool __oct = __basefield == ios_base::oct;
 
  387    int __base = __oct ? 8 : (__basefield == ios_base::hex ? 16 : 10);
 
  389    // True if __beg becomes equal to __end.
 
  390    bool __testeof = __beg == __end;
 
  392    // First check for sign.
 
  393    bool __negative = false;
 
  397        __negative = __c == __lit[__num_base::_S_iminus];
 
  398        if ((__negative || __c == __lit[__num_base::_S_iplus])
 
  399        && !(__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
 
  400        && !(__c == __lc->_M_decimal_point))
 
  402        if (++__beg != __end)
 
  409    // Next, look for leading zeros and check required digits
 
  411    bool __found_zero = false;
 
  415        if ((__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
 
  416        || __c == __lc->_M_decimal_point)
 
  418        else if (__c == __lit[__num_base::_S_izero] 
 
  419             && (!__found_zero || __base == 10))
 
  423        if (__basefield == 0)
 
  428        else if (__found_zero
 
  429             && (__c == __lit[__num_base::_S_ix]
 
  430             || __c == __lit[__num_base::_S_iX]))
 
  432        if (__basefield == 0)
 
  436            __found_zero = false;
 
  445        if (++__beg != __end)
 
  455    // At this point, base is determined. If not hex, only allow
 
  456    // base digits as valid input.
 
  457    const size_t __len = (__base == 16 ? __num_base::_S_iend
 
  458                  - __num_base::_S_izero : __base);
 
  461    string __found_grouping;
 
  462    if (__lc->_M_use_grouping)
 
  463      __found_grouping.reserve(32);
 
  464    bool __testfail = false;
 
  465    bool __testoverflow = false;
 
  466    const __unsigned_type __max =
 
  467      (__negative && __gnu_cxx::__numeric_traits<_ValueT>::__is_signed)
 
  468      ? -__gnu_cxx::__numeric_traits<_ValueT>::__min
 
  469      : __gnu_cxx::__numeric_traits<_ValueT>::__max;
 
  470    const __unsigned_type __smax = __max / __base;
 
  471    __unsigned_type __result = 0;
 
  473    const char_type* __lit_zero = __lit + __num_base::_S_izero;
 
  475    if (!__lc->_M_allocated)
 
  479          __digit = _M_find(__lit_zero, __len, __c);
 
  483          if (__result > __smax)
 
  484        __testoverflow = true;
 
  488          __testoverflow |= __result > __max - __digit;
 
  493          if (++__beg != __end)
 
  501          // According to 22.2.2.1.2, p8-9, first look for thousands_sep
 
  502          // and decimal_point.
 
  503          if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
 
  505          // NB: Thousands separator at the beginning of a string
 
  506          // is a no-no, as is two consecutive thousands separators.
 
  509              __found_grouping += static_cast<char>(__sep_pos);
 
  518          else if (__c == __lc->_M_decimal_point)
 
  522          const char_type* __q =
 
  523            __traits_type::find(__lit_zero, __len, __c);
 
  527          __digit = __q - __lit_zero;
 
  530          if (__result > __smax)
 
  531            __testoverflow = true;
 
  535              __testoverflow |= __result > __max - __digit;
 
  541          if (++__beg != __end)
 
  547    // Digit grouping is checked. If grouping and found_grouping don't
 
  548    // match, then get very very upset, and set failbit.
 
  549    if (__found_grouping.size())
 
  551        // Add the ending grouping.
 
  552        __found_grouping += static_cast<char>(__sep_pos);
 
  554        if (!std::__verify_grouping(__lc->_M_grouping,
 
  555                    __lc->_M_grouping_size,
 
  557          __err = ios_base::failbit;
 
  560    // _GLIBCXX_RESOLVE_LIB_DEFECTS
 
  561    // 23. Num_get overflow result.
 
  562    if ((!__sep_pos && !__found_zero && !__found_grouping.size())
 
  566        __err = ios_base::failbit;
 
  568    else if (__testoverflow)
 
  571        && __gnu_cxx::__numeric_traits<_ValueT>::__is_signed)
 
  572          __v = __gnu_cxx::__numeric_traits<_ValueT>::__min;
 
  574          __v = __gnu_cxx::__numeric_traits<_ValueT>::__max;
 
  575        __err = ios_base::failbit;
 
  578      __v = __negative ? -__result : __result;
 
  581      __err |= ios_base::eofbit;
 
  585   // _GLIBCXX_RESOLVE_LIB_DEFECTS
 
  586   // 17.  Bad bool parsing
 
  587   template<typename _CharT, typename _InIter>
 
  589     num_get<_CharT, _InIter>::
 
  590     do_get(iter_type __beg, iter_type __end, ios_base& __io,
 
  591            ios_base::iostate& __err, bool& __v) const
 
  593       if (!(__io.flags() & ios_base::boolalpha))
 
  595      // Parse bool values as long.
 
  596           // NB: We can't just call do_get(long) here, as it might
 
  597           // refer to a derived class.
 
  599           __beg = _M_extract_int(__beg, __end, __io, __err, __l);
 
  600      if (__l == 0 || __l == 1)
 
  604          // _GLIBCXX_RESOLVE_LIB_DEFECTS
 
  605          // 23. Num_get overflow result.
 
  607          __err = ios_base::failbit;
 
  609        __err |= ios_base::eofbit;
 
  614      // Parse bool values as alphanumeric.
 
  615      typedef __numpunct_cache<_CharT>  __cache_type;
 
  616      __use_cache<__cache_type> __uc;
 
  617      const locale& __loc = __io._M_getloc();
 
  618      const __cache_type* __lc = __uc(__loc);
 
  622      bool __donef = __lc->_M_falsename_size == 0;
 
  623      bool __donet = __lc->_M_truename_size == 0;
 
  624      bool __testeof = false;
 
  626      while (!__donef || !__donet)
 
  634          const char_type __c = *__beg;
 
  637        __testf = __c == __lc->_M_falsename[__n];
 
  639          if (!__testf && __donet)
 
  643        __testt = __c == __lc->_M_truename[__n];
 
  645          if (!__testt && __donef)
 
  648          if (!__testt && !__testf)
 
  654          __donef = !__testf || __n >= __lc->_M_falsename_size;
 
  655          __donet = !__testt || __n >= __lc->_M_truename_size;
 
  657      if (__testf && __n == __lc->_M_falsename_size && __n)
 
  660          if (__testt && __n == __lc->_M_truename_size)
 
  661        __err = ios_base::failbit;
 
  663        __err = __testeof ? ios_base::eofbit : ios_base::goodbit;
 
  665      else if (__testt && __n == __lc->_M_truename_size && __n)
 
  668          __err = __testeof ? ios_base::eofbit : ios_base::goodbit;
 
  672          // _GLIBCXX_RESOLVE_LIB_DEFECTS
 
  673          // 23. Num_get overflow result.
 
  675          __err = ios_base::failbit;
 
  677        __err |= ios_base::eofbit;
 
  683   template<typename _CharT, typename _InIter>
 
  685     num_get<_CharT, _InIter>::
 
  686     do_get(iter_type __beg, iter_type __end, ios_base& __io,
 
  687       ios_base::iostate& __err, float& __v) const
 
  691       __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
 
  692       std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
 
  694    __err |= ios_base::eofbit;
 
  698   template<typename _CharT, typename _InIter>
 
  700     num_get<_CharT, _InIter>::
 
  701     do_get(iter_type __beg, iter_type __end, ios_base& __io,
 
  702            ios_base::iostate& __err, double& __v) const
 
  706       __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
 
  707       std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
 
  709    __err |= ios_base::eofbit;
 
  713 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
 
  714   template<typename _CharT, typename _InIter>
 
  716     num_get<_CharT, _InIter>::
 
  717     __do_get(iter_type __beg, iter_type __end, ios_base& __io,
 
  718         ios_base::iostate& __err, double& __v) const
 
  722       __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
 
  723       std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
 
  725    __err |= ios_base::eofbit;
 
  730   template<typename _CharT, typename _InIter>
 
  732     num_get<_CharT, _InIter>::
 
  733     do_get(iter_type __beg, iter_type __end, ios_base& __io,
 
  734            ios_base::iostate& __err, long double& __v) const
 
  738       __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
 
  739       std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
 
  741    __err |= ios_base::eofbit;
 
  745   template<typename _CharT, typename _InIter>
 
  747     num_get<_CharT, _InIter>::
 
  748     do_get(iter_type __beg, iter_type __end, ios_base& __io,
 
  749            ios_base::iostate& __err, void*& __v) const
 
  751       // Prepare for hex formatted input.
 
  752       typedef ios_base::fmtflags        fmtflags;
 
  753       const fmtflags __fmt = __io.flags();
 
  754       __io.flags((__fmt & ~ios_base::basefield) | ios_base::hex);
 
  756       typedef __gnu_cxx::__conditional_type<(sizeof(void*)
 
  757                         <= sizeof(unsigned long)),
 
  758    unsigned long, unsigned long long>::__type _UIntPtrType;       
 
  761       __beg = _M_extract_int(__beg, __end, __io, __err, __ul);
 
  763       // Reset from hex formatted input.
 
  766       __v = reinterpret_cast<void*>(__ul);
 
  770   // For use by integer and floating-point types after they have been
 
  771   // converted into a char_type string.
 
  772   template<typename _CharT, typename _OutIter>
 
  774     num_put<_CharT, _OutIter>::
 
  775     _M_pad(_CharT __fill, streamsize __w, ios_base& __io,
 
  776       _CharT* __new, const _CharT* __cs, int& __len) const
 
  778       // [22.2.2.2.2] Stage 3.
 
  779       // If necessary, pad.
 
  780       __pad<_CharT, char_traits<_CharT> >::_S_pad(__io, __fill, __new,
 
  782       __len = static_cast<int>(__w);
 
  785 _GLIBCXX_END_NAMESPACE_LDBL
 
  787   template<typename _CharT, typename _ValueT>
 
  789     __int_to_char(_CharT* __bufend, _ValueT __v, const _CharT* __lit,
 
  790          ios_base::fmtflags __flags, bool __dec)
 
  792       _CharT* __buf = __bufend;
 
  793       if (__builtin_expect(__dec, true))
 
  798          *--__buf = __lit[(__v % 10) + __num_base::_S_odigits];
 
  803       else if ((__flags & ios_base::basefield) == ios_base::oct)
 
  808          *--__buf = __lit[(__v & 0x7) + __num_base::_S_odigits];
 
  816      const bool __uppercase = __flags & ios_base::uppercase;
 
  817      const int __case_offset = __uppercase ? __num_base::_S_oudigits
 
  818                                            : __num_base::_S_odigits;
 
  821          *--__buf = __lit[(__v & 0xf) + __case_offset];
 
  826       return __bufend - __buf;
 
  829 _GLIBCXX_BEGIN_NAMESPACE_LDBL
 
  831   template<typename _CharT, typename _OutIter>
 
  833     num_put<_CharT, _OutIter>::
 
  834     _M_group_int(const char* __grouping, size_t __grouping_size, _CharT __sep,
 
  835         ios_base&, _CharT* __new, _CharT* __cs, int& __len) const
 
  837       _CharT* __p = std::__add_grouping(__new, __sep, __grouping,
 
  838                    __grouping_size, __cs, __cs + __len);
 
  842   template<typename _CharT, typename _OutIter>
 
  843     template<typename _ValueT>
 
  845       num_put<_CharT, _OutIter>::
 
  846       _M_insert_int(_OutIter __s, ios_base& __io, _CharT __fill,
 
  849    using __gnu_cxx::__add_unsigned;
 
  850    typedef typename __add_unsigned<_ValueT>::__type __unsigned_type;
 
  851    typedef __numpunct_cache<_CharT>                 __cache_type;
 
  852    __use_cache<__cache_type> __uc;
 
  853    const locale& __loc = __io._M_getloc();
 
  854    const __cache_type* __lc = __uc(__loc);
 
  855    const _CharT* __lit = __lc->_M_atoms_out;
 
  856    const ios_base::fmtflags __flags = __io.flags();
 
  858    // Long enough to hold hex, dec, and octal representations.
 
  859    const int __ilen = 5 * sizeof(_ValueT);
 
  860    _CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
 
  863    // [22.2.2.2.2] Stage 1, numeric conversion to character.
 
  864    // Result is returned right-justified in the buffer.
 
  865    const ios_base::fmtflags __basefield = __flags & ios_base::basefield;
 
  866    const bool __dec = (__basefield != ios_base::oct
 
  867                && __basefield != ios_base::hex);
 
  868    const __unsigned_type __u = ((__v > 0 || !__dec)
 
  869                     ? __unsigned_type(__v)
 
  870                     : -__unsigned_type(__v));
 
  871    int __len = __int_to_char(__cs + __ilen, __u, __lit, __flags, __dec);
 
  872    __cs += __ilen - __len;
 
  874    // Add grouping, if necessary.
 
  875    if (__lc->_M_use_grouping)
 
  877        // Grouping can add (almost) as many separators as the number
 
  878        // of digits + space is reserved for numeric base or sign.
 
  879        _CharT* __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
 
  882        _M_group_int(__lc->_M_grouping, __lc->_M_grouping_size,
 
  883             __lc->_M_thousands_sep, __io, __cs2 + 2, __cs, __len);
 
  887    // Complete Stage 1, prepend numeric base or sign.
 
  888    if (__builtin_expect(__dec, true))
 
  893        if (bool(__flags & ios_base::showpos)
 
  894            && __gnu_cxx::__numeric_traits<_ValueT>::__is_signed)
 
  895          *--__cs = __lit[__num_base::_S_oplus], ++__len;
 
  898          *--__cs = __lit[__num_base::_S_ominus], ++__len;
 
  900    else if (bool(__flags & ios_base::showbase) && __v)
 
  902        if (__basefield == ios_base::oct)
 
  903          *--__cs = __lit[__num_base::_S_odigits], ++__len;
 
  907        const bool __uppercase = __flags & ios_base::uppercase;
 
  908        *--__cs = __lit[__num_base::_S_ox + __uppercase];
 
  910        *--__cs = __lit[__num_base::_S_odigits];
 
  916    const streamsize __w = __io.width();
 
  917    if (__w > static_cast<streamsize>(__len))
 
  919        _CharT* __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
 
  921        _M_pad(__fill, __w, __io, __cs3, __cs, __len);
 
  926    // [22.2.2.2.2] Stage 4.
 
  927    // Write resulting, fully-formatted string to output iterator.
 
  928    return std::__write(__s, __cs, __len);
 
  931   template<typename _CharT, typename _OutIter>
 
  933     num_put<_CharT, _OutIter>::
 
  934     _M_group_float(const char* __grouping, size_t __grouping_size,
 
  935           _CharT __sep, const _CharT* __p, _CharT* __new,
 
  936           _CharT* __cs, int& __len) const
 
  938       // _GLIBCXX_RESOLVE_LIB_DEFECTS
 
  939       // 282. What types does numpunct grouping refer to?
 
  940       // Add grouping, if necessary.
 
  941       const int __declen = __p ? __p - __cs : __len;
 
  942       _CharT* __p2 = std::__add_grouping(__new, __sep, __grouping,
 
  944                     __cs, __cs + __declen);
 
  946       // Tack on decimal part.
 
  947       int __newlen = __p2 - __new;
 
  950      char_traits<_CharT>::copy(__p2, __p, __len - __declen);
 
  951      __newlen += __len - __declen;
 
  956   // The following code uses vsnprintf (or vsprintf(), when
 
  957   // _GLIBCXX_USE_C99 is not defined) to convert floating point values
 
  958   // for insertion into a stream.  An optimization would be to replace
 
  959   // them with code that works directly on a wide buffer and then use
 
  960   // __pad to do the padding.  It would be good to replace them anyway
 
  961   // to gain back the efficiency that C++ provides by knowing up front
 
  962   // the type of the values to insert.  Also, sprintf is dangerous
 
  963   // since may lead to accidental buffer overruns.  This
 
  964   // implementation follows the C++ standard fairly directly as
 
  965   // outlined in 22.2.2.2 [lib.locale.num.put]
 
  966   template<typename _CharT, typename _OutIter>
 
  967     template<typename _ValueT>
 
  969       num_put<_CharT, _OutIter>::
 
  970       _M_insert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
 
  973    typedef __numpunct_cache<_CharT>                __cache_type;
 
  974    __use_cache<__cache_type> __uc;
 
  975    const locale& __loc = __io._M_getloc();
 
  976    const __cache_type* __lc = __uc(__loc);
 
  978    // Use default precision if out of range.
 
  979    const streamsize __prec = __io.precision() < 0 ? 6 : __io.precision();
 
  981    const int __max_digits =
 
  982      __gnu_cxx::__numeric_traits<_ValueT>::__digits10;
 
  984    // [22.2.2.2.2] Stage 1, numeric conversion to character.
 
  986    // Long enough for the max format spec.
 
  988    __num_base::_S_format_float(__io, __fbuf, __mod);
 
  990 #ifdef _GLIBCXX_USE_C99
 
  991    // First try a buffer perhaps big enough (most probably sufficient
 
  992    // for non-ios_base::fixed outputs)
 
  993    int __cs_size = __max_digits * 3;
 
  994    char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
 
  995    __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
 
  996                      __fbuf, __prec, __v);
 
  998    // If the buffer was not large enough, try again with the correct size.
 
  999    if (__len >= __cs_size)
 
 1001        __cs_size = __len + 1;
 
 1002        __cs = static_cast<char*>(__builtin_alloca(__cs_size));
 
 1003        __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
 
 1004                      __fbuf, __prec, __v);
 
 1007    // Consider the possibility of long ios_base::fixed outputs
 
 1008    const bool __fixed = __io.flags() & ios_base::fixed;
 
 1009    const int __max_exp =
 
 1010      __gnu_cxx::__numeric_traits<_ValueT>::__max_exponent10;
 
 1012    // The size of the output string is computed as follows.
 
 1013    // ios_base::fixed outputs may need up to __max_exp + 1 chars
 
 1014    // for the integer part + __prec chars for the fractional part
 
 1015    // + 3 chars for sign, decimal point, '\0'. On the other hand,
 
 1016    // for non-fixed outputs __max_digits * 2 + __prec chars are
 
 1017    // largely sufficient.
 
 1018    const int __cs_size = __fixed ? __max_exp + __prec + 4
 
 1019                                  : __max_digits * 2 + __prec;
 
 1020    char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
 
 1021    __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, __fbuf, 
 
 1025    // [22.2.2.2.2] Stage 2, convert to char_type, using correct
 
 1026    // numpunct.decimal_point() values for '.' and adding grouping.
 
 1027    const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
 
 1029    _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
 
 1031    __ctype.widen(__cs, __cs + __len, __ws);
 
 1033    // Replace decimal point.
 
 1035    const char* __p = char_traits<char>::find(__cs, __len, '.');
 
 1038        __wp = __ws + (__p - __cs);
 
 1039        *__wp = __lc->_M_decimal_point;
 
 1042    // Add grouping, if necessary.
 
 1043    // N.B. Make sure to not group things like 2e20, i.e., no decimal
 
 1044    // point, scientific notation.
 
 1045    if (__lc->_M_use_grouping
 
 1046        && (__wp || __len < 3 || (__cs[1] <= '9' && __cs[2] <= '9'
 
 1047                      && __cs[1] >= '0' && __cs[2] >= '0')))
 
 1049        // Grouping can add (almost) as many separators as the
 
 1050        // number of digits, but no more.
 
 1051        _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
 
 1054        streamsize __off = 0;
 
 1055        if (__cs[0] == '-' || __cs[0] == '+')
 
 1062        _M_group_float(__lc->_M_grouping, __lc->_M_grouping_size,
 
 1063               __lc->_M_thousands_sep, __wp, __ws2 + __off,
 
 1064               __ws + __off, __len);
 
 1071    const streamsize __w = __io.width();
 
 1072    if (__w > static_cast<streamsize>(__len))
 
 1074        _CharT* __ws3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
 
 1076        _M_pad(__fill, __w, __io, __ws3, __ws, __len);
 
 1081    // [22.2.2.2.2] Stage 4.
 
 1082    // Write resulting, fully-formatted string to output iterator.
 
 1083    return std::__write(__s, __ws, __len);
 
 1086   template<typename _CharT, typename _OutIter>
 
 1088     num_put<_CharT, _OutIter>::
 
 1089     do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const
 
 1091       const ios_base::fmtflags __flags = __io.flags();
 
 1092       if ((__flags & ios_base::boolalpha) == 0)
 
 1094           const long __l = __v;
 
 1095           __s = _M_insert_int(__s, __io, __fill, __l);
 
 1099      typedef __numpunct_cache<_CharT>              __cache_type;
 
 1100      __use_cache<__cache_type> __uc;
 
 1101      const locale& __loc = __io._M_getloc();
 
 1102      const __cache_type* __lc = __uc(__loc);
 
 1104      const _CharT* __name = __v ? __lc->_M_truename
 
 1105                                 : __lc->_M_falsename;
 
 1106      int __len = __v ? __lc->_M_truename_size
 
 1107                      : __lc->_M_falsename_size;
 
 1109      const streamsize __w = __io.width();
 
 1110      if (__w > static_cast<streamsize>(__len))
 
 1112          const streamsize __plen = __w - __len;
 
 1114        = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
 
 1117          char_traits<_CharT>::assign(__ps, __plen, __fill);
 
 1120          if ((__flags & ios_base::adjustfield) == ios_base::left)
 
 1122          __s = std::__write(__s, __name, __len);
 
 1123          __s = std::__write(__s, __ps, __plen);
 
 1127          __s = std::__write(__s, __ps, __plen);
 
 1128          __s = std::__write(__s, __name, __len);
 
 1133      __s = std::__write(__s, __name, __len);
 
 1138   template<typename _CharT, typename _OutIter>
 
 1140     num_put<_CharT, _OutIter>::
 
 1141     do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
 
 1142     { return _M_insert_float(__s, __io, __fill, char(), __v); }
 
 1144 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
 
 1145   template<typename _CharT, typename _OutIter>
 
 1147     num_put<_CharT, _OutIter>::
 
 1148     __do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
 
 1149     { return _M_insert_float(__s, __io, __fill, char(), __v); }
 
 1152   template<typename _CharT, typename _OutIter>
 
 1154     num_put<_CharT, _OutIter>::
 
 1155     do_put(iter_type __s, ios_base& __io, char_type __fill,
 
 1156       long double __v) const
 
 1157     { return _M_insert_float(__s, __io, __fill, 'L', __v); }
 
 1159   template<typename _CharT, typename _OutIter>
 
 1161     num_put<_CharT, _OutIter>::
 
 1162     do_put(iter_type __s, ios_base& __io, char_type __fill,
 
 1163            const void* __v) const
 
 1165       const ios_base::fmtflags __flags = __io.flags();
 
 1166       const ios_base::fmtflags __fmt = ~(ios_base::basefield
 
 1167                     | ios_base::uppercase);
 
 1168       __io.flags((__flags & __fmt) | (ios_base::hex | ios_base::showbase));
 
 1170       typedef __gnu_cxx::__conditional_type<(sizeof(const void*)
 
 1171                         <= sizeof(unsigned long)),
 
 1172    unsigned long, unsigned long long>::__type _UIntPtrType;       
 
 1174       __s = _M_insert_int(__s, __io, __fill,
 
 1175              reinterpret_cast<_UIntPtrType>(__v));
 
 1176       __io.flags(__flags);
 
 1180 _GLIBCXX_END_NAMESPACE_LDBL
 
 1182   // Construct correctly padded string, as per 22.2.2.2.2
 
 1184   // __newlen > __oldlen
 
 1185   // __news is allocated for __newlen size
 
 1187   // NB: Of the two parameters, _CharT can be deduced from the
 
 1188   // function arguments. The other (_Traits) has to be explicitly specified.
 
 1189   template<typename _CharT, typename _Traits>
 
 1191     __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill,
 
 1192                   _CharT* __news, const _CharT* __olds,
 
 1193                   streamsize __newlen, streamsize __oldlen)
 
 1195       const size_t __plen = static_cast<size_t>(__newlen - __oldlen);
 
 1196       const ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield;
 
 1199       if (__adjust == ios_base::left)
 
 1201      _Traits::copy(__news, __olds, __oldlen);
 
 1202      _Traits::assign(__news + __oldlen, __plen, __fill);
 
 1207       if (__adjust == ios_base::internal)
 
 1209      // Pad after the sign, if there is one.
 
 1210      // Pad after 0[xX], if there is one.
 
 1211      // Who came up with these rules, anyway? Jeeze.
 
 1212           const locale& __loc = __io._M_getloc();
 
 1213      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
 
 1215      if (__ctype.widen('-') == __olds[0]
 
 1216          || __ctype.widen('+') == __olds[0])
 
 1218          __news[0] = __olds[0];
 
 1222      else if (__ctype.widen('0') == __olds[0]
 
 1224           && (__ctype.widen('x') == __olds[1]
 
 1225               || __ctype.widen('X') == __olds[1]))
 
 1227          __news[0] = __olds[0];
 
 1228          __news[1] = __olds[1];
 
 1232      // else Padding first.
 
 1234       _Traits::assign(__news, __plen, __fill);
 
 1235       _Traits::copy(__news + __plen, __olds + __mod, __oldlen - __mod);
 
 1238   template<typename _CharT>
 
 1240     __add_grouping(_CharT* __s, _CharT __sep,
 
 1241           const char* __gbeg, size_t __gsize,
 
 1242           const _CharT* __first, const _CharT* __last)
 
 1247       while (__last - __first > __gbeg[__idx]
 
 1248         && static_cast<signed char>(__gbeg[__idx]) > 0
 
 1249         && __gbeg[__idx] != __gnu_cxx::__numeric_traits<char>::__max)
 
 1251      __last -= __gbeg[__idx];
 
 1252      __idx < __gsize - 1 ? ++__idx : ++__ctr;
 
 1255       while (__first != __last)
 
 1256    *__s++ = *__first++;
 
 1261      for (char __i = __gbeg[__idx]; __i > 0; --__i)
 
 1262        *__s++ = *__first++;
 
 1268      for (char __i = __gbeg[__idx]; __i > 0; --__i)
 
 1269        *__s++ = *__first++;
 
 1275   // Inhibit implicit instantiations for required instantiations,
 
 1276   // which are defined via explicit instantiations elsewhere.
 
 1277 #if _GLIBCXX_EXTERN_TEMPLATE
 
 1278   extern template class numpunct<char>;
 
 1279   extern template class numpunct_byname<char>;
 
 1280   extern template class _GLIBCXX_NAMESPACE_LDBL num_get<char>;
 
 1281   extern template class _GLIBCXX_NAMESPACE_LDBL num_put<char>;
 
 1282   extern template class ctype_byname<char>;
 
 1286     use_facet<ctype<char> >(const locale&);
 
 1289     const numpunct<char>&
 
 1290     use_facet<numpunct<char> >(const locale&);
 
 1293     const num_put<char>&
 
 1294     use_facet<num_put<char> >(const locale&);
 
 1297     const num_get<char>&
 
 1298     use_facet<num_get<char> >(const locale&);
 
 1302     has_facet<ctype<char> >(const locale&);
 
 1306     has_facet<numpunct<char> >(const locale&);
 
 1310     has_facet<num_put<char> >(const locale&);
 
 1314     has_facet<num_get<char> >(const locale&);
 
 1316 #ifdef _GLIBCXX_USE_WCHAR_T
 
 1317   extern template class numpunct<wchar_t>;
 
 1318   extern template class numpunct_byname<wchar_t>;
 
 1319   extern template class _GLIBCXX_NAMESPACE_LDBL num_get<wchar_t>;
 
 1320   extern template class _GLIBCXX_NAMESPACE_LDBL num_put<wchar_t>;
 
 1321   extern template class ctype_byname<wchar_t>;
 
 1324     const ctype<wchar_t>&
 
 1325     use_facet<ctype<wchar_t> >(const locale&);
 
 1328     const numpunct<wchar_t>&
 
 1329     use_facet<numpunct<wchar_t> >(const locale&);
 
 1332     const num_put<wchar_t>&
 
 1333     use_facet<num_put<wchar_t> >(const locale&);
 
 1336     const num_get<wchar_t>&
 
 1337     use_facet<num_get<wchar_t> >(const locale&);
 
 1341     has_facet<ctype<wchar_t> >(const locale&);
 
 1345     has_facet<numpunct<wchar_t> >(const locale&);
 
 1349     has_facet<num_put<wchar_t> >(const locale&);
 
 1353     has_facet<num_get<wchar_t> >(const locale&);
 
 1357 _GLIBCXX_END_NAMESPACE_VERSION