1 // std::moneypunct implementation details, GNU version -*- C++ -*-
2 
3 // Copyright (C) 2001-2020 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