OSDN Git Service

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