OSDN Git Service

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