OSDN Git Service

2001-09-09 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   locale::~locale() throw()
166   { _M_impl->_M_remove_reference(); }
167
168   void
169   locale::_M_coalesce(const locale& __base, const locale& __add, 
170                       category __cat)
171   {
172     __cat = _S_normalize_category(__cat);  
173     _M_impl = new _Impl(*__base._M_impl, 1);  
174
175     try 
176       { _M_impl->_M_replace_categories(__add._M_impl, __cat); }
177     catch (...) 
178       { 
179         _M_impl->_M_remove_reference(); 
180         __throw_exception_again;
181       }
182   }
183
184   locale::locale() throw()
185   { 
186     _S_initialize(); 
187     (_M_impl = _S_global)->_M_add_reference(); 
188   } // XXX MT
189
190   locale::locale(const locale& __other) throw()
191   { (_M_impl = __other._M_impl)->_M_add_reference(); }
192
193   // This is used to initialize global and classic locales, and
194   // assumes that the _Impl objects are constructed correctly.
195   locale::locale(_Impl* __ip) throw() : _M_impl(__ip)
196   { }
197
198   locale::locale(const char* __s)
199   {
200     if (__s)
201       {
202         _S_initialize(); 
203         if (strcmp(__s, "C") == 0 || strcmp(__s, "POSIX") == 0)
204           (_M_impl = _S_classic)->_M_add_reference();
205         else
206           _M_impl = new _Impl(__s, 1);
207       }
208     else
209       __throw_runtime_error("attempt to create locale from NULL name");
210   }
211
212   locale::locale(const locale& __base, const char* __s, category __cat)
213   { 
214     // NB: There are complicated, yet more efficient ways to do
215     // this. Building up locales on a per-category way is tedious, so
216     // let's do it this way until people complain.
217     locale __add(__s);
218     _M_coalesce(__base, __add, __cat);
219   }
220
221   locale::locale(const locale& __base, const locale& __add, category __cat)
222   { _M_coalesce(__base, __add, __cat); }
223
224   bool
225   locale::operator==(const locale& __rhs) const throw()
226   {
227     string __name = this->name();
228     return (_M_impl == __rhs._M_impl 
229             || (__name != "*" && __name == __rhs.name()));
230   }
231
232   const locale&
233   locale::operator=(const locale& __other) throw()
234   {
235     __other._M_impl->_M_add_reference();
236     _M_impl->_M_remove_reference();
237     _M_impl = __other._M_impl;
238     return *this;
239   }
240
241   locale
242   locale::global(const locale& __other)
243   {
244     // XXX MT
245     _S_initialize();
246     _Impl* __old = _S_global;
247     __other._M_impl->_M_add_reference();
248     _S_global = __other._M_impl; 
249     if (_S_global->_M_check_same_name() && _S_global->_M_names[0] != "*")
250       setlocale(LC_ALL, __other.name().c_str());
251
252     // Reference count sanity check: one reference removed for the
253     // subsition of __other locale, one added by return-by-value. Net
254     // difference: zero. When the returned locale object's destrutor
255     // is called, then the reference count is decremented and possibly
256     // destroyed.
257     return locale(__old);
258   }
259
260   string
261   locale::name() const
262   {
263     string __ret;
264     // Need some kind of separator character. This one was pretty much
265     // arbitrarily chosen as to not conflict with glibc locales: the
266     // exact formatting is not set in stone.
267     const char __separator = '|';
268
269     if (_M_impl->_M_check_same_name())
270       __ret = _M_impl->_M_names[0];
271     else
272       {
273         for (size_t i = 0; i < _S_num_categories; ++i)
274           __ret += __separator + _M_impl->_M_names[i];
275       }
276     return __ret;
277   }
278
279   locale const&
280   locale::classic()
281   {
282     // XXX MT
283     if (!_S_classic)
284       {
285         try 
286           {
287             // 26 Standard facets, 2 references.
288             // One reference for _M_classic, one for _M_global
289             _S_classic = new (&locale_impl_c) _Impl("C", 2);
290             _S_global = _S_classic;         
291             new (&locale_c) locale(_S_classic);
292           }
293         catch(...) 
294           {
295             // Just call destructor, so that locale_impl_c's memory is
296             // not deallocated via a call to delete.
297             if (_S_classic)
298               _S_classic->~_Impl();
299             _S_classic = _S_global = 0;
300             __throw_exception_again;
301           }
302       }
303     return locale_c;
304   }
305
306   locale::category
307   locale::_S_normalize_category(category __cat) 
308   {
309     int __ret = 0;
310     if (__cat == none || (__cat & all) && !(__cat & ~all))
311       __ret = __cat;
312     else
313       {
314         // NB: May be a C-style "LC_ALL" category; convert.
315         switch (__cat)
316           {
317           case LC_COLLATE:  
318             __ret = collate; 
319             break;
320           case LC_CTYPE:    
321             __ret = ctype;
322             break;
323           case LC_MONETARY: 
324             __ret = monetary;
325             break;
326           case LC_NUMERIC:  
327             __ret = numeric;
328             break;
329           case LC_TIME:     
330             __ret = time; 
331             break;
332 #ifdef _GLIBCPP_HAVE_LC_MESSAGES
333           case LC_MESSAGES: 
334             __ret = messages;
335             break;
336 #endif  
337           case LC_ALL:      
338             __ret = all;
339             break;
340           default:
341             __throw_runtime_error("bad locale category");
342           }
343       }
344     return __ret;
345   }
346
347   locale::facet::
348   facet(size_t __refs) throw() : _M_references(__refs) 
349   { }
350
351   void  
352   locale::facet::
353   _M_add_reference() throw()
354   { ++_M_references; }                     // XXX MT
355
356   void  
357   locale::facet::
358   _M_remove_reference() throw()
359   {
360     if (_M_references-- == 0)
361       {
362         try 
363           { delete this; }  
364         catch (...) 
365           { }
366       }
367   }
368   
369   // Definitions for static const data members of ctype_base.
370   const ctype_base::mask ctype_base::space;
371   const ctype_base::mask ctype_base::print;
372   const ctype_base::mask ctype_base::cntrl;
373   const ctype_base::mask ctype_base::upper;
374   const ctype_base::mask ctype_base::lower;
375   const ctype_base::mask ctype_base::alpha;
376   const ctype_base::mask ctype_base::digit;
377   const ctype_base::mask ctype_base::punct;
378   const ctype_base::mask ctype_base::xdigit;
379   const ctype_base::mask ctype_base::alnum;
380   const ctype_base::mask ctype_base::graph;
381
382   // Platform-specific initialization code for ctype tables.
383   #include <bits/ctype_noninline.h>
384
385   const size_t ctype<char>::table_size;
386
387   ctype<char>::~ctype()
388   { if (_M_del) delete[] this->table(); }
389
390   // These are dummy placeholders as these virtual functions are never called.
391   bool 
392   ctype<char>::do_is(mask, char_type) const 
393   { return false; }
394   
395   const char*
396   ctype<char>::do_is(const char_type* __c, const char_type*, mask*) const 
397   { return __c; }
398   
399   const char*
400   ctype<char>::do_scan_is(mask, const char_type* __c, const char_type*) const 
401   { return __c; }
402
403   const char* 
404   ctype<char>::do_scan_not(mask, const char_type* __c, const char_type*) const
405   { return __c; }
406
407   char
408   ctype<char>::do_widen(char __c) const
409   { return __c; }
410   
411   const char* 
412   ctype<char>::do_widen(const char* __lo, const char* __hi, char* __dest) const
413   {
414     memcpy(__dest, __lo, __hi - __lo);
415     return __hi;
416   }
417   
418   char
419   ctype<char>::do_narrow(char __c, char /*__dfault*/) const
420   { return __c; }
421   
422   const char* 
423   ctype<char>::do_narrow(const char* __lo, const char* __hi, 
424                          char /*__dfault*/, char* __dest) const
425   {
426     memcpy(__dest, __lo, __hi - __lo);
427     return __hi;
428   }
429
430   template<>
431   ctype_byname<char>::ctype_byname(const char* /*__s*/, size_t __refs)
432   : ctype<char>(new mask[table_size], true, __refs)
433   { }
434
435   // Definitions for static const data members of money_base
436   const money_base::pattern 
437   money_base::_S_default_pattern =  {{symbol, sign, none, value}};
438
439   template<>
440     _Format_cache<char>::_Format_cache()
441     : _M_valid(true),
442     _M_decimal_point('.'), _M_thousands_sep(','),
443     _M_truename("true"), _M_falsename("false"), _M_use_grouping(false)
444     { }
445
446 #ifdef _GLIBCPP_USE_WCHAR_T
447   template<>
448     _Format_cache<wchar_t>::_Format_cache()
449     : _M_valid(true),
450     _M_decimal_point(L'.'), _M_thousands_sep(L','),
451     _M_truename(L"true"), _M_falsename(L"false"), _M_use_grouping(false)
452     { }
453 #endif
454
455   template<>
456     const ctype<char>&
457     use_facet<ctype<char> >(const locale& __loc)
458     {
459       size_t __i = ctype<char>::id._M_index;
460       const locale::_Impl* __tmp = __loc._M_impl;
461       return static_cast<const ctype<char>&>(* (*(__tmp->_M_facets))[__i]);
462     }
463
464 #ifdef _GLIBCPP_USE_WCHAR_T
465   template<>
466     const ctype<wchar_t>&
467     use_facet<ctype<wchar_t> >(const locale& __loc)
468     {
469       size_t __i = ctype<wchar_t>::id._M_index;
470       const locale::_Impl* __tmp = __loc._M_impl;
471       return static_cast<const ctype<wchar_t>&>(* (*(__tmp->_M_facets))[__i]);
472     }
473 #endif
474
475   template<>
476     void
477     num_get<char, istreambuf_iterator<char> >::
478     _M_extract(istreambuf_iterator<char> __beg, 
479                istreambuf_iterator<char> __end, ios_base& __io, 
480                ios_base::iostate& __err, char* __xtrc, int& __base, 
481                bool __fp) const
482     {
483       typedef _Format_cache<char> __cache_type; 
484
485       // Prepare for possible failure
486       __xtrc[0] = '\0';
487
488       // Stage 1: determine a conversion specifier.
489       ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
490       if (__basefield == ios_base::dec)
491         __base = 10;
492       else if (__basefield == ios_base::oct)
493         __base = 8;
494       else if (__basefield == ios_base::hex)
495         __base = 16;
496       else
497         __base = 0;
498       // As far as I can tell, bases other than 10 are not available for
499       // floating point types
500       if (__fp)
501         __base = 10;
502
503       // Stage 2: extract characters.
504       __cache_type const* __fmt = __cache_type::_S_get(__io);
505
506       // Fail quickly if !__valid
507       if (__beg == __end)
508         {
509           __err |= (ios_base::eofbit | ios_base::failbit);
510           return;
511         }
512
513       // Acceptable formats for numbers here are based on 22.2.3.1
514       string __grp;
515       int __sep_pos = 0;
516       int __pos = 0;
517       const char* __lits = __fmt->_S_literals;
518       char __c = *__beg;
519
520       // Check first for sign
521       bool __testsign = false;
522       if ((__c == __lits[__cache_type::_S_minus])
523           || (__c == __lits[__cache_type::_S_plus]))
524         {
525           __testsign = true;
526           __xtrc[__pos++] = __c;
527           ++__beg;
528           __c = * __beg;
529
530           // Whitespace may follow a sign
531           while ((__beg != __end) && (isspace(__c)))
532             {
533               ++__beg;
534               __c = *__beg;
535             }
536
537           // There had better be more to come...
538           if (__beg == __end)
539             {
540               __xtrc[__pos] = '\0';
541               __err |= (ios_base::eofbit | ios_base::failbit);
542               return;
543             }
544         }
545
546       // Now check if first character is a zero.
547       bool __testzero = false;    
548       if (__c == __lits[__cache_type::_S_digits])
549         {
550            __testzero = true;
551            ++__beg;
552            __c = *__beg;
553
554            // We have to check for __beg == __end here. If so,
555            // a plain '0' (possibly with a sign) can be got rid of now
556            if (__beg == __end)
557              {
558                __xtrc[__pos++] = __lits[__cache_type::_S_digits];
559                __xtrc[__pos] = '\0';
560                __err |= ios_base::eofbit;
561                return;
562              }
563
564           // Figure out base for integer types only
565           // Based on Table 55 of 22.2.2.1.2
566           if (!__fp && __base != 10 && __base != 8)
567             {
568               // Here, __base == 0 or 16
569               if ((__c == __lits[__cache_type::_S_x])
570                  || (__c == __lits[__cache_type::_S_X]))
571                 {
572                   ++__beg;
573                   __c = *__beg;
574                   __base = 16;
575                   __testzero = false; // "0x" is not a leading zero
576                 }
577               else if (__base == 0)
578                 __base = 8;
579             }
580
581           // Remove any more leading zeros
582           while (__beg != __end)
583             {
584               if (__c == __lits[__cache_type::_S_digits])
585                 {
586                   ++__beg;
587                   __c = *__beg;
588                   __testzero = true;
589                 }
590               else
591                 break;
592             }
593         }
594       else if (__base == 0) // 1st character is not zero
595         __base = 10;
596
597       // We now seek "units", i.e. digits and thousands separators.
598       // We may need to know if anything is found here. A leading zero
599       // (removed by now) would count.
600       bool __testunits = __testzero;
601       while (__beg != __end)
602         {
603           const char* __p = strchr(__lits, __c);
604
605           // NB: strchr returns true for __c == 0x0
606           if (__p && __c
607               &&((__p >= &__lits[__cache_type::_S_digits]
608                   && __p < &__lits[__cache_type::_S_digits + __base])
609                  || (__p >= &__lits[__cache_type::_S_udigits]
610                      && __p < &__lits[__cache_type::_S_udigits + __base])))
611             {
612               // Try first for acceptable digit; record it if found.
613               __xtrc[__pos++] = __c;
614               ++__sep_pos;
615               __testunits = true;
616               ++__beg;
617               __c = *__beg;
618             }
619           else if (__c == __fmt->_M_thousands_sep && __fmt->_M_use_grouping)
620             {
621               // NB: Thousands separator at the beginning of a string
622               // is a no-no, as is two consecutive thousands
623               // separators.
624               if (__sep_pos)
625                 {
626                   __grp += static_cast<char>(__sep_pos);
627                   __sep_pos = 0;
628                   ++__beg;
629                   __c = *__beg;
630                 }
631               else
632                 {
633                   __err |= ios_base::failbit;
634                   break;
635                 }
636             }
637           else
638             // Not a valid input item.
639             break;
640         }
641
642       // Digit grouping is checked. If _M_groupings() doesn't
643       // match, then get very very upset, and set failbit.
644       if (__fmt->_M_use_grouping && !__grp.empty())
645         {
646           // Add the ending grouping
647           __grp += static_cast<char>(__sep_pos);
648
649           // __grp is parsed L to R
650           // 1,222,444 == __grp of "/1/3/3"
651           // __fmt->_M_grouping is parsed R to L
652           // 1,222,444 == __fmt->_M_grouping of "/3" == "/3/3/3"
653           int __i = 0;
654           int __j = 0;
655           const int __len = __fmt->_M_grouping.size();
656           int __n = __grp.size();
657           bool __test = true;
658
659           // Parsed number groupings have to match the
660           // numpunct::grouping string exactly, starting at the
661           // right-most point of the parsed sequence of elements ...
662           while (__test && __i < __n - 1)
663             for (__j = 0; __test && __j < __len && __i < __n - 1; ++__j,++__i)
664               __test &= __fmt->_M_grouping[__j] == __grp[__n - __i - 1];
665           // ... but the last parsed grouping can be <= numpunct
666           // grouping.
667           __j == __len ? __j = 0 : __j;
668           __test &= __fmt->_M_grouping[__j] >= __grp[__n - __i - 1];
669
670           if (!__test)
671             {
672               __err |= ios_base::failbit;
673               __xtrc[__pos] = '\0';
674               if (__beg == __end)
675                 __err |= ios_base::eofbit;
676               return;
677             }
678         }
679
680       // If there was nothing but zeros, put one in the output string
681       if (__testzero && (__pos == 0 || (__pos == 1 && __testsign)))
682         __xtrc[__pos++] = __lits[__cache_type::_S_digits];
683
684       // That's it for integer types. Remaining code is for floating point
685       if (__fp && __beg != __end)
686         {
687           // Check first for decimal point. There MUST be one if
688           // __testunits is false.
689           bool __testdec = false;    // Is there a decimal point
690                                      // with digits following it?
691           if (__c == __fmt->_M_decimal_point)
692             {
693               __xtrc[__pos++] = '.';
694               ++__beg;
695               __c = *__beg;
696
697               // Now we get any digits after the decimal point
698               // There MUST be some if __testunits is false.
699               while (__beg != __end)
700                 {
701                   const char* __p = strchr(__lits, __c);
702                   if ((__p >= &__lits[__cache_type::_S_digits]
703                         && __p < &__lits[__cache_type::_S_digits + __base])
704                        || (__p >= &__lits[__cache_type::_S_udigits]
705                            && __p < &__lits[__cache_type::_S_udigits + __base]))
706                     {
707                       __xtrc[__pos++] = __c;
708                       ++__beg;
709                       __c = *__beg;
710                       __testdec = true;
711                     }
712                   else
713                     break;
714                 }
715             }
716           if (!__testunits && !__testdec) // Ill formed
717             {
718               __err |= ios_base::failbit;
719               __xtrc[__pos] = '\0';
720               if (__beg == __end)
721                 __err |= ios_base::eofbit;
722               return;
723             }
724
725           // Now we may find an exponent
726           if (__beg != __end)
727             {
728               if ((__c == __lits[__cache_type::_S_ee])
729                    || (__c == __lits[__cache_type::_S_Ee]))
730                 {
731                   __xtrc[__pos++] = __c;
732                   ++__beg;
733                   __c = *__beg;
734
735                   // Now there may be a sign
736                   if (__beg != __end)
737                     {
738                       if ((__c == __lits[__cache_type::_S_minus])
739                           || (__c == __lits[__cache_type::_S_plus]))
740                         {
741                           __xtrc[__pos++] = __c;
742                           ++__beg;
743                           __c = *__beg;
744                           // whitespace may follow a sign
745                           while ((__beg != __end) && (isspace(__c)))
746                             {
747                               ++__beg;
748                               __c = *__beg;
749                             }
750                         }
751                     }
752                   // And now there must be some digits
753                   if (__beg == __end)
754                     {
755                       __xtrc[__pos] = '\0';
756                       __err |= (ios_base::eofbit | ios_base::failbit);
757                       return;
758                     }
759                   while (__beg != __end)
760                     {
761                       const char* __p = strchr(__lits, __c);
762                       if ((__p >= &__lits[__cache_type::_S_digits]
763                             && __p < &__lits[__cache_type::_S_digits + __base])
764                            || (__p >= &__lits[__cache_type::_S_udigits]
765                                && __p < &__lits[__cache_type::_S_udigits + __base]))
766                         {
767                           __xtrc[__pos++] = __c;
768                           ++__beg;
769                           __c = *__beg;
770                         }
771                       else
772                         break;
773                     }
774                 }
775             }
776           // Finally, that's it for floating point
777         }
778
779       // Finish up
780       __xtrc[__pos] = '\0';
781       if (__beg == __end)
782         __err |= ios_base::eofbit;
783     }
784
785   // The following code uses sprintf() to convert floating point
786   // values for insertion into a stream. The current implementation
787   // replicates the code in _S_pad_numeric() (in _S_output_float()) in
788   // order to prevent having to create a "wide" buffer in addition to
789   // the "narrow" buffer passed to sprintf(). An optimization would be
790   // to replace sprintf() with code that works directly on a wide
791   // buffer and then use _S_pad_numeric() to do the padding. It would
792   // be good to replace sprintf() anyway to avoid accidental buffer
793   // overruns and to gain back the efficiency that C++ provides by
794   // knowing up front the type of the values to insert. This
795   // implementation follows the C++ standard fairly directly as
796   // outlined in 22.2.2.2 [lib.locale.num.put]
797   bool
798   __build_float_format(ios_base& __io, char* __fptr, char __modifier,
799                        streamsize __prec)
800   {
801     bool __incl_prec = false;
802     ios_base::fmtflags __flags = __io.flags();
803     *__fptr++ = '%';
804     // [22.2.2.2.2] Table 60
805     if (__flags & ios_base::showpos)
806       *__fptr++ = '+';
807     if (__flags & ios_base::showpoint)
808       *__fptr++ = '#';
809     // As per [22.2.2.2.2.11]
810     if (__flags & ios_base::fixed || __prec > 0)
811       {
812         *__fptr++ = '.';
813         *__fptr++ = '*';
814         __incl_prec = true;
815       }
816     if (__modifier)
817       *__fptr++ = __modifier;
818     ios_base::fmtflags __fltfield = __flags & ios_base::floatfield;
819     // [22.2.2.2.2] Table 58
820     if (__fltfield == ios_base::fixed)
821       *__fptr++ = 'f';
822     else if (__fltfield == ios_base::scientific)
823       *__fptr++ = (__flags & ios_base::uppercase) ? 'E' : 'e';
824     else
825       *__fptr++ = (__flags & ios_base::uppercase) ? 'G' : 'g';
826     *__fptr = '\0';
827     return __incl_prec;
828   }
829
830   template<>
831   moneypunct_byname<char, false>::moneypunct_byname(const char* /*__s*/, 
832                                                     size_t __refs)
833   : moneypunct<char, false>(__refs) { }
834   
835   template<>
836   moneypunct_byname<char, true>::moneypunct_byname(const char* /*__s*/, 
837                                                    size_t __refs)
838   : moneypunct<char, true>(__refs) { }
839   
840 #ifdef _GLIBCPP_USE_WCHAR_T  
841   ctype<wchar_t>::__wmask_type
842   ctype<wchar_t>::_M_convert_to_wmask(const mask __m) const
843   {
844     __wmask_type __ret;
845     switch (__m)
846       {
847       case space:
848         __ret = wctype("space");
849         break;
850       case print:
851         __ret = wctype("print");
852         break;
853       case cntrl:
854         __ret = wctype("cntrl");
855         break;
856       case upper:
857         __ret = wctype("upper");
858         break;
859       case lower:
860         __ret = wctype("lower");
861         break;
862       case alpha:
863         __ret = wctype("alpha");
864         break;
865       case digit:
866         __ret = wctype("digit");
867         break;
868       case punct:
869         __ret = wctype("punct");
870         break;
871       case xdigit:
872         __ret = wctype("xdigit");
873         break;
874       case alnum:
875         __ret = wctype("alnum");
876         break;
877       case graph:
878         __ret = wctype("graph");
879         break;
880       default:
881         __ret = 0;
882       }
883     return __ret;
884   };
885   
886   ctype<wchar_t>::~ctype() { }
887
888   // NB: These ctype<wchar_t> methods are not configuration-specific,
889   // unlike the ctype<char> bits.
890   ctype<wchar_t>::ctype(size_t __refs) : __ctype_abstract_base<wchar_t>(__refs)
891   { }
892
893   wchar_t
894   ctype<wchar_t>::do_toupper(wchar_t __c) const
895   { return towupper(__c); }
896
897   const wchar_t*
898   ctype<wchar_t>::do_toupper(wchar_t* __lo, const wchar_t* __hi) const
899   {
900     while (__lo < __hi)
901       {
902         *__lo = towupper(*__lo);
903         ++__lo;
904       }
905     return __hi;
906   }
907   
908   wchar_t
909   ctype<wchar_t>::do_tolower(wchar_t __c) const
910   { return towlower(__c); }
911   
912   const wchar_t*
913   ctype<wchar_t>::do_tolower(wchar_t* __lo, const wchar_t* __hi) const
914   {
915     while (__lo < __hi)
916       {
917         *__lo = towlower(*__lo);
918         ++__lo;
919       }
920     return __hi;
921   }
922
923   bool
924   ctype<wchar_t>::
925   do_is(mask __m, char_type __c) const
926   { return static_cast<bool>(iswctype(__c, _M_convert_to_wmask(__m))); }
927   
928   const wchar_t* 
929   ctype<wchar_t>::
930   do_is(const wchar_t* __lo, const wchar_t* __hi, mask* __m) const
931   {
932     while (__lo < __hi && !this->is(*__m, *__lo))
933       ++__lo;
934     return __lo;
935   }
936   
937   const wchar_t* 
938   ctype<wchar_t>::
939   do_scan_is(mask __m, const wchar_t* __lo, const wchar_t* __hi) const
940   {
941     while (__lo < __hi && !this->is(__m, *__lo))
942       ++__lo;
943     return __lo;
944   }
945
946   const wchar_t*
947   ctype<wchar_t>::
948   do_scan_not(mask __m, const char_type* __lo, const char_type* __hi) const
949   {
950     while (__lo < __hi && this->is(__m, *__lo) != 0)
951       ++__lo;
952     return __lo;
953   }
954
955   wchar_t
956   ctype<wchar_t>::
957   do_widen(char __c) const
958   { return btowc(__c); }
959   
960   const char* 
961   ctype<wchar_t>::
962   do_widen(const char* __lo, const char* __hi, wchar_t* __dest) const
963   {
964     mbstate_t __state;
965     memset(static_cast<void*>(&__state), 0, sizeof(mbstate_t));
966     mbsrtowcs(__dest, &__lo, __hi - __lo, &__state);
967     return __hi;
968   }
969
970   char
971   ctype<wchar_t>::
972   do_narrow(wchar_t __wc, char __dfault) const
973   { 
974     int __c = wctob(__wc);
975     return (__c == EOF ? __dfault : static_cast<char>(__c)); 
976   }
977
978   const wchar_t*
979   ctype<wchar_t>::
980   do_narrow(const wchar_t* __lo, const wchar_t* __hi, char __dfault, 
981             char* __dest) const
982   {
983     mbstate_t __state;
984     memset(static_cast<void*>(&__state), 0, sizeof(mbstate_t));
985     size_t __len = __hi - __lo;
986     size_t __conv = wcsrtombs(__dest, &__lo, __len, &__state);
987     if (__conv == __len)
988       *__dest = __dfault;
989     return __hi;
990   }
991
992   template<>
993   ctype_byname<wchar_t>::
994   ctype_byname(const char* /*__s*/, size_t __refs)
995   : ctype<wchar_t>(__refs) { }
996 #endif //  _GLIBCPP_USE_WCHAR_T
997 } // namespace std