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