gcc50: Add proper locale support to libstdc++ (local mod)
[dragonfly.git] / contrib / gcc-5.0 / libstdc++-v3 / config / locale / dragonfly / monetary_members.cc
1 // std::moneypunct implementation details, DragonFly version -*- C++ -*-
2
3 // Copyright (C) 2015 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 // Modified for DragonFly by John Marino <gnugcc@marino.st>
31
32 #include <locale>
33 #include <cstring>
34 #include <xlocale.h>
35
36 namespace std _GLIBCXX_VISIBILITY(default)
37 {
38 _GLIBCXX_BEGIN_NAMESPACE_VERSION
39
40 // This file might be compiled twice, but we only want to define the members
41 // of money_base once.
42 #if ! _GLIBCXX_USE_CXX11_ABI
43
44   // Construct and return valid pattern consisting of some combination of:
45   // space none symbol sign value
46   money_base::pattern
47   money_base::_S_construct_pattern(char __precedes, char __space, 
48                                    char __posn) throw()
49   { 
50     pattern __ret;
51
52     // This insanely complicated routine attempts to construct a valid
53     // pattern for use with moneypunct. A couple of invariants:
54
55     // if (__precedes) symbol -> value
56     // else value -> symbol
57     
58     // if (__space) space
59     // else none
60
61     // none == never first
62     // space never first or last
63
64     // Any elegant implementations of this are welcome.
65     switch (__posn)
66       {
67       case 0:
68       case 1:
69         // 1 The sign precedes the value and symbol.
70         __ret.field[0] = sign;
71         if (__space)
72           {
73             // Pattern starts with sign.
74             if (__precedes)
75               {
76                 __ret.field[1] = symbol;
77                 __ret.field[3] = value;
78               }
79             else
80               {
81                 __ret.field[1] = value;
82                 __ret.field[3] = symbol;
83               }
84             __ret.field[2] = space;
85           }
86         else
87           {
88             // Pattern starts with sign and ends with none.
89             if (__precedes)
90               {
91                 __ret.field[1] = symbol;
92                 __ret.field[2] = value;
93               }
94             else
95               {
96                 __ret.field[1] = value;
97                 __ret.field[2] = symbol;
98               }
99             __ret.field[3] = none;
100           }
101         break;
102       case 2:
103         // 2 The sign follows the value and symbol.
104         if (__space)
105           {
106             // Pattern either ends with sign.
107             if (__precedes)
108               {
109                 __ret.field[0] = symbol;
110                 __ret.field[2] = value;
111               }
112             else
113               {
114                 __ret.field[0] = value;
115                 __ret.field[2] = symbol;
116               }
117             __ret.field[1] = space;
118             __ret.field[3] = sign;
119           }
120         else
121           {
122             // Pattern ends with sign then none.
123             if (__precedes)
124               {
125                 __ret.field[0] = symbol;
126                 __ret.field[1] = value;
127               }
128             else
129               {
130                 __ret.field[0] = value;
131                 __ret.field[1] = symbol;
132               }
133             __ret.field[2] = sign;
134             __ret.field[3] = none;
135           }
136         break;
137       case 3:
138         // 3 The sign immediately precedes the symbol.
139         if (__precedes)
140           {
141             __ret.field[0] = sign;
142             __ret.field[1] = symbol;        
143             if (__space)
144               {
145                 __ret.field[2] = space;
146                 __ret.field[3] = value;
147               }
148             else
149               {
150                 __ret.field[2] = value;         
151                 __ret.field[3] = none;
152               }
153           }
154         else
155           {
156             __ret.field[0] = value;
157             if (__space)
158               {
159                 __ret.field[1] = space;
160                 __ret.field[2] = sign;
161                 __ret.field[3] = symbol;
162               }
163             else
164               {
165                 __ret.field[1] = sign;
166                 __ret.field[2] = symbol;
167                 __ret.field[3] = none;
168               }
169           }
170         break;
171       case 4:
172         // 4 The sign immediately follows the symbol.
173         if (__precedes)
174           {
175             __ret.field[0] = symbol;
176             __ret.field[1] = sign;
177             if (__space)
178               {
179                 __ret.field[2] = space;
180                 __ret.field[3] = value;
181               }
182             else
183               {
184                 __ret.field[2] = value;
185                 __ret.field[3] = none;
186               }
187           }
188         else
189           {
190             __ret.field[0] = value;
191             if (__space)
192               {
193                 __ret.field[1] = space;
194                 __ret.field[2] = symbol;
195                 __ret.field[3] = sign;
196               }
197             else
198               {
199                 __ret.field[1] = symbol;
200                 __ret.field[2] = sign;
201                 __ret.field[3] = none;
202               }
203           }
204         break;
205       default:
206         __ret = pattern();
207       }
208     return __ret;
209   }
210 #endif
211
212   template<>
213     void
214     moneypunct<char, true>::_M_initialize_moneypunct(__c_locale __cloc, 
215                                                      const char*)
216     {
217       if (!_M_data)
218         _M_data = new __moneypunct_cache<char, true>;
219
220       if (!__cloc)
221         {
222           // "C" locale
223           _M_data->_M_decimal_point = '.';
224           _M_data->_M_thousands_sep = ',';
225           _M_data->_M_grouping = "";
226           _M_data->_M_grouping_size = 0;
227           _M_data->_M_use_grouping = false;
228           _M_data->_M_curr_symbol = "";
229           _M_data->_M_curr_symbol_size = 0;
230           _M_data->_M_positive_sign = "";
231           _M_data->_M_positive_sign_size = 0;
232           _M_data->_M_negative_sign = "";
233           _M_data->_M_negative_sign_size = 0;
234           _M_data->_M_frac_digits = 0;
235           _M_data->_M_pos_format = money_base::_S_default_pattern;
236           _M_data->_M_neg_format = money_base::_S_default_pattern;
237
238           for (size_t __i = 0; __i < money_base::_S_end; ++__i)
239             _M_data->_M_atoms[__i] = money_base::_S_atoms[__i];
240         }
241       else
242         {
243           // Named locale.
244           lconv* lc = localeconv_l((locale_t) __cloc);
245
246           // Check for NULL, which implies no fractional digits.
247           if (lc->mon_decimal_point == NULL ||
248               lc->mon_decimal_point[0] == '\0')
249             {
250               // Like in "C" locale.
251               _M_data->_M_frac_digits = 0;
252               _M_data->_M_decimal_point = '.';
253             }
254           else
255             {
256               _M_data->_M_decimal_point = lc->mon_decimal_point[0];
257               _M_data->_M_frac_digits = lc->int_frac_digits;
258             }
259
260           const char* __cgroup = lc->mon_grouping;
261           const char* __cpossign = lc->positive_sign;
262           const char* __cnegsign = lc->negative_sign;
263           // _Intl == true
264           const char* __ccurr = lc->int_curr_symbol;
265
266           char* __group = 0;
267           char* __ps = 0;
268           char* __ns = 0;
269           const char __nposn = lc->int_n_sign_posn;
270           __try
271             {
272               size_t __len;
273               
274               // Check for NULL, which implies no grouping.
275               if (lc->mon_thousands_sep == NULL ||
276                   lc->mon_thousands_sep[0] == '\0')
277                 {
278                   // Like in "C" locale.
279                   _M_data->_M_grouping = "";
280                   _M_data->_M_grouping_size = 0;
281                   _M_data->_M_use_grouping = false;
282                   _M_data->_M_thousands_sep = ',';
283                 }
284               else
285                 {
286                   _M_data->_M_thousands_sep = lc->mon_thousands_sep[0];
287
288                   __len = strlen(__cgroup);
289                   if (__len)
290                     {
291                       __group = new char[__len + 1];
292                       memcpy(__group, __cgroup, __len + 1);
293                       _M_data->_M_grouping = __group;
294                     }
295                   else
296                     {
297                       _M_data->_M_grouping = "";
298                       _M_data->_M_use_grouping = false;
299                     }
300                   _M_data->_M_grouping_size = __len;
301                 }
302
303               __len = strlen(__cpossign);
304               if (__len)
305                 {
306                   __ps = new char[__len + 1];
307                   memcpy(__ps, __cpossign, __len + 1);
308                   _M_data->_M_positive_sign = __ps;
309                 }
310               else
311                 _M_data->_M_positive_sign = "";
312               _M_data->_M_positive_sign_size = __len;
313
314               if (!__nposn)
315                 {
316                   _M_data->_M_negative_sign = "()";
317                   _M_data->_M_negative_sign_size = 2;
318                 }
319               else
320                 {
321                   __len = strlen(__cnegsign);
322                   if (__len)
323                     {
324                       __ns = new char[__len + 1];
325                       memcpy(__ns, __cnegsign, __len + 1);
326                       _M_data->_M_negative_sign = __ns;
327                     }
328                   else
329                     _M_data->_M_negative_sign = "";
330                   _M_data->_M_negative_sign_size = __len;
331                 }
332
333               __len = strlen(__ccurr);
334               if (__len)
335                 {
336                   char* __curr = new char[__len + 1];
337                   memcpy(__curr, __ccurr, __len + 1);
338                   _M_data->_M_curr_symbol = __curr;
339                 }
340               else
341                 _M_data->_M_curr_symbol = "";
342               _M_data->_M_curr_symbol_size = __len;
343             }
344           __catch(...)
345             {
346               delete _M_data;
347               _M_data = 0;
348               delete [] __group;
349               delete [] __ps;
350               delete [] __ns;
351               __throw_exception_again;
352             }
353
354           char __pprecedes = lc->int_p_cs_precedes;
355           char __pspace = lc->int_p_sep_by_space;
356           char __pposn = lc->int_p_sign_posn;
357           _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
358                                                         __pposn);
359           char __nprecedes = lc->int_n_cs_precedes;
360           char __nspace = lc->int_n_sep_by_space;
361           _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
362                                                         __nposn);
363         }
364     }
365
366   template<>
367     void
368     moneypunct<char, false>::_M_initialize_moneypunct(__c_locale __cloc, 
369                                                       const char*)
370     {
371       if (!_M_data)
372         _M_data = new __moneypunct_cache<char, false>;
373
374       if (!__cloc)
375         {
376           // "C" locale
377           _M_data->_M_decimal_point = '.';
378           _M_data->_M_thousands_sep = ',';
379           _M_data->_M_grouping = "";
380           _M_data->_M_grouping_size = 0;
381           _M_data->_M_use_grouping = false;
382           _M_data->_M_curr_symbol = "";
383           _M_data->_M_curr_symbol_size = 0;
384           _M_data->_M_positive_sign = "";
385           _M_data->_M_positive_sign_size = 0;
386           _M_data->_M_negative_sign = "";
387           _M_data->_M_negative_sign_size = 0;
388           _M_data->_M_frac_digits = 0;
389           _M_data->_M_pos_format = money_base::_S_default_pattern;
390           _M_data->_M_neg_format = money_base::_S_default_pattern;
391
392           for (size_t __i = 0; __i < money_base::_S_end; ++__i)
393             _M_data->_M_atoms[__i] = money_base::_S_atoms[__i];
394         }
395       else
396         {
397           // Named locale.
398           lconv* lc = localeconv_l((locale_t) __cloc);
399
400           // Check for NULL, which implies no fractional digits.
401           if (lc->mon_decimal_point == NULL ||
402               lc->mon_decimal_point[0] == '\0')
403             {
404               // Like in "C" locale.
405               _M_data->_M_frac_digits = 0;
406               _M_data->_M_decimal_point = '.';
407             }
408           else
409             {
410               _M_data->_M_decimal_point = lc->mon_decimal_point[0];
411               _M_data->_M_frac_digits = lc->frac_digits;
412             }
413
414           const char* __cgroup = lc->mon_grouping;
415           const char* __cpossign = lc->positive_sign;
416           const char* __cnegsign = lc->negative_sign;
417           // _Intl == false
418           const char* __ccurr = lc->currency_symbol;
419
420           char* __group = 0;
421           char* __ps = 0;
422           char* __ns = 0;
423           const char __nposn = lc->n_sign_posn;
424           __try
425             {
426               size_t __len;
427
428               // Check for NULL, which implies no grouping.
429               if (lc->mon_thousands_sep == NULL ||
430                   lc->mon_thousands_sep[0] == '\0')
431                 {
432                   // Like in "C" locale.
433                   _M_data->_M_grouping = "";
434                   _M_data->_M_grouping_size = 0;
435                   _M_data->_M_use_grouping = false;
436                   _M_data->_M_thousands_sep = ',';
437                 }
438               else
439                 {
440                   _M_data->_M_thousands_sep = lc->mon_thousands_sep[0];
441
442                   __len = strlen(__cgroup);
443                   if (__len)
444                     {
445                       __group = new char[__len + 1];
446                       memcpy(__group, __cgroup, __len + 1);
447                       _M_data->_M_grouping = __group;
448                     }
449                   else
450                     {
451                       _M_data->_M_grouping = "";
452                       _M_data->_M_use_grouping = false;
453                     }
454                   _M_data->_M_grouping_size = __len;
455                 }
456
457               __len = strlen(__cpossign);
458               if (__len)
459                 {
460                   __ps = new char[__len + 1];
461                   memcpy(__ps, __cpossign, __len + 1);
462                   _M_data->_M_positive_sign = __ps;
463                 }
464               else
465                 _M_data->_M_positive_sign = "";
466               _M_data->_M_positive_sign_size = __len;
467
468               if (!__nposn)
469                 {
470                   _M_data->_M_negative_sign = "()";
471                   _M_data->_M_negative_sign_size = 2;
472                 }
473               else
474                 {
475                   __len = strlen(__cnegsign);
476                   if (__len)
477                     {
478                       __ns = new char[__len + 1];
479                       memcpy(__ns, __cnegsign, __len + 1);
480                       _M_data->_M_negative_sign = __ns;
481                     }
482                   else
483                     _M_data->_M_negative_sign = "";
484                   _M_data->_M_negative_sign_size = __len;
485                 }
486
487               __len = strlen(__ccurr);
488               if (__len)
489                 {
490                   char* __curr = new char[__len + 1];
491                   memcpy(__curr, __ccurr, __len + 1);
492                   _M_data->_M_curr_symbol = __curr;
493                 }
494               else
495                 _M_data->_M_curr_symbol = "";
496               _M_data->_M_curr_symbol_size = __len;
497             }
498           __catch(...)
499             {
500               delete _M_data;
501               _M_data = 0;
502               delete [] __group;
503               delete [] __ps;
504               delete [] __ns;
505               __throw_exception_again;
506             }
507
508           char __pprecedes = lc->p_cs_precedes;
509           char __pspace = lc->p_sep_by_space;
510           char __pposn = lc->p_sign_posn;
511           _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
512                                                         __pposn);
513           char __nprecedes = lc->n_cs_precedes;
514           char __nspace = lc->n_sep_by_space;
515           _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
516                                                         __nposn);
517         }
518     }
519
520   template<>
521     moneypunct<char, true>::~moneypunct()
522     {
523       if (_M_data->_M_grouping_size)
524         delete [] _M_data->_M_grouping;
525       if (_M_data->_M_positive_sign_size)
526         delete [] _M_data->_M_positive_sign;
527       if (_M_data->_M_negative_sign_size
528           && strcmp(_M_data->_M_negative_sign, "()") != 0)
529         delete [] _M_data->_M_negative_sign;
530       if (_M_data->_M_curr_symbol_size)
531         delete [] _M_data->_M_curr_symbol;
532       delete _M_data;
533     }
534
535   template<>
536     moneypunct<char, false>::~moneypunct()
537     {
538       if (_M_data->_M_grouping_size)
539         delete [] _M_data->_M_grouping;
540       if (_M_data->_M_positive_sign_size)
541         delete [] _M_data->_M_positive_sign;
542       if (_M_data->_M_negative_sign_size
543           && strcmp(_M_data->_M_negative_sign, "()") != 0)
544         delete [] _M_data->_M_negative_sign;
545       if (_M_data->_M_curr_symbol_size)
546         delete [] _M_data->_M_curr_symbol;
547       delete _M_data;
548     }
549
550 #ifdef _GLIBCXX_USE_WCHAR_T
551   template<>
552     void
553     moneypunct<wchar_t, true>::_M_initialize_moneypunct(__c_locale __cloc, 
554                                                         const char*)
555     {
556       if (!_M_data)
557         _M_data = new __moneypunct_cache<wchar_t, true>;
558
559       if (!__cloc)
560         {
561           // "C" locale
562           _M_data->_M_decimal_point = L'.';
563           _M_data->_M_thousands_sep = L',';
564           _M_data->_M_grouping = "";
565           _M_data->_M_grouping_size = 0;
566           _M_data->_M_use_grouping = false;
567           _M_data->_M_curr_symbol = L"";
568           _M_data->_M_curr_symbol_size = 0;
569           _M_data->_M_positive_sign = L"";
570           _M_data->_M_positive_sign_size = 0;
571           _M_data->_M_negative_sign = L"";
572           _M_data->_M_negative_sign_size = 0;
573           _M_data->_M_frac_digits = 0;
574           _M_data->_M_pos_format = money_base::_S_default_pattern;
575           _M_data->_M_neg_format = money_base::_S_default_pattern;
576
577           // Use ctype::widen code without the facet...
578           for (size_t __i = 0; __i < money_base::_S_end; ++__i)
579             _M_data->_M_atoms[__i] =
580               static_cast<wchar_t>(money_base::_S_atoms[__i]);
581         }
582       else
583         {
584           __c_locale __old = (__c_locale)uselocale((locale_t)__cloc);
585           // Named locale.
586           lconv* lc = localeconv_l((locale_t) __cloc);
587
588           // Check for NULL, which implies no fractional digits.
589           if (lc->mon_decimal_point == NULL ||
590               lc->mon_decimal_point[0] == '\0')
591             {
592               // Like in "C" locale.
593               _M_data->_M_frac_digits = 0;
594               _M_data->_M_decimal_point = L'.';
595             }
596           else
597             {
598               _M_data->_M_frac_digits = lc->int_frac_digits;
599               _M_data->_M_decimal_point = (wchar_t)lc->mon_decimal_point[0];
600             }
601
602           const char* __cgroup = lc->mon_grouping;
603           const char* __cpossign = lc->positive_sign;
604           const char* __cnegsign = lc->negative_sign;
605           const char* __ccurr = lc->int_curr_symbol;
606
607           char* __group = 0;
608           wchar_t* __wcs_ps = 0;
609           wchar_t* __wcs_ns = 0;
610           const char __nposn = lc->int_n_sign_posn;
611           __try
612             {
613               size_t __len;
614
615               // Check for NULL, which implies no grouping.
616               if (lc->mon_thousands_sep == NULL ||
617                   lc->mon_thousands_sep[0] == '\0')
618                 {
619                   // Like in "C" locale.
620                   _M_data->_M_grouping = "";
621                   _M_data->_M_grouping_size = 0;
622                   _M_data->_M_use_grouping = false;
623                   _M_data->_M_thousands_sep = L',';
624                 }
625               else
626                 {
627                   _M_data->_M_thousands_sep =
628                         (wchar_t)lc->mon_thousands_sep[0];
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               uselocale((locale_t)__old);
694               __throw_exception_again;
695             } 
696           
697           char __pprecedes = lc->int_p_cs_precedes;
698           char __pspace = lc->int_p_sep_by_space;
699           char __pposn = lc->int_p_sign_posn;
700           _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
701                                                         __pposn);
702           char __nprecedes = lc->int_n_cs_precedes;
703           char __nspace = lc->int_n_sep_by_space;
704           _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
705                                                         __nposn);
706
707           uselocale((locale_t)__old);
708         }
709     }
710
711   template<>
712   void
713   moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc,
714                                                        const char*)
715   {
716     if (!_M_data)
717       _M_data = new __moneypunct_cache<wchar_t, false>;
718
719     if (!__cloc)
720         {
721           // "C" locale
722           _M_data->_M_decimal_point = L'.';
723           _M_data->_M_thousands_sep = L',';
724           _M_data->_M_grouping = "";
725           _M_data->_M_grouping_size = 0;
726           _M_data->_M_use_grouping = false;
727           _M_data->_M_curr_symbol = L"";
728           _M_data->_M_curr_symbol_size = 0;
729           _M_data->_M_positive_sign = L"";
730           _M_data->_M_positive_sign_size = 0;
731           _M_data->_M_negative_sign = L"";
732           _M_data->_M_negative_sign_size = 0;
733           _M_data->_M_frac_digits = 0;
734           _M_data->_M_pos_format = money_base::_S_default_pattern;
735           _M_data->_M_neg_format = money_base::_S_default_pattern;
736
737           // Use ctype::widen code without the facet...
738           for (size_t __i = 0; __i < money_base::_S_end; ++__i)
739             _M_data->_M_atoms[__i] =
740               static_cast<wchar_t>(money_base::_S_atoms[__i]);
741         }
742       else
743         {
744           __c_locale __old = (__c_locale)uselocale((locale_t)__cloc);
745           // Named locale.
746           lconv* lc = localeconv_l((locale_t) __cloc);
747
748           // Check for NULL, which implies no fractional digits.
749           if (lc->mon_decimal_point == NULL ||
750               lc->mon_decimal_point[0] == '\0')
751             {
752               // Like in "C" locale.
753               _M_data->_M_frac_digits = 0;
754               _M_data->_M_decimal_point = L'.';
755             }
756           else
757             {
758               _M_data->_M_frac_digits = lc->frac_digits;
759               _M_data->_M_decimal_point = (wchar_t)lc->mon_decimal_point[0];
760             }
761
762           const char* __cgroup = lc->mon_grouping;
763           const char* __cpossign = lc->positive_sign;
764           const char* __cnegsign = lc->negative_sign;
765           const char* __ccurr = lc->currency_symbol;
766
767           char* __group = 0;
768           wchar_t* __wcs_ps = 0;
769           wchar_t* __wcs_ns = 0;
770           const char __nposn = lc->n_sign_posn;
771           __try
772             {
773               size_t __len;
774
775               // Check for NULL, which implies no grouping.
776               if (lc->mon_thousands_sep == NULL ||
777                   lc->mon_thousands_sep[0] == '\0')
778                 {
779                   // Like in "C" locale.
780                   _M_data->_M_grouping = "";
781                   _M_data->_M_grouping_size = 0;
782                   _M_data->_M_use_grouping = false;
783                   _M_data->_M_thousands_sep = L',';
784                 }
785               else
786                 {
787                   _M_data->_M_thousands_sep =
788                         (wchar_t)lc->mon_thousands_sep[0];
789                   __len = strlen(__cgroup);
790                   if (__len)
791                     {
792                       __group = new char[__len + 1];
793                       memcpy(__group, __cgroup, __len + 1);
794                       _M_data->_M_grouping = __group;
795                     }
796                   else
797                     {
798                       _M_data->_M_grouping = "";
799                       _M_data->_M_use_grouping = false;
800                     }
801                   _M_data->_M_grouping_size = __len;
802                 }
803
804               mbstate_t __state;
805               __len = strlen(__cpossign);
806               if (__len)
807                 {
808                   memset(&__state, 0, sizeof(mbstate_t));
809                   __wcs_ps = new wchar_t[__len + 1];
810                   mbsrtowcs(__wcs_ps, &__cpossign, __len + 1, &__state);
811                   _M_data->_M_positive_sign = __wcs_ps;
812                 }
813               else
814                 _M_data->_M_positive_sign = L"";
815               _M_data->_M_positive_sign_size = 
816                 wcslen(_M_data->_M_positive_sign);
817
818               __len = strlen(__cnegsign);
819               if (!__nposn)
820                 _M_data->_M_negative_sign = L"()";
821               else if (__len)
822                 {
823                   memset(&__state, 0, sizeof(mbstate_t));
824                   __wcs_ns = new wchar_t[__len + 1];
825                   mbsrtowcs(__wcs_ns, &__cnegsign, __len + 1, &__state);
826                   _M_data->_M_negative_sign = __wcs_ns;
827                 }
828               else
829                 _M_data->_M_negative_sign = L"";
830               _M_data->_M_negative_sign_size = 
831                 wcslen(_M_data->_M_negative_sign);
832
833               // _Intl == true.
834               __len = strlen(__ccurr);
835               if (__len)
836                 {
837                   memset(&__state, 0, sizeof(mbstate_t));
838                   wchar_t* __wcs = new wchar_t[__len + 1];
839                   mbsrtowcs(__wcs, &__ccurr, __len + 1, &__state);
840                   _M_data->_M_curr_symbol = __wcs;
841                 }
842               else
843                 _M_data->_M_curr_symbol = L"";
844               _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol);
845             }
846           __catch(...)
847             {
848               delete _M_data;
849               _M_data = 0;
850               delete [] __group;
851               delete [] __wcs_ps;
852               delete [] __wcs_ns;             
853               uselocale((locale_t)__old);
854               __throw_exception_again;
855             }
856
857           char __pprecedes = lc->p_cs_precedes;
858           char __pspace = lc->p_sep_by_space;
859           char __pposn = lc->p_sign_posn;
860           _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
861                                                         __pposn);
862           char __nprecedes = lc->n_cs_precedes;
863           char __nspace = lc->n_sep_by_space;
864           _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
865                                                         __nposn);
866
867           uselocale((locale_t)__old);
868         }
869     }
870
871   template<>
872     moneypunct<wchar_t, true>::~moneypunct()
873     {
874       if (_M_data->_M_grouping_size)
875         delete [] _M_data->_M_grouping;
876       if (_M_data->_M_positive_sign_size)
877         delete [] _M_data->_M_positive_sign;
878       if (_M_data->_M_negative_sign_size
879           && wcscmp(_M_data->_M_negative_sign, L"()") != 0)
880         delete [] _M_data->_M_negative_sign;
881       if (_M_data->_M_curr_symbol_size)
882         delete [] _M_data->_M_curr_symbol;
883       delete _M_data;
884     }
885
886   template<>
887     moneypunct<wchar_t, false>::~moneypunct()
888     {
889       if (_M_data->_M_grouping_size)
890         delete [] _M_data->_M_grouping;
891       if (_M_data->_M_positive_sign_size)
892         delete [] _M_data->_M_positive_sign;
893       if (_M_data->_M_negative_sign_size
894           && wcscmp(_M_data->_M_negative_sign, L"()") != 0)
895         delete [] _M_data->_M_negative_sign;
896       if (_M_data->_M_curr_symbol_size)
897         delete [] _M_data->_M_curr_symbol;
898       delete _M_data;
899     }
900 #endif
901
902 _GLIBCXX_END_NAMESPACE_VERSION
903 } // namespace