OSDN Git Service

2001-02-15 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;
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       bool __valid = __beg != __end;
680       // Fail quickly if !__valid
681       if (!__valid)
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           __xtrc[__pos++] = __c;
700           ++__beg;
701           __testsign = true;
702           // whitespace may follow a sign
703           while ((__beg != __end) && (isspace(*__beg)))
704             ++__beg;
705
706           // There had better be more to come...
707           if (__beg == __end)
708             {
709               __xtrc[__pos] = '\0';
710               __err |= (ios_base::eofbit | ios_base::failbit);
711               return;
712             }
713         }
714
715       bool __testzero = false;    // Has there been a leading zero?
716
717       // Now check if first character is a zero
718       __c = *__beg;
719       if (__c == __lits[__cache_type::_S_digits])
720         {
721            __testzero = true;
722            ++__beg;
723
724            // We have to check for __beg == __end here. If so,
725            // a plain '0' (possibly with a sign) can be got rid of now
726            if (__beg == __end)
727              {
728                __xtrc[__pos++] = __c;
729                __xtrc[__pos] = '\0';
730                __err |= ios_base::eofbit;
731                return;
732              }
733
734           // Figure out base for integer types only
735           // Based on Table 55 of 22.2.2.1.2
736           if (!__fp && __base != 10 && __base != 8)
737             {
738               // Here, __base == 0 or 16
739               __c = *__beg;
740               if ((__c == __lits[__cache_type::_S_x])
741                  || (__c == __lits[__cache_type::_S_X]))
742                 {
743                   ++__beg;
744                   __base = 16;
745                   __testzero = false; // "0x" is not a leading zero
746                 }
747               else if (__base == 0)
748                 __base = 8;
749             }
750
751           // Remove any more leading zeros
752           while (__beg != __end)
753             {
754               if (*__beg == __lits[__cache_type::_S_digits])
755                 {
756                   ++__beg;
757                   __testzero = true;
758                 }
759               else
760                 break;
761             }
762         }
763       else if (__base == 0) // 1st character is not zero
764         __base = 10;
765
766       // We now seek "units", i.e. digits and thousands separators.
767       // We may need to know if anything is found here. A leading zero
768       // (removed by now) would count.
769       bool __testunits = __testzero;
770       while (__valid && __beg != __end)
771         {
772           __valid = false;
773           __c = *__beg;
774           const char* __p = strchr(__fmt->_S_literals, __c);
775
776           // NB: strchr returns true for __c == 0x0
777           if (__p && __c)
778             {
779               // Try first for acceptable digit; record it if found
780               if ((__p >= &__lits[__cache_type::_S_digits]
781                     && __p < &__lits[__cache_type::_S_digits + __base])
782                    || (__p >= &__lits[__cache_type::_S_udigits]
783                        && __p < &__lits[__cache_type::_S_udigits + __base]))
784                 {
785                   __xtrc[__pos++] = __c;
786                   ++__sep_pos;
787                   __valid = true;
788                   __testunits = true;
789                 }
790             }
791           else if (__c == __fmt->_M_thousands_sep
792                    && __fmt->_M_use_grouping)
793             {
794               // NB: Thousands separator at the beginning of a string
795               // is a no-no, as is two consecutive thousands
796               // separators
797               if (__sep_pos)
798                 {
799                   __grp += static_cast<char>(__sep_pos);
800                   __sep_pos = 0;
801                   __valid = true;
802                 }
803               else
804                 __err |= ios_base::failbit;
805             }
806           if (__valid)
807             ++__beg;
808         }
809
810       // Digit grouping is checked. If _M_groupings() doesn't
811       // match, then get very very upset, and set failbit.
812       if (__fmt->_M_use_grouping && !__grp.empty())
813         {
814           // Add the ending grouping
815           __grp += static_cast<char>(__sep_pos);
816
817           // __grp is parsed L to R
818           // 1,222,444 == __grp of "/1/3/3"
819           // __fmt->_M_grouping is parsed R to L
820           // 1,222,444 == __fmt->_M_grouping of "/3" == "/3/3/3"
821           int __i = 0;
822           int __j = 0;
823           const int __len = __fmt->_M_grouping.size();
824           int __n = __grp.size();
825           bool __test = true;
826
827           // Parsed number groupings have to match the
828           // numpunct::grouping string exactly, starting at the
829           // right-most point of the parsed sequence of elements ...
830           while (__test && __i < __n - 1)
831             for (__j = 0; __test && __j < __len && __i < __n - 1; ++__j,++__i)
832               __test &= __fmt->_M_grouping[__j] == __grp[__n - __i - 1];
833           // ... but the last parsed grouping can be <= numpunct
834           // grouping.
835           __j == __len ? __j = 0 : __j;
836           __test &= __fmt->_M_grouping[__j] >= __grp[__n - __i - 1];
837
838           if (!__test)
839             {
840               __err |= ios_base::failbit;
841               __xtrc[__pos] = '\0';
842               if (__beg == __end)
843                 __err |= ios_base::eofbit;
844               return;
845             }
846         }
847
848       // If there was nothing but zeros, put one in the output string
849       if (__testzero && (__pos == 0 || (__pos == 1 && __testsign)))
850         __xtrc[__pos++] = __lits[__cache_type::_S_digits];
851
852       // That's it for integer types. Remaining code is for floating point
853       if (__fp && __beg != __end)
854         {
855           __c = *__beg;
856           // Check first for decimal point. There MUST be one if
857           // __testunits is false.
858           bool __testdec = false;    // Is there a decimal point
859                                      // with digits following it?
860           if (__c == __fmt->_M_decimal_point)
861             {
862               __xtrc[__pos++] = '.';
863               ++__beg;
864               // Now we get any digits after the decimal point
865               // There MUST be some if __testunits is false.
866               while (__beg != __end)
867                 {
868                   __c = *__beg;
869                   const char* __p = strchr(__fmt->_S_literals, __c);
870                   if ((__p >= &__lits[__cache_type::_S_digits]
871                         && __p < &__lits[__cache_type::_S_digits + __base])
872                        || (__p >= &__lits[__cache_type::_S_udigits]
873                            && __p < &__lits[__cache_type::_S_udigits + __base]))
874                     {
875                       __xtrc[__pos++] = __c;
876                       ++__beg;
877                       __testdec = true;
878                     }
879                   else
880                     break;
881                 }
882             }
883           if (!__testunits && !__testdec) // Ill formed
884             {
885               __err |= ios_base::failbit;
886               __xtrc[__pos] = '\0';
887               if (__beg == __end)
888                 __err |= ios_base::eofbit;
889               return;
890             }
891
892           // Now we may find an exponent
893           if (__beg != __end)
894             {
895               __c = *__beg;
896               if ((__c == __lits[__cache_type::_S_ee])
897                    || (__c == __lits[__cache_type::_S_Ee]))
898                 {
899                   __xtrc[__pos++] = __c;
900                   ++__beg;
901                   // Now there may be a sign
902                   if (__beg != __end)
903                     {
904                       __c = *__beg;
905                       if ((__c == __lits[__cache_type::_S_minus])
906                           || (__c == __lits[__cache_type::_S_plus]))
907                         {
908                           __xtrc[__pos++] = __c;
909                           ++__beg;
910                           // whitespace may follow a sign
911                           while ((__beg != __end) && (isspace(*__beg)))
912                             ++__beg;
913
914                         }
915                     }
916                   // And now there must be some digits
917                   if (__beg == __end)
918                     {
919                       __xtrc[__pos] = '\0';
920                       __err |= (ios_base::eofbit | ios_base::failbit);
921                       return;
922                     }
923                   while (__beg != __end)
924                     {
925                       __c = *__beg;
926                       const char* __p = strchr(__fmt->_S_literals, __c);
927                       if ((__p >= &__lits[__cache_type::_S_digits]
928                             && __p < &__lits[__cache_type::_S_digits + __base])
929                            || (__p >= &__lits[__cache_type::_S_udigits]
930                                && __p < &__lits[__cache_type::_S_udigits + __base]))
931                         {
932                           __xtrc[__pos++] = __c;
933                           ++__beg;
934                         }
935                       else
936                         break;
937                     }
938                 }
939             }
940           // Finally, that's it for floating point
941         }
942
943       // Finish up
944       __xtrc[__pos] = '\0';
945       if (__beg == __end)
946         __err |= ios_base::eofbit;
947     }
948
949   // The following code uses sprintf() to convert floating point
950   // values for insertion into a stream. The current implementation
951   // replicates the code in _S_pad_numeric() (in _S_output_float()) in
952   // order to prevent having to create a "wide" buffer in addition to
953   // the "narrow" buffer passed to sprintf(). An optimization would be
954   // to replace sprintf() with code that works directly on a wide
955   // buffer and then use _S_pad_numeric() to do the padding. It would
956   // be good to replace sprintf() anyway to avoid accidental buffer
957   // overruns and to gain back the efficiency that C++ provides by
958   // knowing up front the type of the values to insert. This
959   // implementation follows the C++ standard fairly directly as
960   // outlined in 22.2.2.2 [lib.locale.num.put]
961   bool
962   __build_float_format(ios_base& __io, char* __fptr, char __modifier,
963                        streamsize __prec)
964   {
965     bool __incl_prec = false;
966     ios_base::fmtflags __flags = __io.flags();
967     *__fptr++ = '%';
968     // [22.2.2.2.2] Table 60
969     if (__flags & ios_base::showpos)
970       *__fptr++ = '+';
971     if (__flags & ios_base::showpoint)
972       *__fptr++ = '#';
973     // As per [22.2.2.2.2.11]
974     if (__flags & ios_base::fixed || __prec > 0)
975       {
976         *__fptr++ = '.';
977         *__fptr++ = '*';
978         __incl_prec = true;
979       }
980     if (__modifier)
981       *__fptr++ = __modifier;
982     ios_base::fmtflags __fltfield = __flags & ios_base::floatfield;
983     // [22.2.2.2.2] Table 58
984     if (__fltfield == ios_base::fixed)
985       *__fptr++ = 'f';
986     else if (__fltfield == ios_base::scientific)
987       *__fptr++ = (__flags & ios_base::uppercase) ? 'E' : 'e';
988     else
989       *__fptr++ = (__flags & ios_base::uppercase) ? 'G' : 'g';
990     *__fptr = '\0';
991     return __incl_prec;
992   }
993
994   collate<char>::collate(size_t __refs)
995   : locale::facet(__refs) { }
996   
997   collate<char>::~collate() { }
998   
999   int 
1000   collate<char>::do_compare(const char* __lo1, const char* __hi1, 
1001                             const char* __lo2, const char* __hi2) const
1002   {
1003     for (; __lo1 < __hi1 && __lo2 < __hi2; ++__lo1, ++__lo2) 
1004       if (*__lo1 != *__lo2) 
1005         return (*__lo1 < *__lo2) ? -1 : 1;
1006     if (__lo1 < __hi1) 
1007       return 1;
1008     else if (__lo2 < __hi2) 
1009       return -1;
1010     else 
1011       return 0;
1012   }
1013   
1014   string
1015   collate<char>::
1016   do_transform(const char* __lo, const char* __hi) const
1017   { return string(__lo, __hi - __lo); }
1018   
1019   long
1020   collate<char>::
1021   do_hash(const char* __lo, const char* __hi) const
1022   {
1023     unsigned long __val = 0xdeadbeef;
1024     for (; __lo < __hi; ++__lo)
1025       __val = *__lo ^ ((__val << 7) & 
1026                    (__val >> (numeric_limits<unsigned long>::digits - 1)));
1027     return __val;
1028   }
1029   
1030   collate_byname<char>::collate_byname(const char* /*__s*/, size_t __refs)
1031   : collate<char>(__refs) { }
1032
1033   moneypunct_byname<char, false>::moneypunct_byname(const char* /*__s*/, 
1034                                                     size_t __refs)
1035   : moneypunct<char, false>(__refs) { }
1036   
1037   moneypunct_byname<char, true>::moneypunct_byname(const char* /*__s*/, 
1038                                                    size_t __refs)
1039   : moneypunct<char, true>(__refs) { }
1040   
1041   messages_byname<char>::
1042   messages_byname(const char* /*__s*/, size_t __refs)
1043   : messages<char>(__refs) { }
1044
1045 #ifdef _GLIBCPP_USE_WCHAR_T  
1046   ctype<wchar_t>::__wmask_type
1047   ctype<wchar_t>::_M_convert_to_wmask(const mask __m) const
1048   {
1049     __wmask_type __ret;
1050     switch (__m)
1051       {
1052       case space:
1053         __ret = wctype("space");
1054         break;
1055       case print:
1056         __ret = wctype("print");
1057         break;
1058       case cntrl:
1059         __ret = wctype("cntrl");
1060         break;
1061       case upper:
1062         __ret = wctype("upper");
1063         break;
1064       case lower:
1065         __ret = wctype("lower");
1066         break;
1067       case alpha:
1068         __ret = wctype("alpha");
1069         break;
1070       case digit:
1071         __ret = wctype("digit");
1072         break;
1073       case punct:
1074         __ret = wctype("punct");
1075         break;
1076       case xdigit:
1077         __ret = wctype("xdigit");
1078         break;
1079       case alnum:
1080         __ret = wctype("alnum");
1081         break;
1082       case graph:
1083         __ret = wctype("graph");
1084         break;
1085       default:
1086         __ret = 0;
1087       }
1088     return __ret;
1089   };
1090   
1091   ctype<wchar_t>::~ctype() { }
1092
1093   // NB: These ctype<wchar_t> methods are not configuration-specific,
1094   // unlike the ctype<char> bits.
1095   ctype<wchar_t>::ctype(size_t __refs) : __ctype_abstract_base<wchar_t>(__refs)
1096   { }
1097
1098   wchar_t
1099   ctype<wchar_t>::do_toupper(wchar_t __c) const
1100   { return towupper(__c); }
1101
1102   const wchar_t*
1103   ctype<wchar_t>::do_toupper(wchar_t* __low, const wchar_t* __high) const
1104   {
1105     while (__low < __high)
1106       {
1107         *__low = towupper(*__low);
1108         ++__low;
1109       }
1110     return __high;
1111   }
1112   
1113   wchar_t
1114   ctype<wchar_t>::do_tolower(wchar_t __c) const
1115   { return towlower(__c); }
1116   
1117   const wchar_t*
1118   ctype<wchar_t>::do_tolower(wchar_t* __low, const wchar_t* __high) const
1119   {
1120     while (__low < __high)
1121       {
1122         *__low = towlower(*__low);
1123         ++__low;
1124       }
1125     return __high;
1126   }
1127
1128   bool
1129   ctype<wchar_t>::
1130   do_is(mask __m, char_type __c) const
1131   { return static_cast<bool>(iswctype(__c, _M_convert_to_wmask(__m))); }
1132   
1133   const wchar_t* 
1134   ctype<wchar_t>::
1135   do_is(const wchar_t* __low, const wchar_t* __high, mask* __m) const
1136   {
1137     while (__low < __high && !this->is(*__m, *__low))
1138       ++__low;
1139     return __low;
1140   }
1141   
1142   const wchar_t* 
1143   ctype<wchar_t>::
1144   do_scan_is(mask __m, const wchar_t* __low, const wchar_t* __high) const
1145   {
1146     while (__low < __high && !this->is(__m, *__low))
1147       ++__low;
1148     return __low;
1149   }
1150
1151   const wchar_t*
1152   ctype<wchar_t>::
1153   do_scan_not(mask __m, const char_type* __low, const char_type* __high) const
1154   {
1155     while (__low < __high && this->is(__m, *__low) != 0)
1156       ++__low;
1157     return __low;
1158   }
1159
1160   wchar_t
1161   ctype<wchar_t>::
1162   do_widen(char __c) const
1163   { return btowc(__c); }
1164   
1165   const char* 
1166   ctype<wchar_t>::
1167   do_widen(const char* __low, const char* __high, wchar_t* __dest) const
1168   {
1169     mbstate_t __state;
1170     memset(static_cast<void*>(&__state), 0, sizeof(mbstate_t));
1171     mbsrtowcs(__dest, &__low, __high - __low, &__state);
1172     return __high;
1173   }
1174
1175   char
1176   ctype<wchar_t>::
1177   do_narrow(wchar_t __wc, char __dfault) const
1178   { 
1179     int __c = wctob(__wc);
1180     return (__c == EOF ? __dfault : static_cast<char>(__c)); 
1181   }
1182
1183   const wchar_t*
1184   ctype<wchar_t>::
1185   do_narrow(const wchar_t* __low, const wchar_t* __high, char __dfault, 
1186             char* __dest) const
1187   {
1188     mbstate_t __state;
1189     memset(static_cast<void*>(&__state), 0, sizeof(mbstate_t));
1190     size_t __len = __high - __low;
1191     size_t __conv = wcsrtombs(__dest, &__low, __len, &__state);
1192     if (__conv == __len)
1193       *__dest = __dfault;
1194     return __high;
1195   }
1196
1197   ctype_byname<wchar_t>::
1198   ctype_byname(const char* /*__s*/, size_t __refs)
1199   : ctype<wchar_t>(__refs) { }
1200
1201   collate<wchar_t>::
1202   collate(size_t __refs): locale::facet(__refs) { }
1203   
1204   collate<wchar_t>::
1205   ~collate() { }
1206
1207   int 
1208   collate<wchar_t>::
1209   do_compare(const wchar_t* /*__lo1*/, const wchar_t* /*__hi1*/,
1210              const wchar_t* /*__lo2*/, const wchar_t* /*__hi2*/) const
1211   {
1212     return 0; // XXX not done
1213   }
1214   
1215   wstring collate<wchar_t>::
1216   do_transform(const wchar_t* /*__lo*/, const wchar_t* /*__hi*/) const
1217   {
1218     return wstring(); // XXX not done
1219   }
1220   
1221   long collate<wchar_t>::
1222   do_hash(const wchar_t* /*__lo*/, const wchar_t* /*__hi*/) const
1223   {
1224     return 0; // XXX not done
1225   }
1226
1227   collate_byname<wchar_t>::
1228   collate_byname(const char* /*__s*/, size_t __refs)
1229   : collate<wchar_t> (__refs) { }
1230   
1231   messages_byname<wchar_t>::
1232   messages_byname(const char* /*__s*/, size_t __refs)
1233   : messages<wchar_t> (__refs) { }
1234 #endif //  _GLIBCPP_USE_WCHAR_T
1235 } // namespace std
1236
1237
1238
1239
1240
1241