OSDN Git Service

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