OSDN Git Service

2010-02-16 Benjamin Kosnik <bkoz@redhat.com>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / config / locale / gnu / monetary_members.cc
1 // std::moneypunct implementation details, GNU version -*- C++ -*-
2
3 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
4 // Free Software Foundation, Inc.
5 //
6 // This file is part of the GNU ISO C++ Library.  This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 3, or (at your option)
10 // any later version.
11
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 // GNU General Public License for more details.
16
17 // Under Section 7 of GPL version 3, you are granted additional
18 // permissions described in the GCC Runtime Library Exception, version
19 // 3.1, as published by the Free Software Foundation.
20
21 // You should have received a copy of the GNU General Public License and
22 // a copy of the GCC Runtime Library Exception along with this program;
23 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24 // <http://www.gnu.org/licenses/>.
25
26 //
27 // ISO C++ 14882: 22.2.6.3.2  moneypunct virtual functions
28 //
29
30 // Written by Benjamin Kosnik <bkoz@redhat.com>
31
32 #include <locale>
33 #include <bits/c++locale_internal.h>
34
35 _GLIBCXX_BEGIN_NAMESPACE(std)
36
37   // Construct and return valid pattern consisting of some combination of:
38   // space none symbol sign value
39   money_base::pattern
40   money_base::_S_construct_pattern(char __precedes, char __space, 
41                                    char __posn) throw()
42   { 
43     pattern __ret;
44
45     // This insanely complicated routine attempts to construct a valid
46     // pattern for use with monyepunct. A couple of invariants:
47
48     // if (__precedes) symbol -> value
49     // else value -> symbol
50     
51     // if (__space) space
52     // else none
53
54     // none == never first
55     // space never first or last
56
57     // Any elegant implementations of this are welcome.
58     switch (__posn)
59       {
60       case 0:
61       case 1:
62         // 1 The sign precedes the value and symbol.
63         __ret.field[0] = sign;
64         if (__space)
65           {
66             // Pattern starts with sign.
67             if (__precedes)
68               {
69                 __ret.field[1] = symbol;
70                 __ret.field[3] = value;
71               }
72             else
73               {
74                 __ret.field[1] = value;
75                 __ret.field[3] = symbol;
76               }
77             __ret.field[2] = space;
78           }
79         else
80           {
81             // Pattern starts with sign and ends with none.
82             if (__precedes)
83               {
84                 __ret.field[1] = symbol;
85                 __ret.field[2] = value;
86               }
87             else
88               {
89                 __ret.field[1] = value;
90                 __ret.field[2] = symbol;
91               }
92             __ret.field[3] = none;
93           }
94         break;
95       case 2:
96         // 2 The sign follows the value and symbol.
97         if (__space)
98           {
99             // Pattern either ends with sign.
100             if (__precedes)
101               {
102                 __ret.field[0] = symbol;
103                 __ret.field[2] = value;
104               }
105             else
106               {
107                 __ret.field[0] = value;
108                 __ret.field[2] = symbol;
109               }
110             __ret.field[1] = space;
111             __ret.field[3] = sign;
112           }
113         else
114           {
115             // Pattern ends with sign then none.
116             if (__precedes)
117               {
118                 __ret.field[0] = symbol;
119                 __ret.field[1] = value;
120               }
121             else
122               {
123                 __ret.field[0] = value;
124                 __ret.field[1] = symbol;
125               }
126             __ret.field[2] = sign;
127             __ret.field[3] = none;
128           }
129         break;
130       case 3:
131         // 3 The sign immediately precedes the symbol.
132         if (__precedes)
133           {
134             __ret.field[0] = sign;
135             __ret.field[1] = symbol;        
136             if (__space)
137               {
138                 __ret.field[2] = space;
139                 __ret.field[3] = value;
140               }
141             else
142               {
143                 __ret.field[2] = value;         
144                 __ret.field[3] = none;
145               }
146           }
147         else
148           {
149             __ret.field[0] = value;
150             if (__space)
151               {
152                 __ret.field[1] = space;
153                 __ret.field[2] = sign;
154                 __ret.field[3] = symbol;
155               }
156             else
157               {
158                 __ret.field[1] = sign;
159                 __ret.field[2] = symbol;
160                 __ret.field[3] = none;
161               }
162           }
163         break;
164       case 4:
165         // 4 The sign immediately follows the symbol.
166         if (__precedes)
167           {
168             __ret.field[0] = symbol;
169             __ret.field[1] = sign;
170             if (__space)
171               {
172                 __ret.field[2] = space;
173                 __ret.field[3] = value;
174               }
175             else
176               {
177                 __ret.field[2] = value;
178                 __ret.field[3] = none;
179               }
180           }
181         else
182           {
183             __ret.field[0] = value;
184             if (__space)
185               {
186                 __ret.field[1] = space;
187                 __ret.field[2] = symbol;
188                 __ret.field[3] = sign;
189               }
190             else
191               {
192                 __ret.field[1] = symbol;
193                 __ret.field[2] = sign;
194                 __ret.field[3] = none;
195               }
196           }
197         break;
198       default:
199         __ret = pattern();
200       }
201     return __ret;
202   }
203
204   template<> 
205     void
206     moneypunct<char, true>::_M_initialize_moneypunct(__c_locale __cloc, 
207                                                      const char*)
208     {
209       if (!_M_data)
210         _M_data = new __moneypunct_cache<char, true>;
211
212       if (!__cloc)
213         {
214           // "C" locale
215           _M_data->_M_decimal_point = '.';
216           _M_data->_M_thousands_sep = ',';
217           _M_data->_M_grouping = "";
218           _M_data->_M_grouping_size = 0;
219           _M_data->_M_use_grouping = false;
220           _M_data->_M_curr_symbol = "";
221           _M_data->_M_curr_symbol_size = 0;
222           _M_data->_M_positive_sign = "";
223           _M_data->_M_positive_sign_size = 0;
224           _M_data->_M_negative_sign = "";
225           _M_data->_M_negative_sign_size = 0;
226           _M_data->_M_frac_digits = 0;
227           _M_data->_M_pos_format = money_base::_S_default_pattern;
228           _M_data->_M_neg_format = money_base::_S_default_pattern;
229
230           for (size_t __i = 0; __i < money_base::_S_end; ++__i)
231             _M_data->_M_atoms[__i] = money_base::_S_atoms[__i];
232         }
233       else
234         {
235           // Named locale.
236           _M_data->_M_decimal_point = *(__nl_langinfo_l(__MON_DECIMAL_POINT, 
237                                                         __cloc));
238           _M_data->_M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP, 
239                                                         __cloc));
240
241           // Check for NULL, which implies no fractional digits.
242           if (_M_data->_M_decimal_point == '\0')
243             {
244               // Like in "C" locale.
245               _M_data->_M_frac_digits = 0;
246               _M_data->_M_decimal_point = '.';
247             }
248           else
249             _M_data->_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS, 
250                                                         __cloc));
251
252           const char* __cgroup = __nl_langinfo_l(__MON_GROUPING, __cloc);
253           const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
254           const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
255           // _Intl == true
256           const char* __ccurr = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc);
257
258           char* __group = 0;
259           char* __ps = 0;
260           char* __ns = 0;
261           const char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc));     
262           __try
263             {
264               size_t __len;
265               
266               // Check for NULL, which implies no grouping.
267               if (_M_data->_M_thousands_sep == '\0')
268                 {
269                   // Like in "C" locale.
270                   _M_data->_M_grouping = "";
271                   _M_data->_M_grouping_size = 0;
272                   _M_data->_M_use_grouping = false;
273                   _M_data->_M_thousands_sep = ',';
274                 }
275               else
276                 {
277                   __len = strlen(__cgroup);
278                   if (__len)
279                     {
280                       __group = new char[__len + 1];
281                       memcpy(__group, __cgroup, __len + 1);
282                       _M_data->_M_grouping = __group;
283                     }
284                   else
285                     {
286                       _M_data->_M_grouping = "";
287                       _M_data->_M_use_grouping = false;
288                     }
289                   _M_data->_M_grouping_size = __len;
290                 }
291
292               __len = strlen(__cpossign);
293               if (__len)
294                 {
295                   __ps = new char[__len + 1];
296                   memcpy(__ps, __cpossign, __len + 1);
297                   _M_data->_M_positive_sign = __ps;
298                 }
299               else
300                 _M_data->_M_positive_sign = "";
301               _M_data->_M_positive_sign_size = __len;
302
303               if (!__nposn)
304                 {
305                   _M_data->_M_negative_sign = "()";
306                   _M_data->_M_negative_sign_size = 2;
307                 }
308               else
309                 {
310                   __len = strlen(__cnegsign);
311                   if (__len)
312                     {
313                       __ns = new char[__len + 1];
314                       memcpy(__ns, __cnegsign, __len + 1);
315                       _M_data->_M_negative_sign = __ns;
316                     }
317                   else
318                     _M_data->_M_negative_sign = "";
319                   _M_data->_M_negative_sign_size = __len;
320                 }
321
322               __len = strlen(__ccurr);
323               if (__len)
324                 {
325                   char* __curr = new char[__len + 1];
326                   memcpy(__curr, __ccurr, __len + 1);
327                   _M_data->_M_curr_symbol = __curr;
328                 }
329               else
330                 _M_data->_M_curr_symbol = "";
331               _M_data->_M_curr_symbol_size = __len;
332             }
333           __catch(...)
334             {
335               delete _M_data;
336               _M_data = 0;
337               delete [] __group;
338               delete [] __ps;
339               delete [] __ns;
340             }
341
342           char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc));
343           char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc));
344           char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc));
345           _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
346                                                         __pposn);
347           char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc));
348           char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc));
349           _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
350                                                         __nposn);
351         }
352     }
353
354   template<> 
355     void
356     moneypunct<char, false>::_M_initialize_moneypunct(__c_locale __cloc, 
357                                                       const char*)
358     {
359       if (!_M_data)
360         _M_data = new __moneypunct_cache<char, false>;
361
362       if (!__cloc)
363         {
364           // "C" locale
365           _M_data->_M_decimal_point = '.';
366           _M_data->_M_thousands_sep = ',';
367           _M_data->_M_grouping = "";
368           _M_data->_M_grouping_size = 0;
369           _M_data->_M_use_grouping = false;
370           _M_data->_M_curr_symbol = "";
371           _M_data->_M_curr_symbol_size = 0;
372           _M_data->_M_positive_sign = "";
373           _M_data->_M_positive_sign_size = 0;
374           _M_data->_M_negative_sign = "";
375           _M_data->_M_negative_sign_size = 0;
376           _M_data->_M_frac_digits = 0;
377           _M_data->_M_pos_format = money_base::_S_default_pattern;
378           _M_data->_M_neg_format = money_base::_S_default_pattern;
379
380           for (size_t __i = 0; __i < money_base::_S_end; ++__i)
381             _M_data->_M_atoms[__i] = money_base::_S_atoms[__i];
382         }
383       else
384         {
385           // Named locale.
386           _M_data->_M_decimal_point = *(__nl_langinfo_l(__MON_DECIMAL_POINT, 
387                                                         __cloc));
388           _M_data->_M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP, 
389                                                         __cloc));
390
391           // Check for NULL, which implies no fractional digits.
392           if (_M_data->_M_decimal_point == '\0')
393             {
394               // Like in "C" locale.
395               _M_data->_M_frac_digits = 0;
396               _M_data->_M_decimal_point = '.';
397             }
398           else
399             _M_data->_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS,
400                                                         __cloc));
401
402           const char* __cgroup = __nl_langinfo_l(__MON_GROUPING, __cloc);
403           const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
404           const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
405           // _Intl == false
406           const char* __ccurr = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc);
407
408           char* __group = 0;
409           char* __ps = 0;
410           char* __ns = 0;
411           const char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc));
412           __try
413             {
414               size_t __len;
415
416               // Check for NULL, which implies no grouping.
417               if (_M_data->_M_thousands_sep == '\0')
418                 {
419                   // Like in "C" locale.
420                   _M_data->_M_grouping = "";
421                   _M_data->_M_grouping_size = 0;
422                   _M_data->_M_use_grouping = false;
423                   _M_data->_M_thousands_sep = ',';
424                 }
425               else
426                 {
427                   __len = strlen(__cgroup);
428                   if (__len)
429                     {
430                       __group = new char[__len + 1];
431                       memcpy(__group, __cgroup, __len + 1);
432                       _M_data->_M_grouping = __group;
433                     }
434                   else
435                     {
436                       _M_data->_M_grouping = "";
437                       _M_data->_M_use_grouping = false;
438                     }
439                   _M_data->_M_grouping_size = __len;
440                 }
441
442               __len = strlen(__cpossign);
443               if (__len)
444                 {
445                   __ps = new char[__len + 1];
446                   memcpy(__ps, __cpossign, __len + 1);
447                   _M_data->_M_positive_sign = __ps;
448                 }
449               else
450                 _M_data->_M_positive_sign = "";
451               _M_data->_M_positive_sign_size = __len;
452
453               if (!__nposn)
454                 {
455                   _M_data->_M_negative_sign = "()";
456                   _M_data->_M_negative_sign_size = 2;
457                 }
458               else
459                 {
460                   __len = strlen(__cnegsign);
461                   if (__len)
462                     {
463                       __ns = new char[__len + 1];
464                       memcpy(__ns, __cnegsign, __len + 1);
465                       _M_data->_M_negative_sign = __ns;
466                     }
467                   else
468                     _M_data->_M_negative_sign = "";
469                   _M_data->_M_negative_sign_size = __len;
470                 }
471
472               __len = strlen(__ccurr);
473               if (__len)
474                 {
475                   char* __curr = new char[__len + 1];
476                   memcpy(__curr, __ccurr, __len + 1);
477                   _M_data->_M_curr_symbol = __curr;
478                 }
479               else
480                 _M_data->_M_curr_symbol = "";
481               _M_data->_M_curr_symbol_size = __len;
482             }
483           __catch(...)
484             {
485               delete _M_data;
486               _M_data = 0;
487               delete [] __group;
488               delete [] __ps;
489               delete [] __ns;
490             }
491
492           char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc));
493           char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc));
494           char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc));
495           _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
496                                                         __pposn);
497           char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc));
498           char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc));
499           _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
500                                                         __nposn);
501         }
502     }
503
504   template<> 
505     moneypunct<char, true>::~moneypunct()
506     {
507       if (_M_data->_M_grouping_size)
508         delete [] _M_data->_M_grouping;
509       if (_M_data->_M_positive_sign_size)
510         delete [] _M_data->_M_positive_sign;
511       if (_M_data->_M_negative_sign_size
512           && strcmp(_M_data->_M_negative_sign, "()") != 0)
513         delete [] _M_data->_M_negative_sign;
514       if (_M_data->_M_curr_symbol_size)
515         delete [] _M_data->_M_curr_symbol;
516       delete _M_data;
517     }
518
519   template<> 
520     moneypunct<char, false>::~moneypunct()
521     {
522       if (_M_data->_M_grouping_size)
523         delete [] _M_data->_M_grouping;
524       if (_M_data->_M_positive_sign_size)
525         delete [] _M_data->_M_positive_sign;
526       if (_M_data->_M_negative_sign_size
527           && strcmp(_M_data->_M_negative_sign, "()") != 0)
528         delete [] _M_data->_M_negative_sign;
529       if (_M_data->_M_curr_symbol_size)
530         delete [] _M_data->_M_curr_symbol;
531       delete _M_data;
532     }
533
534 #ifdef _GLIBCXX_USE_WCHAR_T
535   template<> 
536     void
537     moneypunct<wchar_t, true>::_M_initialize_moneypunct(__c_locale __cloc, 
538 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
539                                                         const char*)
540 #else
541                                                         const char* __name)
542 #endif
543     {
544       if (!_M_data)
545         _M_data = new __moneypunct_cache<wchar_t, true>;
546
547       if (!__cloc)
548         {
549           // "C" locale
550           _M_data->_M_decimal_point = L'.';
551           _M_data->_M_thousands_sep = L',';
552           _M_data->_M_grouping = "";
553           _M_data->_M_grouping_size = 0;
554           _M_data->_M_use_grouping = false;
555           _M_data->_M_curr_symbol = L"";
556           _M_data->_M_curr_symbol_size = 0;
557           _M_data->_M_positive_sign = L"";
558           _M_data->_M_positive_sign_size = 0;
559           _M_data->_M_negative_sign = L"";
560           _M_data->_M_negative_sign_size = 0;
561           _M_data->_M_frac_digits = 0;
562           _M_data->_M_pos_format = money_base::_S_default_pattern;
563           _M_data->_M_neg_format = money_base::_S_default_pattern;
564
565           // Use ctype::widen code without the facet...
566           for (size_t __i = 0; __i < money_base::_S_end; ++__i)
567             _M_data->_M_atoms[__i] =
568               static_cast<wchar_t>(money_base::_S_atoms[__i]);
569         }
570       else
571         {
572           // Named locale.
573 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
574           __c_locale __old = __uselocale(__cloc);
575 #else
576           // Switch to named locale so that mbsrtowcs will work.
577           char* __old = setlocale(LC_ALL, NULL);
578           const size_t __llen = strlen(__old) + 1;
579           char* __sav = new char[__llen];
580           memcpy(__sav, __old, __llen);
581           setlocale(LC_ALL, __name);
582 #endif
583
584           union { char *__s; wchar_t __w; } __u;
585           __u.__s = __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC, __cloc);
586           _M_data->_M_decimal_point = __u.__w;
587
588           __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc);
589           _M_data->_M_thousands_sep = __u.__w;
590
591           // Check for NULL, which implies no fractional digits.
592           if (_M_data->_M_decimal_point == L'\0')
593             {
594               // Like in "C" locale.
595               _M_data->_M_frac_digits = 0;
596               _M_data->_M_decimal_point = L'.';
597             }
598           else
599             _M_data->_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS, 
600                                                         __cloc));
601
602           const char* __cgroup = __nl_langinfo_l(__MON_GROUPING, __cloc);
603           const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
604           const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
605           const char* __ccurr = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc);
606
607           char* __group = 0;
608           wchar_t* __wcs_ps = 0;
609           wchar_t* __wcs_ns = 0;
610           const char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc));
611           __try
612             {
613               size_t __len;
614
615               // Check for NULL, which implies no grouping.
616               if (_M_data->_M_thousands_sep == L'\0')
617                 {
618                   // Like in "C" locale.
619                   _M_data->_M_grouping = "";
620                   _M_data->_M_grouping_size = 0;
621                   _M_data->_M_use_grouping = false;
622                   _M_data->_M_thousands_sep = L',';
623                 }
624               else
625                 {
626                   __len = strlen(__cgroup);
627                   if (__len)
628                     {
629                       __group = new char[__len + 1];
630                       memcpy(__group, __cgroup, __len + 1);
631                       _M_data->_M_grouping = __group;
632                     }
633                   else
634                     {
635                       _M_data->_M_grouping = "";
636                       _M_data->_M_use_grouping = false;
637                     }
638                   _M_data->_M_grouping_size = __len;
639                 }
640
641               mbstate_t __state;
642               __len = strlen(__cpossign);
643               if (__len)
644                 {
645                   memset(&__state, 0, sizeof(mbstate_t));
646                   __wcs_ps = new wchar_t[__len + 1];
647                   mbsrtowcs(__wcs_ps, &__cpossign, __len + 1, &__state);
648                   _M_data->_M_positive_sign = __wcs_ps;
649                 }
650               else
651                 _M_data->_M_positive_sign = L"";
652               _M_data->_M_positive_sign_size = 
653                 wcslen(_M_data->_M_positive_sign);
654               
655               __len = strlen(__cnegsign);
656               if (!__nposn)
657                 _M_data->_M_negative_sign = L"()";
658               else if (__len)
659                 {
660                   memset(&__state, 0, sizeof(mbstate_t));
661                   __wcs_ns = new wchar_t[__len + 1];
662                   mbsrtowcs(__wcs_ns, &__cnegsign, __len + 1, &__state);
663                   _M_data->_M_negative_sign = __wcs_ns;
664                 }
665               else
666                 _M_data->_M_negative_sign = L"";
667               _M_data->_M_negative_sign_size = 
668                 wcslen(_M_data->_M_negative_sign);
669               
670               // _Intl == true.
671               __len = strlen(__ccurr);
672               if (__len)
673                 {
674                   memset(&__state, 0, sizeof(mbstate_t));
675                   wchar_t* __wcs = new wchar_t[__len + 1];
676                   mbsrtowcs(__wcs, &__ccurr, __len + 1, &__state);
677                   _M_data->_M_curr_symbol = __wcs;
678                 }
679               else
680                 _M_data->_M_curr_symbol = L"";
681               _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol);
682             }
683           __catch(...)
684             {
685               delete _M_data;
686               _M_data = 0;
687               delete [] __group;
688               delete [] __wcs_ps;
689               delete [] __wcs_ns;             
690 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
691               __uselocale(__old);
692 #else
693               setlocale(LC_ALL, __sav);
694               delete [] __sav;
695 #endif
696               __throw_exception_again;
697             } 
698           
699           char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc));
700           char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc));
701           char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc));
702           _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
703                                                         __pposn);
704           char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc));
705           char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc));
706           _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
707                                                         __nposn);
708
709 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
710           __uselocale(__old);
711 #else
712           setlocale(LC_ALL, __sav);
713           delete [] __sav;
714 #endif
715         }
716     }
717
718   template<> 
719   void
720   moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc,
721 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
722                                                        const char*)
723 #else
724                                                        const char* __name)
725 #endif
726   {
727     if (!_M_data)
728       _M_data = new __moneypunct_cache<wchar_t, false>;
729
730     if (!__cloc)
731         {
732           // "C" locale
733           _M_data->_M_decimal_point = L'.';
734           _M_data->_M_thousands_sep = L',';
735           _M_data->_M_grouping = "";
736           _M_data->_M_grouping_size = 0;
737           _M_data->_M_use_grouping = false;
738           _M_data->_M_curr_symbol = L"";
739           _M_data->_M_curr_symbol_size = 0;
740           _M_data->_M_positive_sign = L"";
741           _M_data->_M_positive_sign_size = 0;
742           _M_data->_M_negative_sign = L"";
743           _M_data->_M_negative_sign_size = 0;
744           _M_data->_M_frac_digits = 0;
745           _M_data->_M_pos_format = money_base::_S_default_pattern;
746           _M_data->_M_neg_format = money_base::_S_default_pattern;
747
748           // Use ctype::widen code without the facet...
749           for (size_t __i = 0; __i < money_base::_S_end; ++__i)
750             _M_data->_M_atoms[__i] =
751               static_cast<wchar_t>(money_base::_S_atoms[__i]);
752         }
753       else
754         {
755           // Named locale.
756 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
757           __c_locale __old = __uselocale(__cloc);
758 #else
759           // Switch to named locale so that mbsrtowcs will work.
760           char* __old = setlocale(LC_ALL, NULL);
761           const size_t __llen = strlen(__old) + 1;
762           char* __sav = new char[__llen];
763           memcpy(__sav, __old, __llen);
764           setlocale(LC_ALL, __name);
765 #endif
766
767           union { char *__s; wchar_t __w; } __u;
768           __u.__s = __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC, __cloc);
769           _M_data->_M_decimal_point = __u.__w;
770
771           __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc);
772           _M_data->_M_thousands_sep = __u.__w;
773
774           // Check for NULL, which implies no fractional digits.
775           if (_M_data->_M_decimal_point == L'\0')
776             {
777               // Like in "C" locale.
778               _M_data->_M_frac_digits = 0;
779               _M_data->_M_decimal_point = L'.';
780             }
781           else
782             _M_data->_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS,
783                                                         __cloc));
784
785           const char* __cgroup = __nl_langinfo_l(__MON_GROUPING, __cloc);
786           const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
787           const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
788           const char* __ccurr = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc);
789
790           char* __group = 0;
791           wchar_t* __wcs_ps = 0;
792           wchar_t* __wcs_ns = 0;
793           const char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc));
794           __try
795             {
796               size_t __len;
797
798               // Check for NULL, which implies no grouping.
799               if (_M_data->_M_thousands_sep == L'\0')
800                 {
801                   // Like in "C" locale.
802                   _M_data->_M_grouping = "";
803                   _M_data->_M_grouping_size = 0;
804                   _M_data->_M_use_grouping = false;
805                   _M_data->_M_thousands_sep = L',';
806                 }
807               else
808                 {
809                   __len = strlen(__cgroup);
810                   if (__len)
811                     {
812                       __group = new char[__len + 1];
813                       memcpy(__group, __cgroup, __len + 1);
814                       _M_data->_M_grouping = __group;
815                     }
816                   else
817                     {
818                       _M_data->_M_grouping = "";
819                       _M_data->_M_use_grouping = false;
820                     }
821                   _M_data->_M_grouping_size = __len;
822                 }
823
824               mbstate_t __state;
825               __len = strlen(__cpossign);
826               if (__len)
827                 {
828                   memset(&__state, 0, sizeof(mbstate_t));
829                   __wcs_ps = new wchar_t[__len + 1];
830                   mbsrtowcs(__wcs_ps, &__cpossign, __len + 1, &__state);
831                   _M_data->_M_positive_sign = __wcs_ps;
832                 }
833               else
834                 _M_data->_M_positive_sign = L"";
835               _M_data->_M_positive_sign_size = 
836                 wcslen(_M_data->_M_positive_sign);
837
838               __len = strlen(__cnegsign);
839               if (!__nposn)
840                 _M_data->_M_negative_sign = L"()";
841               else if (__len)
842                 {
843                   memset(&__state, 0, sizeof(mbstate_t));
844                   __wcs_ns = new wchar_t[__len + 1];
845                   mbsrtowcs(__wcs_ns, &__cnegsign, __len + 1, &__state);
846                   _M_data->_M_negative_sign = __wcs_ns;
847                 }
848               else
849                 _M_data->_M_negative_sign = L"";
850               _M_data->_M_negative_sign_size = 
851                 wcslen(_M_data->_M_negative_sign);
852
853               // _Intl == true.
854               __len = strlen(__ccurr);
855               if (__len)
856                 {
857                   memset(&__state, 0, sizeof(mbstate_t));
858                   wchar_t* __wcs = new wchar_t[__len + 1];
859                   mbsrtowcs(__wcs, &__ccurr, __len + 1, &__state);
860                   _M_data->_M_curr_symbol = __wcs;
861                 }
862               else
863                 _M_data->_M_curr_symbol = L"";
864               _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol);
865             }
866           __catch(...)
867             {
868               delete _M_data;
869               _M_data = 0;
870               delete [] __group;
871               delete [] __wcs_ps;
872               delete [] __wcs_ns;             
873 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
874               __uselocale(__old);
875 #else
876               setlocale(LC_ALL, __sav);
877               delete [] __sav;
878 #endif
879               __throw_exception_again;
880             }
881
882           char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc));
883           char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc));
884           char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc));
885           _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
886                                                         __pposn);
887           char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc));
888           char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc));
889           _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
890                                                         __nposn);
891
892 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
893           __uselocale(__old);
894 #else
895           setlocale(LC_ALL, __sav);
896           delete [] __sav;
897 #endif
898         }
899     }
900
901   template<> 
902     moneypunct<wchar_t, true>::~moneypunct()
903     {
904       if (_M_data->_M_grouping_size)
905         delete [] _M_data->_M_grouping;
906       if (_M_data->_M_positive_sign_size)
907         delete [] _M_data->_M_positive_sign;
908       if (_M_data->_M_negative_sign_size
909           && wcscmp(_M_data->_M_negative_sign, L"()") != 0)
910         delete [] _M_data->_M_negative_sign;
911       if (_M_data->_M_curr_symbol_size)
912         delete [] _M_data->_M_curr_symbol;
913       delete _M_data;
914     }
915
916   template<> 
917     moneypunct<wchar_t, false>::~moneypunct()
918     {
919       if (_M_data->_M_grouping_size)
920         delete [] _M_data->_M_grouping;
921       if (_M_data->_M_positive_sign_size)
922         delete [] _M_data->_M_positive_sign;
923       if (_M_data->_M_negative_sign_size
924           && wcscmp(_M_data->_M_negative_sign, L"()") != 0)
925         delete [] _M_data->_M_negative_sign;
926       if (_M_data->_M_curr_symbol_size)
927         delete [] _M_data->_M_curr_symbol;
928       delete _M_data;
929     }
930 #endif
931
932 _GLIBCXX_END_NAMESPACE