OSDN Git Service

2001-08-17 Benjamin Kosnik <bkoz@redhat.com>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / src / locale.cc
1 // Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
2 //
3 // This file is part of the GNU ISO C++ Library.  This library is free
4 // software; you can redistribute it and/or modify it under the
5 // terms of the GNU General Public License as published by the
6 // Free Software Foundation; either version 2, or (at your option)
7 // any later version.
8
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13
14 // You should have received a copy of the GNU General Public License along
15 // with this library; see the file COPYING.  If not, write to the Free
16 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
17 // USA.
18
19 // As a special exception, you may use this file as part of a free software
20 // library without restriction.  Specifically, if other files instantiate
21 // templates or use macros or inline functions from this file, or you compile
22 // this file and link it with other files to produce an executable, this
23 // file does not by itself cause the resulting executable to be covered by
24 // the GNU General Public License.  This exception does not however
25 // invalidate any other reasons why the executable file might be covered by
26 // the GNU General Public License.
27
28 #include <bits/std_clocale.h>
29 #include <bits/std_cstring.h>
30 #include <bits/std_cassert.h>
31 #include <bits/std_cctype.h>
32 #include <bits/std_limits.h>
33 #include <exception>
34 #include <bits/std_stdexcept.h>
35 #include <bits/std_locale.h>
36 #include <bits/std_istream.h>
37 #include <bits/std_ostream.h>
38 #include <bits/std_vector.h>
39 #include <bits/std_memory.h>      // for auto_ptr
40 #ifdef _GLIBCPP_USE_WCHAR_T  
41 # include <bits/std_cwctype.h>     // for towupper, etc.
42 #endif
43
44 namespace std 
45 {
46   // Defined in globals.cc.
47   extern locale::_Impl locale_impl_c;
48   extern locale locale_c;
49
50   // Definitions for static const data members of locale.
51   const locale::category        locale::none;
52   const locale::category        locale::ctype;
53   const locale::category        locale::numeric;
54   const locale::category        locale::collate;
55   const locale::category        locale::time;
56   const locale::category        locale::monetary;
57   const locale::category        locale::messages;
58   const locale::category        locale::all;
59
60   locale::_Impl*                locale::_S_classic;
61   locale::_Impl*                locale::_S_global; 
62   const size_t                  locale::_S_num_categories;
63   const size_t                  locale::_S_num_facets;
64
65   // Definitions for locale::id of standard facets. 
66   locale::id ctype<char>::id;
67   locale::id codecvt<char, char, mbstate_t>::id;
68
69 #ifdef _GLIBCPP_USE_WCHAR_T  
70   locale::id ctype<wchar_t>::id;
71   locale::id codecvt<wchar_t, char, mbstate_t>::id;
72 #endif
73
74   // Definitions for static const data members of locale::id
75   size_t locale::id::_S_highwater;  // init'd to 0 by linker
76
77   // Definitions for static const data members of locale::_Impl
78   const locale::id* const
79   locale::_Impl::_S_id_ctype[] =
80   {
81     &std::ctype<char>::id, 
82     &codecvt<char, char, mbstate_t>::id,
83 #ifdef _GLIBCPP_USE_WCHAR_T
84     &std::ctype<wchar_t>::id,
85     &codecvt<wchar_t, char, mbstate_t>::id,
86 #endif
87     0
88   };
89
90   const locale::id* const
91   locale::_Impl::_S_id_numeric[] =
92   {
93     &num_get<char>::id,  
94     &num_put<char>::id,  
95     &numpunct<char>::id, 
96 #ifdef _GLIBCPP_USE_WCHAR_T
97     &num_get<wchar_t>::id,
98     &num_put<wchar_t>::id,
99     &numpunct<wchar_t>::id,
100 #endif
101     0
102   };
103   
104   const locale::id* const
105   locale::_Impl::_S_id_collate[] =
106   {
107     &std::collate<char>::id,
108 #ifdef _GLIBCPP_USE_WCHAR_T
109     &std::collate<wchar_t>::id,
110 #endif
111     0
112   };
113
114   const locale::id* const
115   locale::_Impl::_S_id_time[] =
116   {
117     &time_get<char>::id, 
118     &time_put<char>::id, 
119 #ifdef _GLIBCPP_USE_WCHAR_T
120     &time_get<wchar_t>::id,
121     &time_put<wchar_t>::id,
122 #endif
123     0
124   };
125   
126   const locale::id* const
127   locale::_Impl::_S_id_monetary[] =
128   {
129     &money_get<char>::id,        
130     &money_put<char>::id,        
131     &moneypunct<char, false>::id, 
132     &moneypunct<char, true >::id, 
133 #ifdef _GLIBCPP_USE_WCHAR_T
134     &money_get<wchar_t>::id,
135     &money_put<wchar_t>::id,
136     &moneypunct<wchar_t, false>::id,
137     &moneypunct<wchar_t, true >::id,
138 #endif
139     0
140   };
141
142   const locale::id* const
143   locale::_Impl::_S_id_messages[] =
144   {
145     &std::messages<char>::id, 
146 #ifdef _GLIBCPP_USE_WCHAR_T
147     &std::messages<wchar_t>::id,
148 #endif
149     0
150   };
151   
152   const locale::id* const* const
153   locale::_Impl::_S_facet_categories[] =
154   {
155     // Order must match the decl order in class locale.
156     locale::_Impl::_S_id_ctype,
157     locale::_Impl::_S_id_numeric,
158     locale::_Impl::_S_id_collate,
159     locale::_Impl::_S_id_time,
160     locale::_Impl::_S_id_monetary,
161     locale::_Impl::_S_id_messages,
162     0
163   };
164
165   // Construct and return valid pattern consisting of some combination of:
166   // space none symbol sign value
167   money_base::pattern
168   money_base::_S_construct_pattern(char __preceeds, char __space, char __posn)
169   { 
170     pattern __ret;
171
172     // This insanely complicated routine attempts to construct a valid
173     // pattern for use with monyepunct. A couple of invariants:
174
175     // if (__preceeds) symbol -> value
176     // else value -> symbol
177     
178     // if (__space) space
179     // else none
180
181     // none == never first
182     // space never first or last
183
184     // Any elegant implementations of this are welcome.
185     switch (__posn)
186       {
187       case 1:
188         // 1 The sign precedes the value and symbol.
189         if (__space)
190           {
191             // Pattern starts with sign.
192             if (__preceeds)
193               {
194                 __ret.field[1] = symbol;
195                 __ret.field[2] = space;
196                 __ret.field[3] = value;
197               }
198             else
199               {
200                 __ret.field[1] = value;
201                 __ret.field[2] = space;
202                 __ret.field[3] = symbol;
203               }
204             __ret.field[0] = sign;
205           }
206         else
207           {
208             // Pattern starts with sign and ends with none.
209             if (__preceeds)
210               {
211                 __ret.field[1] = symbol;
212                 __ret.field[2] = value;
213               }
214             else
215               {
216                 __ret.field[1] = value;
217                 __ret.field[2] = symbol;
218               }
219             __ret.field[0] = sign;
220             __ret.field[3] = none;
221           }
222         break;
223       case 2:
224         // 2 The sign follows the value and symbol.
225         if (__space)
226           {
227             // Pattern either ends with sign.
228             if (__preceeds)
229               {
230                 __ret.field[0] = symbol;
231                 __ret.field[1] = space;
232                 __ret.field[2] = value;
233               }
234             else
235               {
236                 __ret.field[0] = value;
237                 __ret.field[1] = space;
238                 __ret.field[2] = symbol;
239               }
240             __ret.field[3] = sign;
241           }
242         else
243           {
244             // Pattern ends with sign then none.
245             if (__preceeds)
246               {
247                 __ret.field[0] = symbol;
248                 __ret.field[1] = value;
249               }
250             else
251               {
252                 __ret.field[0] = value;
253                 __ret.field[1] = symbol;
254               }
255             __ret.field[2] = sign;
256             __ret.field[3] = none;
257           }
258         break;
259       case 3:
260         // 3 The sign immediately precedes the symbol.
261         if (__space)
262           {
263             // Have space.
264             if (__preceeds)
265               {
266                 __ret.field[0] = sign;
267                 __ret.field[1] = symbol;
268                 __ret.field[2] = space;
269                 __ret.field[3] = value;
270               }
271             else
272               {
273                 __ret.field[0] = value;
274                 __ret.field[1] = space;
275                 __ret.field[2] = sign;
276                 __ret.field[3] = symbol;
277               }
278           }
279         else
280           {
281             // Have none.
282             if (__preceeds)
283               {
284                 __ret.field[0] = sign;
285                 __ret.field[1] = symbol;
286                 __ret.field[2] = value;
287               }
288             else
289               {
290                 __ret.field[0] = value;
291                 __ret.field[1] = sign;
292                 __ret.field[2] = symbol;
293               }
294             __ret.field[3] = none;
295           }
296         break;
297       case 4:
298         // 4 The sign immediately follows the symbol. 
299         if (__space)
300           {
301             // Have space.
302             if (__preceeds)
303               {
304                 __ret.field[0] = symbol;
305                 __ret.field[1] = sign;
306                 __ret.field[2] = space;
307                 __ret.field[3] = value;
308               }
309             else
310               {
311                 __ret.field[0] = value;
312                 __ret.field[1] = space;
313                 __ret.field[2] = symbol;
314                 __ret.field[3] = sign;
315               }
316           }
317         else
318           {
319             // Have none.
320             if (__preceeds)
321               {
322                 __ret.field[0] = symbol;
323                 __ret.field[1] = sign;
324                 __ret.field[2] = value;
325               }
326             else
327               {
328                 __ret.field[0] = value;
329                 __ret.field[1] = symbol;
330                 __ret.field[2] = sign;
331               }
332             __ret.field[3] = none;
333           }
334         break;
335       default:
336         ;
337       }
338     return __ret;
339   }
340
341   locale::~locale() throw()
342   { _M_impl->_M_remove_reference(); }
343
344   void
345   locale::_M_coalesce(const locale& __base, const locale& __add, 
346                       category __cat)
347   {
348     __cat = _S_normalize_category(__cat);  
349     _M_impl = new _Impl(*__base._M_impl, 1);  
350
351     try 
352       { _M_impl->_M_replace_categories(__add._M_impl, __cat); }
353     catch (...) 
354       { 
355         _M_impl->_M_remove_reference(); 
356         __throw_exception_again;
357       }
358   }
359
360   locale::locale() throw()
361   { 
362     _S_initialize(); 
363     (_M_impl = _S_global)->_M_add_reference(); 
364   } // XXX MT
365
366   locale::locale(const locale& __other) throw()
367   { (_M_impl = __other._M_impl)->_M_add_reference(); }
368
369   // This is used to initialize global and classic locales, and
370   // assumes that the _Impl objects are constructed correctly.
371   locale::locale(_Impl* __ip) throw() : _M_impl(__ip)
372   { }
373
374   locale::locale(const char* __s)
375   {
376     if (__s)
377       {
378         _S_initialize(); 
379         if (strcmp(__s, "C") == 0 || strcmp(__s, "POSIX") == 0)
380           (_M_impl = _S_classic)->_M_add_reference();
381         else
382           _M_impl = new _Impl(__s, 1);
383       }
384     else
385       __throw_runtime_error("attempt to create locale from NULL name");
386   }
387
388   locale::locale(const locale& __base, const char* __s, category __cat)
389   { 
390     // NB: There are complicated, yet more efficient ways to do
391     // this. Building up locales on a per-category way is tedious, so
392     // let's do it this way until people complain.
393     locale __add(__s);
394     _M_coalesce(__base, __add, __cat);
395   }
396
397   locale::locale(const locale& __base, const locale& __add, category __cat)
398   { _M_coalesce(__base, __add, __cat); }
399
400   bool
401   locale::operator==(const locale& __rhs) const throw()
402   {
403     string __name = this->name();
404     return (_M_impl == __rhs._M_impl 
405             || (__name != "*" && __name == __rhs.name()));
406   }
407
408   const locale&
409   locale::operator=(const locale& __other) throw()
410   {
411     __other._M_impl->_M_add_reference();
412     _M_impl->_M_remove_reference();
413     _M_impl = __other._M_impl;
414     return *this;
415   }
416
417   locale
418   locale::global(const locale& __other)
419   {
420     // XXX MT
421     _S_initialize();
422     _Impl* __old = _S_global;
423     __other._M_impl->_M_add_reference();
424     _S_global = __other._M_impl; 
425     if (_S_global->_M_check_same_name() && _S_global->_M_names[0] != "*")
426       setlocale(LC_ALL, __other.name().c_str());
427
428     // Reference count sanity check: one reference removed for the
429     // subsition of __other locale, one added by return-by-value. Net
430     // difference: zero. When the returned locale object's destrutor
431     // is called, then the reference count is decremented and possibly
432     // destroyed.
433     return locale(__old);
434   }
435
436   string
437   locale::name() const
438   {
439     string __ret;
440     // Need some kind of separator character. This one was pretty much
441     // arbitrarily chosen as to not conflict with glibc locales: the
442     // exact formatting is not set in stone.
443     const char __separator = '|';
444
445     if (_M_impl->_M_check_same_name())
446       __ret = _M_impl->_M_names[0];
447     else
448       {
449         for (size_t i = 0; i < _S_num_categories; ++i)
450           __ret += __separator + _M_impl->_M_names[i];
451       }
452     return __ret;
453   }
454
455   locale const&
456   locale::classic()
457   {
458     // XXX MT
459     if (!_S_classic)
460       {
461         try 
462           {
463             // 26 Standard facets, 2 references.
464             // One reference for _M_classic, one for _M_global
465             _S_classic = new (&locale_impl_c) _Impl("C", 2);
466             _S_global = _S_classic;         
467             new (&locale_c) locale(_S_classic);
468           }
469         catch(...) 
470           {
471             // Just call destructor, so that locale_impl_c's memory is
472             // not deallocated via a call to delete.
473             if (_S_classic)
474               _S_classic->~_Impl();
475             _S_classic = _S_global = 0;
476             __throw_exception_again;
477           }
478       }
479     return locale_c;
480   }
481
482   locale::category
483   locale::_S_normalize_category(category __cat) 
484   {
485     int __ret = 0;
486     if (__cat == none || (__cat & all) && !(__cat & ~all))
487       __ret = __cat;
488     else
489       {
490         // NB: May be a C-style "LC_ALL" category; convert.
491         switch (__cat)
492           {
493           case LC_COLLATE:  
494             __ret = collate; 
495             break;
496           case LC_CTYPE:    
497             __ret = ctype;
498             break;
499           case LC_MONETARY: 
500             __ret = monetary;
501             break;
502           case LC_NUMERIC:  
503             __ret = numeric;
504             break;
505           case LC_TIME:     
506             __ret = time; 
507             break;
508 #ifdef _GLIBCPP_HAVE_LC_MESSAGES
509           case LC_MESSAGES: 
510             __ret = messages;
511             break;
512 #endif  
513           case LC_ALL:      
514             __ret = all;
515             break;
516           default:
517             __throw_runtime_error("bad locale category");
518           }
519       }
520     return __ret;
521   }
522
523   locale::facet::
524   facet(size_t __refs) throw() : _M_references(__refs) 
525   { }
526
527   void  
528   locale::facet::
529   _M_add_reference() throw()
530   { ++_M_references; }                     // XXX MT
531
532   void  
533   locale::facet::
534   _M_remove_reference() throw()
535   {
536     if (_M_references-- == 0)
537       {
538         try 
539           { delete this; }  
540         catch (...) 
541           { }
542       }
543   }
544   
545   // Definitions for static const data members of ctype_base.
546   const ctype_base::mask ctype_base::space;
547   const ctype_base::mask ctype_base::print;
548   const ctype_base::mask ctype_base::cntrl;
549   const ctype_base::mask ctype_base::upper;
550   const ctype_base::mask ctype_base::lower;
551   const ctype_base::mask ctype_base::alpha;
552   const ctype_base::mask ctype_base::digit;
553   const ctype_base::mask ctype_base::punct;
554   const ctype_base::mask ctype_base::xdigit;
555   const ctype_base::mask ctype_base::alnum;
556   const ctype_base::mask ctype_base::graph;
557
558   // Platform-specific initialization code for ctype tables.
559   #include <bits/ctype_noninline.h>
560
561   const size_t ctype<char>::table_size;
562
563   ctype<char>::~ctype()
564   { if (_M_del) delete[] this->table(); }
565
566   // These are dummy placeholders as these virtual functions are never called.
567   bool 
568   ctype<char>::do_is(mask, char_type) const 
569   { return false; }
570   
571   const char*
572   ctype<char>::do_is(const char_type* __c, const char_type*, mask*) const 
573   { return __c; }
574   
575   const char*
576   ctype<char>::do_scan_is(mask, const char_type* __c, const char_type*) const 
577   { return __c; }
578
579   const char* 
580   ctype<char>::do_scan_not(mask, const char_type* __c, const char_type*) const
581   { return __c; }
582
583   char
584   ctype<char>::do_widen(char __c) const
585   { return __c; }
586   
587   const char* 
588   ctype<char>::do_widen(const char* __lo, const char* __hi, char* __dest) const
589   {
590     memcpy(__dest, __lo, __hi - __lo);
591     return __hi;
592   }
593   
594   char
595   ctype<char>::do_narrow(char __c, char /*__dfault*/) const
596   { return __c; }
597   
598   const char* 
599   ctype<char>::do_narrow(const char* __lo, const char* __hi, 
600                          char /*__dfault*/, char* __dest) const
601   {
602     memcpy(__dest, __lo, __hi - __lo);
603     return __hi;
604   }
605
606   template<>
607   ctype_byname<char>::ctype_byname(const char* /*__s*/, size_t __refs)
608   : ctype<char>(new mask[table_size], true, __refs)
609   { }
610
611   // Definitions for static const data members of money_base
612   const money_base::pattern 
613   money_base::_S_default_pattern =  {{symbol, sign, none, value}};
614
615   template<>
616     _Format_cache<char>::_Format_cache()
617     : _M_valid(true),
618     _M_decimal_point('.'), _M_thousands_sep(','),
619     _M_truename("true"), _M_falsename("false"), _M_use_grouping(false)
620     { }
621
622 #ifdef _GLIBCPP_USE_WCHAR_T
623   template<>
624     _Format_cache<wchar_t>::_Format_cache()
625     : _M_valid(true),
626     _M_decimal_point(L'.'), _M_thousands_sep(L','),
627     _M_truename(L"true"), _M_falsename(L"false"), _M_use_grouping(false)
628     { }
629 #endif
630
631   template<>
632     const ctype<char>&
633     use_facet<ctype<char> >(const locale& __loc)
634     {
635       size_t __i = ctype<char>::id._M_index;
636       const locale::_Impl* __tmp = __loc._M_impl;
637       return static_cast<const ctype<char>&>(* (*(__tmp->_M_facets))[__i]);
638     }
639
640 #ifdef _GLIBCPP_USE_WCHAR_T
641   template<>
642     const ctype<wchar_t>&
643     use_facet<ctype<wchar_t> >(const locale& __loc)
644     {
645       size_t __i = ctype<wchar_t>::id._M_index;
646       const locale::_Impl* __tmp = __loc._M_impl;
647       return static_cast<const ctype<wchar_t>&>(* (*(__tmp->_M_facets))[__i]);
648     }
649 #endif
650
651   template<>
652     void
653     num_get<char, istreambuf_iterator<char> >::
654     _M_extract(istreambuf_iterator<char> __beg, 
655                istreambuf_iterator<char> __end, ios_base& __io, 
656                ios_base::iostate& __err, char* __xtrc, int& __base, 
657                bool __fp) const
658     {
659       typedef _Format_cache<char> __cache_type; 
660
661       // Prepare for possible failure
662       __xtrc[0] = '\0';
663
664       // Stage 1: determine a conversion specifier.
665       ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
666       if (__basefield == ios_base::dec)
667         __base = 10;
668       else if (__basefield == ios_base::oct)
669         __base = 8;
670       else if (__basefield == ios_base::hex)
671         __base = 16;
672       else
673         __base = 0;
674       // As far as I can tell, bases other than 10 are not available for
675       // floating point types
676       if (__fp)
677         __base = 10;
678
679       // Stage 2: extract characters.
680       __cache_type const* __fmt = __cache_type::_S_get(__io);
681
682       // Fail quickly if !__valid
683       if (__beg == __end)
684         {
685           __err |= (ios_base::eofbit | ios_base::failbit);
686           return;
687         }
688
689       // Acceptable formats for numbers here are based on 22.2.3.1
690       string __grp;
691       int __sep_pos = 0;
692       int __pos = 0;
693       const char* __lits = __fmt->_S_literals;
694       char __c = *__beg;
695
696       // Check first for sign
697       bool __testsign = false;
698       if ((__c == __lits[__cache_type::_S_minus])
699           || (__c == __lits[__cache_type::_S_plus]))
700         {
701           __testsign = true;
702           __xtrc[__pos++] = __c;
703           ++__beg;
704           __c = * __beg;
705
706           // Whitespace may follow a sign
707           while ((__beg != __end) && (isspace(__c)))
708             {
709               ++__beg;
710               __c = *__beg;
711             }
712
713           // There had better be more to come...
714           if (__beg == __end)
715             {
716               __xtrc[__pos] = '\0';
717               __err |= (ios_base::eofbit | ios_base::failbit);
718               return;
719             }
720         }
721
722       // Now check if first character is a zero.
723       bool __testzero = false;    
724       if (__c == __lits[__cache_type::_S_digits])
725         {
726            __testzero = true;
727            ++__beg;
728            __c = *__beg;
729
730            // We have to check for __beg == __end here. If so,
731            // a plain '0' (possibly with a sign) can be got rid of now
732            if (__beg == __end)
733              {
734                __xtrc[__pos++] = __lits[__cache_type::_S_digits];
735                __xtrc[__pos] = '\0';
736                __err |= ios_base::eofbit;
737                return;
738              }
739
740           // Figure out base for integer types only
741           // Based on Table 55 of 22.2.2.1.2
742           if (!__fp && __base != 10 && __base != 8)
743             {
744               // Here, __base == 0 or 16
745               if ((__c == __lits[__cache_type::_S_x])
746                  || (__c == __lits[__cache_type::_S_X]))
747                 {
748                   ++__beg;
749                   __c = *__beg;
750                   __base = 16;
751                   __testzero = false; // "0x" is not a leading zero
752                 }
753               else if (__base == 0)
754                 __base = 8;
755             }
756
757           // Remove any more leading zeros
758           while (__beg != __end)
759             {
760               if (__c == __lits[__cache_type::_S_digits])
761                 {
762                   ++__beg;
763                   __c = *__beg;
764                   __testzero = true;
765                 }
766               else
767                 break;
768             }
769         }
770       else if (__base == 0) // 1st character is not zero
771         __base = 10;
772
773       // We now seek "units", i.e. digits and thousands separators.
774       // We may need to know if anything is found here. A leading zero
775       // (removed by now) would count.
776       bool __testunits = __testzero;
777       while (__beg != __end)
778         {
779           const char* __p = strchr(__lits, __c);
780
781           // NB: strchr returns true for __c == 0x0
782           if (__p && __c
783               &&((__p >= &__lits[__cache_type::_S_digits]
784                   && __p < &__lits[__cache_type::_S_digits + __base])
785                  || (__p >= &__lits[__cache_type::_S_udigits]
786                      && __p < &__lits[__cache_type::_S_udigits + __base])))
787             {
788               // Try first for acceptable digit; record it if found.
789               __xtrc[__pos++] = __c;
790               ++__sep_pos;
791               __testunits = true;
792               ++__beg;
793               __c = *__beg;
794             }
795           else if (__c == __fmt->_M_thousands_sep && __fmt->_M_use_grouping)
796             {
797               // NB: Thousands separator at the beginning of a string
798               // is a no-no, as is two consecutive thousands
799               // separators.
800               if (__sep_pos)
801                 {
802                   __grp += static_cast<char>(__sep_pos);
803                   __sep_pos = 0;
804                   ++__beg;
805                   __c = *__beg;
806                 }
807               else
808                 {
809                   __err |= ios_base::failbit;
810                   break;
811                 }
812             }
813           else
814             // Not a valid input item.
815             break;
816         }
817
818       // Digit grouping is checked. If _M_groupings() doesn't
819       // match, then get very very upset, and set failbit.
820       if (__fmt->_M_use_grouping && !__grp.empty())
821         {
822           // Add the ending grouping
823           __grp += static_cast<char>(__sep_pos);
824
825           // __grp is parsed L to R
826           // 1,222,444 == __grp of "/1/3/3"
827           // __fmt->_M_grouping is parsed R to L
828           // 1,222,444 == __fmt->_M_grouping of "/3" == "/3/3/3"
829           int __i = 0;
830           int __j = 0;
831           const int __len = __fmt->_M_grouping.size();
832           int __n = __grp.size();
833           bool __test = true;
834
835           // Parsed number groupings have to match the
836           // numpunct::grouping string exactly, starting at the
837           // right-most point of the parsed sequence of elements ...
838           while (__test && __i < __n - 1)
839             for (__j = 0; __test && __j < __len && __i < __n - 1; ++__j,++__i)
840               __test &= __fmt->_M_grouping[__j] == __grp[__n - __i - 1];
841           // ... but the last parsed grouping can be <= numpunct
842           // grouping.
843           __j == __len ? __j = 0 : __j;
844           __test &= __fmt->_M_grouping[__j] >= __grp[__n - __i - 1];
845
846           if (!__test)
847             {
848               __err |= ios_base::failbit;
849               __xtrc[__pos] = '\0';
850               if (__beg == __end)
851                 __err |= ios_base::eofbit;
852               return;
853             }
854         }
855
856       // If there was nothing but zeros, put one in the output string
857       if (__testzero && (__pos == 0 || (__pos == 1 && __testsign)))
858         __xtrc[__pos++] = __lits[__cache_type::_S_digits];
859
860       // That's it for integer types. Remaining code is for floating point
861       if (__fp && __beg != __end)
862         {
863           // Check first for decimal point. There MUST be one if
864           // __testunits is false.
865           bool __testdec = false;    // Is there a decimal point
866                                      // with digits following it?
867           if (__c == __fmt->_M_decimal_point)
868             {
869               __xtrc[__pos++] = '.';
870               ++__beg;
871               __c = *__beg;
872
873               // Now we get any digits after the decimal point
874               // There MUST be some if __testunits is false.
875               while (__beg != __end)
876                 {
877                   const char* __p = strchr(__lits, __c);
878                   if ((__p >= &__lits[__cache_type::_S_digits]
879                         && __p < &__lits[__cache_type::_S_digits + __base])
880                        || (__p >= &__lits[__cache_type::_S_udigits]
881                            && __p < &__lits[__cache_type::_S_udigits + __base]))
882                     {
883                       __xtrc[__pos++] = __c;
884                       ++__beg;
885                       __c = *__beg;
886                       __testdec = true;
887                     }
888                   else
889                     break;
890                 }
891             }
892           if (!__testunits && !__testdec) // Ill formed
893             {
894               __err |= ios_base::failbit;
895               __xtrc[__pos] = '\0';
896               if (__beg == __end)
897                 __err |= ios_base::eofbit;
898               return;
899             }
900
901           // Now we may find an exponent
902           if (__beg != __end)
903             {
904               if ((__c == __lits[__cache_type::_S_ee])
905                    || (__c == __lits[__cache_type::_S_Ee]))
906                 {
907                   __xtrc[__pos++] = __c;
908                   ++__beg;
909                   __c = *__beg;
910
911                   // Now there may be a sign
912                   if (__beg != __end)
913                     {
914                       if ((__c == __lits[__cache_type::_S_minus])
915                           || (__c == __lits[__cache_type::_S_plus]))
916                         {
917                           __xtrc[__pos++] = __c;
918                           ++__beg;
919                           __c = *__beg;
920                           // whitespace may follow a sign
921                           while ((__beg != __end) && (isspace(__c)))
922                             {
923                               ++__beg;
924                               __c = *__beg;
925                             }
926                         }
927                     }
928                   // And now there must be some digits
929                   if (__beg == __end)
930                     {
931                       __xtrc[__pos] = '\0';
932                       __err |= (ios_base::eofbit | ios_base::failbit);
933                       return;
934                     }
935                   while (__beg != __end)
936                     {
937                       const char* __p = strchr(__lits, __c);
938                       if ((__p >= &__lits[__cache_type::_S_digits]
939                             && __p < &__lits[__cache_type::_S_digits + __base])
940                            || (__p >= &__lits[__cache_type::_S_udigits]
941                                && __p < &__lits[__cache_type::_S_udigits + __base]))
942                         {
943                           __xtrc[__pos++] = __c;
944                           ++__beg;
945                           __c = *__beg;
946                         }
947                       else
948                         break;
949                     }
950                 }
951             }
952           // Finally, that's it for floating point
953         }
954
955       // Finish up
956       __xtrc[__pos] = '\0';
957       if (__beg == __end)
958         __err |= ios_base::eofbit;
959     }
960
961   // The following code uses sprintf() to convert floating point
962   // values for insertion into a stream. The current implementation
963   // replicates the code in _S_pad_numeric() (in _S_output_float()) in
964   // order to prevent having to create a "wide" buffer in addition to
965   // the "narrow" buffer passed to sprintf(). An optimization would be
966   // to replace sprintf() with code that works directly on a wide
967   // buffer and then use _S_pad_numeric() to do the padding. It would
968   // be good to replace sprintf() anyway to avoid accidental buffer
969   // overruns and to gain back the efficiency that C++ provides by
970   // knowing up front the type of the values to insert. This
971   // implementation follows the C++ standard fairly directly as
972   // outlined in 22.2.2.2 [lib.locale.num.put]
973   bool
974   __build_float_format(ios_base& __io, char* __fptr, char __modifier,
975                        streamsize __prec)
976   {
977     bool __incl_prec = false;
978     ios_base::fmtflags __flags = __io.flags();
979     *__fptr++ = '%';
980     // [22.2.2.2.2] Table 60
981     if (__flags & ios_base::showpos)
982       *__fptr++ = '+';
983     if (__flags & ios_base::showpoint)
984       *__fptr++ = '#';
985     // As per [22.2.2.2.2.11]
986     if (__flags & ios_base::fixed || __prec > 0)
987       {
988         *__fptr++ = '.';
989         *__fptr++ = '*';
990         __incl_prec = true;
991       }
992     if (__modifier)
993       *__fptr++ = __modifier;
994     ios_base::fmtflags __fltfield = __flags & ios_base::floatfield;
995     // [22.2.2.2.2] Table 58
996     if (__fltfield == ios_base::fixed)
997       *__fptr++ = 'f';
998     else if (__fltfield == ios_base::scientific)
999       *__fptr++ = (__flags & ios_base::uppercase) ? 'E' : 'e';
1000     else
1001       *__fptr++ = (__flags & ios_base::uppercase) ? 'G' : 'g';
1002     *__fptr = '\0';
1003     return __incl_prec;
1004   }
1005
1006   template<>
1007   moneypunct_byname<char, false>::moneypunct_byname(const char* /*__s*/, 
1008                                                     size_t __refs)
1009   : moneypunct<char, false>(__refs) { }
1010   
1011   template<>
1012   moneypunct_byname<char, true>::moneypunct_byname(const char* /*__s*/, 
1013                                                    size_t __refs)
1014   : moneypunct<char, true>(__refs) { }
1015   
1016 #ifdef _GLIBCPP_USE_WCHAR_T  
1017   ctype<wchar_t>::__wmask_type
1018   ctype<wchar_t>::_M_convert_to_wmask(const mask __m) const
1019   {
1020     __wmask_type __ret;
1021     switch (__m)
1022       {
1023       case space:
1024         __ret = wctype("space");
1025         break;
1026       case print:
1027         __ret = wctype("print");
1028         break;
1029       case cntrl:
1030         __ret = wctype("cntrl");
1031         break;
1032       case upper:
1033         __ret = wctype("upper");
1034         break;
1035       case lower:
1036         __ret = wctype("lower");
1037         break;
1038       case alpha:
1039         __ret = wctype("alpha");
1040         break;
1041       case digit:
1042         __ret = wctype("digit");
1043         break;
1044       case punct:
1045         __ret = wctype("punct");
1046         break;
1047       case xdigit:
1048         __ret = wctype("xdigit");
1049         break;
1050       case alnum:
1051         __ret = wctype("alnum");
1052         break;
1053       case graph:
1054         __ret = wctype("graph");
1055         break;
1056       default:
1057         __ret = 0;
1058       }
1059     return __ret;
1060   };
1061   
1062   ctype<wchar_t>::~ctype() { }
1063
1064   // NB: These ctype<wchar_t> methods are not configuration-specific,
1065   // unlike the ctype<char> bits.
1066   ctype<wchar_t>::ctype(size_t __refs) : __ctype_abstract_base<wchar_t>(__refs)
1067   { }
1068
1069   wchar_t
1070   ctype<wchar_t>::do_toupper(wchar_t __c) const
1071   { return towupper(__c); }
1072
1073   const wchar_t*
1074   ctype<wchar_t>::do_toupper(wchar_t* __lo, const wchar_t* __hi) const
1075   {
1076     while (__lo < __hi)
1077       {
1078         *__lo = towupper(*__lo);
1079         ++__lo;
1080       }
1081     return __hi;
1082   }
1083   
1084   wchar_t
1085   ctype<wchar_t>::do_tolower(wchar_t __c) const
1086   { return towlower(__c); }
1087   
1088   const wchar_t*
1089   ctype<wchar_t>::do_tolower(wchar_t* __lo, const wchar_t* __hi) const
1090   {
1091     while (__lo < __hi)
1092       {
1093         *__lo = towlower(*__lo);
1094         ++__lo;
1095       }
1096     return __hi;
1097   }
1098
1099   bool
1100   ctype<wchar_t>::
1101   do_is(mask __m, char_type __c) const
1102   { return static_cast<bool>(iswctype(__c, _M_convert_to_wmask(__m))); }
1103   
1104   const wchar_t* 
1105   ctype<wchar_t>::
1106   do_is(const wchar_t* __lo, const wchar_t* __hi, mask* __m) const
1107   {
1108     while (__lo < __hi && !this->is(*__m, *__lo))
1109       ++__lo;
1110     return __lo;
1111   }
1112   
1113   const wchar_t* 
1114   ctype<wchar_t>::
1115   do_scan_is(mask __m, const wchar_t* __lo, const wchar_t* __hi) const
1116   {
1117     while (__lo < __hi && !this->is(__m, *__lo))
1118       ++__lo;
1119     return __lo;
1120   }
1121
1122   const wchar_t*
1123   ctype<wchar_t>::
1124   do_scan_not(mask __m, const char_type* __lo, const char_type* __hi) const
1125   {
1126     while (__lo < __hi && this->is(__m, *__lo) != 0)
1127       ++__lo;
1128     return __lo;
1129   }
1130
1131   wchar_t
1132   ctype<wchar_t>::
1133   do_widen(char __c) const
1134   { return btowc(__c); }
1135   
1136   const char* 
1137   ctype<wchar_t>::
1138   do_widen(const char* __lo, const char* __hi, wchar_t* __dest) const
1139   {
1140     mbstate_t __state;
1141     memset(static_cast<void*>(&__state), 0, sizeof(mbstate_t));
1142     mbsrtowcs(__dest, &__lo, __hi - __lo, &__state);
1143     return __hi;
1144   }
1145
1146   char
1147   ctype<wchar_t>::
1148   do_narrow(wchar_t __wc, char __dfault) const
1149   { 
1150     int __c = wctob(__wc);
1151     return (__c == EOF ? __dfault : static_cast<char>(__c)); 
1152   }
1153
1154   const wchar_t*
1155   ctype<wchar_t>::
1156   do_narrow(const wchar_t* __lo, const wchar_t* __hi, char __dfault, 
1157             char* __dest) const
1158   {
1159     mbstate_t __state;
1160     memset(static_cast<void*>(&__state), 0, sizeof(mbstate_t));
1161     size_t __len = __hi - __lo;
1162     size_t __conv = wcsrtombs(__dest, &__lo, __len, &__state);
1163     if (__conv == __len)
1164       *__dest = __dfault;
1165     return __hi;
1166   }
1167
1168   template<>
1169   ctype_byname<wchar_t>::
1170   ctype_byname(const char* /*__s*/, size_t __refs)
1171   : ctype<wchar_t>(__refs) { }
1172 #endif //  _GLIBCPP_USE_WCHAR_T
1173 } // namespace std