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