xref: /netbsd-src/external/gpl3/gcc.old/dist/libstdc++-v3/config/locale/gnu/monetary_members.cc (revision d90047b5d07facf36e6c01dcc0bded8997ce9cc2)
1 // std::moneypunct implementation details, GNU version -*- C++ -*-
2 
3 // Copyright (C) 2001-2017 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
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   template<>
211     void
212     moneypunct<char, true>::_M_initialize_moneypunct(__c_locale __cloc,
213 						     const char*)
214     {
215       if (!_M_data)
216 	_M_data = new __moneypunct_cache<char, true>;
217 
218       if (!__cloc)
219 	{
220 	  // "C" locale
221 	  _M_data->_M_decimal_point = '.';
222 	  _M_data->_M_thousands_sep = ',';
223 	  _M_data->_M_grouping = "";
224 	  _M_data->_M_grouping_size = 0;
225 	  _M_data->_M_use_grouping = false;
226 	  _M_data->_M_curr_symbol = "";
227 	  _M_data->_M_curr_symbol_size = 0;
228 	  _M_data->_M_positive_sign = "";
229 	  _M_data->_M_positive_sign_size = 0;
230 	  _M_data->_M_negative_sign = "";
231 	  _M_data->_M_negative_sign_size = 0;
232 	  _M_data->_M_frac_digits = 0;
233 	  _M_data->_M_pos_format = money_base::_S_default_pattern;
234 	  _M_data->_M_neg_format = money_base::_S_default_pattern;
235 
236 	  for (size_t __i = 0; __i < money_base::_S_end; ++__i)
237 	    _M_data->_M_atoms[__i] = money_base::_S_atoms[__i];
238 	}
239       else
240 	{
241 	  // Named locale.
242 	  _M_data->_M_decimal_point = *(__nl_langinfo_l(__MON_DECIMAL_POINT,
243 							__cloc));
244 	  _M_data->_M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP,
245 							__cloc));
246 
247 	  // Check for NULL, which implies no fractional digits.
248 	  if (_M_data->_M_decimal_point == '\0')
249 	    {
250 	      // Like in "C" locale.
251 	      _M_data->_M_frac_digits = 0;
252 	      _M_data->_M_decimal_point = '.';
253 	    }
254 	  else
255 	    _M_data->_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS,
256 							__cloc));
257 
258 	  const char* __cgroup = __nl_langinfo_l(__MON_GROUPING, __cloc);
259 	  const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
260 	  const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
261 	  // _Intl == true
262 	  const char* __ccurr = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc);
263 
264 	  char* __group = 0;
265 	  char* __ps = 0;
266 	  char* __ns = 0;
267 	  const char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc));
268 	  __try
269 	    {
270 	      size_t __len;
271 
272 	      // Check for NULL, which implies no grouping.
273 	      if (_M_data->_M_thousands_sep == '\0')
274 		{
275 		  // Like in "C" locale.
276 		  _M_data->_M_grouping = "";
277 		  _M_data->_M_grouping_size = 0;
278 		  _M_data->_M_use_grouping = false;
279 		  _M_data->_M_thousands_sep = ',';
280 		}
281 	      else
282 		{
283 		  __len = strlen(__cgroup);
284 		  if (__len)
285 		    {
286 		      __group = new char[__len + 1];
287 		      memcpy(__group, __cgroup, __len + 1);
288 		      _M_data->_M_grouping = __group;
289 		    }
290 		  else
291 		    {
292 		      _M_data->_M_grouping = "";
293 		      _M_data->_M_use_grouping = false;
294 		    }
295 		  _M_data->_M_grouping_size = __len;
296 		}
297 
298 	      __len = strlen(__cpossign);
299 	      if (__len)
300 		{
301 		  __ps = new char[__len + 1];
302 		  memcpy(__ps, __cpossign, __len + 1);
303 		  _M_data->_M_positive_sign = __ps;
304 		}
305 	      else
306 		_M_data->_M_positive_sign = "";
307 	      _M_data->_M_positive_sign_size = __len;
308 
309 	      if (!__nposn)
310 		{
311 		  _M_data->_M_negative_sign = "()";
312 		  _M_data->_M_negative_sign_size = 2;
313 		}
314 	      else
315 		{
316 		  __len = strlen(__cnegsign);
317 		  if (__len)
318 		    {
319 		      __ns = new char[__len + 1];
320 		      memcpy(__ns, __cnegsign, __len + 1);
321 		      _M_data->_M_negative_sign = __ns;
322 		    }
323 		  else
324 		    _M_data->_M_negative_sign = "";
325 		  _M_data->_M_negative_sign_size = __len;
326 		}
327 
328 	      __len = strlen(__ccurr);
329 	      if (__len)
330 		{
331 		  char* __curr = new char[__len + 1];
332 		  memcpy(__curr, __ccurr, __len + 1);
333 		  _M_data->_M_curr_symbol = __curr;
334 		}
335 	      else
336 		_M_data->_M_curr_symbol = "";
337 	      _M_data->_M_curr_symbol_size = __len;
338 	    }
339 	  __catch(...)
340 	    {
341 	      delete _M_data;
342 	      _M_data = 0;
343 	      delete [] __group;
344 	      delete [] __ps;
345 	      delete [] __ns;
346 	      __throw_exception_again;
347 	    }
348 
349 	  char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc));
350 	  char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc));
351 	  char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc));
352 	  _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
353 							__pposn);
354 	  char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc));
355 	  char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc));
356 	  _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
357 							__nposn);
358 	}
359     }
360 
361   template<>
362     void
363     moneypunct<char, false>::_M_initialize_moneypunct(__c_locale __cloc,
364 						      const char*)
365     {
366       if (!_M_data)
367 	_M_data = new __moneypunct_cache<char, false>;
368 
369       if (!__cloc)
370 	{
371 	  // "C" locale
372 	  _M_data->_M_decimal_point = '.';
373 	  _M_data->_M_thousands_sep = ',';
374 	  _M_data->_M_grouping = "";
375 	  _M_data->_M_grouping_size = 0;
376 	  _M_data->_M_use_grouping = false;
377 	  _M_data->_M_curr_symbol = "";
378 	  _M_data->_M_curr_symbol_size = 0;
379 	  _M_data->_M_positive_sign = "";
380 	  _M_data->_M_positive_sign_size = 0;
381 	  _M_data->_M_negative_sign = "";
382 	  _M_data->_M_negative_sign_size = 0;
383 	  _M_data->_M_frac_digits = 0;
384 	  _M_data->_M_pos_format = money_base::_S_default_pattern;
385 	  _M_data->_M_neg_format = money_base::_S_default_pattern;
386 
387 	  for (size_t __i = 0; __i < money_base::_S_end; ++__i)
388 	    _M_data->_M_atoms[__i] = money_base::_S_atoms[__i];
389 	}
390       else
391 	{
392 	  // Named locale.
393 	  _M_data->_M_decimal_point = *(__nl_langinfo_l(__MON_DECIMAL_POINT,
394 							__cloc));
395 	  _M_data->_M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP,
396 							__cloc));
397 
398 	  // Check for NULL, which implies no fractional digits.
399 	  if (_M_data->_M_decimal_point == '\0')
400 	    {
401 	      // Like in "C" locale.
402 	      _M_data->_M_frac_digits = 0;
403 	      _M_data->_M_decimal_point = '.';
404 	    }
405 	  else
406 	    _M_data->_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS,
407 							__cloc));
408 
409 	  const char* __cgroup = __nl_langinfo_l(__MON_GROUPING, __cloc);
410 	  const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
411 	  const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
412 	  // _Intl == false
413 	  const char* __ccurr = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc);
414 
415 	  char* __group = 0;
416 	  char* __ps = 0;
417 	  char* __ns = 0;
418 	  const char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc));
419 	  __try
420 	    {
421 	      size_t __len;
422 
423 	      // Check for NULL, which implies no grouping.
424 	      if (_M_data->_M_thousands_sep == '\0')
425 		{
426 		  // Like in "C" locale.
427 		  _M_data->_M_grouping = "";
428 		  _M_data->_M_grouping_size = 0;
429 		  _M_data->_M_use_grouping = false;
430 		  _M_data->_M_thousands_sep = ',';
431 		}
432 	      else
433 		{
434 		  __len = strlen(__cgroup);
435 		  if (__len)
436 		    {
437 		      __group = new char[__len + 1];
438 		      memcpy(__group, __cgroup, __len + 1);
439 		      _M_data->_M_grouping = __group;
440 		    }
441 		  else
442 		    {
443 		      _M_data->_M_grouping = "";
444 		      _M_data->_M_use_grouping = false;
445 		    }
446 		  _M_data->_M_grouping_size = __len;
447 		}
448 
449 	      __len = strlen(__cpossign);
450 	      if (__len)
451 		{
452 		  __ps = new char[__len + 1];
453 		  memcpy(__ps, __cpossign, __len + 1);
454 		  _M_data->_M_positive_sign = __ps;
455 		}
456 	      else
457 		_M_data->_M_positive_sign = "";
458 	      _M_data->_M_positive_sign_size = __len;
459 
460 	      if (!__nposn)
461 		{
462 		  _M_data->_M_negative_sign = "()";
463 		  _M_data->_M_negative_sign_size = 2;
464 		}
465 	      else
466 		{
467 		  __len = strlen(__cnegsign);
468 		  if (__len)
469 		    {
470 		      __ns = new char[__len + 1];
471 		      memcpy(__ns, __cnegsign, __len + 1);
472 		      _M_data->_M_negative_sign = __ns;
473 		    }
474 		  else
475 		    _M_data->_M_negative_sign = "";
476 		  _M_data->_M_negative_sign_size = __len;
477 		}
478 
479 	      __len = strlen(__ccurr);
480 	      if (__len)
481 		{
482 		  char* __curr = new char[__len + 1];
483 		  memcpy(__curr, __ccurr, __len + 1);
484 		  _M_data->_M_curr_symbol = __curr;
485 		}
486 	      else
487 		_M_data->_M_curr_symbol = "";
488 	      _M_data->_M_curr_symbol_size = __len;
489 	    }
490 	  __catch(...)
491 	    {
492 	      delete _M_data;
493 	      _M_data = 0;
494 	      delete [] __group;
495 	      delete [] __ps;
496 	      delete [] __ns;
497 	      __throw_exception_again;
498 	    }
499 
500 	  char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc));
501 	  char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc));
502 	  char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc));
503 	  _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
504 							__pposn);
505 	  char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc));
506 	  char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc));
507 	  _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
508 							__nposn);
509 	}
510     }
511 
512   template<>
513     moneypunct<char, true>::~moneypunct()
514     {
515       if (_M_data->_M_grouping_size)
516 	delete [] _M_data->_M_grouping;
517       if (_M_data->_M_positive_sign_size)
518 	delete [] _M_data->_M_positive_sign;
519       if (_M_data->_M_negative_sign_size
520           && strcmp(_M_data->_M_negative_sign, "()") != 0)
521 	delete [] _M_data->_M_negative_sign;
522       if (_M_data->_M_curr_symbol_size)
523 	delete [] _M_data->_M_curr_symbol;
524       delete _M_data;
525     }
526 
527   template<>
528     moneypunct<char, false>::~moneypunct()
529     {
530       if (_M_data->_M_grouping_size)
531 	delete [] _M_data->_M_grouping;
532       if (_M_data->_M_positive_sign_size)
533 	delete [] _M_data->_M_positive_sign;
534       if (_M_data->_M_negative_sign_size
535           && strcmp(_M_data->_M_negative_sign, "()") != 0)
536 	delete [] _M_data->_M_negative_sign;
537       if (_M_data->_M_curr_symbol_size)
538 	delete [] _M_data->_M_curr_symbol;
539       delete _M_data;
540     }
541 
542 #ifdef _GLIBCXX_USE_WCHAR_T
543   template<>
544     void
545     moneypunct<wchar_t, true>::_M_initialize_moneypunct(__c_locale __cloc,
546 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
547 							const char*)
548 #else
549 							const char* __name)
550 #endif
551     {
552       if (!_M_data)
553 	_M_data = new __moneypunct_cache<wchar_t, true>;
554 
555       if (!__cloc)
556 	{
557 	  // "C" locale
558 	  _M_data->_M_decimal_point = L'.';
559 	  _M_data->_M_thousands_sep = L',';
560 	  _M_data->_M_grouping = "";
561 	  _M_data->_M_grouping_size = 0;
562 	  _M_data->_M_use_grouping = false;
563 	  _M_data->_M_curr_symbol = L"";
564 	  _M_data->_M_curr_symbol_size = 0;
565 	  _M_data->_M_positive_sign = L"";
566 	  _M_data->_M_positive_sign_size = 0;
567 	  _M_data->_M_negative_sign = L"";
568 	  _M_data->_M_negative_sign_size = 0;
569 	  _M_data->_M_frac_digits = 0;
570 	  _M_data->_M_pos_format = money_base::_S_default_pattern;
571 	  _M_data->_M_neg_format = money_base::_S_default_pattern;
572 
573 	  // Use ctype::widen code without the facet...
574 	  for (size_t __i = 0; __i < money_base::_S_end; ++__i)
575 	    _M_data->_M_atoms[__i] =
576 	      static_cast<wchar_t>(money_base::_S_atoms[__i]);
577 	}
578       else
579 	{
580 	  // Named locale.
581 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
582 	  __c_locale __old = __uselocale(__cloc);
583 #else
584 	  // Switch to named locale so that mbsrtowcs will work.
585 	  char* __old = setlocale(LC_ALL, 0);
586           const size_t __llen = strlen(__old) + 1;
587           char* __sav = new char[__llen];
588           memcpy(__sav, __old, __llen);
589 	  setlocale(LC_ALL, __name);
590 #endif
591 
592 	  union { char *__s; wchar_t __w; } __u;
593 	  __u.__s = __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC, __cloc);
594 	  _M_data->_M_decimal_point = __u.__w;
595 
596 	  __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc);
597 	  _M_data->_M_thousands_sep = __u.__w;
598 
599 	  // Check for NULL, which implies no fractional digits.
600 	  if (_M_data->_M_decimal_point == L'\0')
601 	    {
602 	      // Like in "C" locale.
603 	      _M_data->_M_frac_digits = 0;
604 	      _M_data->_M_decimal_point = L'.';
605 	    }
606 	  else
607 	    _M_data->_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS,
608 							__cloc));
609 
610 	  const char* __cgroup = __nl_langinfo_l(__MON_GROUPING, __cloc);
611 	  const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
612 	  const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
613 	  const char* __ccurr = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc);
614 
615 	  char* __group = 0;
616 	  wchar_t* __wcs_ps = 0;
617 	  wchar_t* __wcs_ns = 0;
618 	  const char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc));
619 	  __try
620 	    {
621 	      size_t __len;
622 
623 	      // Check for NULL, which implies no grouping.
624 	      if (_M_data->_M_thousands_sep == L'\0')
625 		{
626 		  // Like in "C" locale.
627 		  _M_data->_M_grouping = "";
628 		  _M_data->_M_grouping_size = 0;
629 		  _M_data->_M_use_grouping = false;
630 		  _M_data->_M_thousands_sep = L',';
631 		}
632 	      else
633 		{
634 		  __len = strlen(__cgroup);
635 		  if (__len)
636 		    {
637 		      __group = new char[__len + 1];
638 		      memcpy(__group, __cgroup, __len + 1);
639 		      _M_data->_M_grouping = __group;
640 		    }
641 		  else
642 		    {
643 		      _M_data->_M_grouping = "";
644 		      _M_data->_M_use_grouping = false;
645 		    }
646 		  _M_data->_M_grouping_size = __len;
647 		}
648 
649 	      mbstate_t __state;
650 	      __len = strlen(__cpossign);
651 	      if (__len)
652 		{
653 		  memset(&__state, 0, sizeof(mbstate_t));
654 		  __wcs_ps = new wchar_t[__len + 1];
655 		  mbsrtowcs(__wcs_ps, &__cpossign, __len + 1, &__state);
656 		  _M_data->_M_positive_sign = __wcs_ps;
657 		}
658 	      else
659 		_M_data->_M_positive_sign = L"";
660 	      _M_data->_M_positive_sign_size =
661 		wcslen(_M_data->_M_positive_sign);
662 
663 	      __len = strlen(__cnegsign);
664 	      if (!__nposn)
665 		_M_data->_M_negative_sign = L"()";
666 	      else if (__len)
667 		{
668 		  memset(&__state, 0, sizeof(mbstate_t));
669 		  __wcs_ns = new wchar_t[__len + 1];
670 		  mbsrtowcs(__wcs_ns, &__cnegsign, __len + 1, &__state);
671 		  _M_data->_M_negative_sign = __wcs_ns;
672 		}
673 	      else
674 		_M_data->_M_negative_sign = L"";
675 	      _M_data->_M_negative_sign_size =
676 		wcslen(_M_data->_M_negative_sign);
677 
678 	      // _Intl == true.
679 	      __len = strlen(__ccurr);
680 	      if (__len)
681 		{
682 		  memset(&__state, 0, sizeof(mbstate_t));
683 		  wchar_t* __wcs = new wchar_t[__len + 1];
684 		  mbsrtowcs(__wcs, &__ccurr, __len + 1, &__state);
685 		  _M_data->_M_curr_symbol = __wcs;
686 		}
687 	      else
688 		_M_data->_M_curr_symbol = L"";
689 	      _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol);
690 	    }
691 	  __catch(...)
692 	    {
693 	      delete _M_data;
694 	      _M_data = 0;
695 	      delete [] __group;
696 	      delete [] __wcs_ps;
697 	      delete [] __wcs_ns;
698 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
699 	      __uselocale(__old);
700 #else
701 	      setlocale(LC_ALL, __sav);
702 	      delete [] __sav;
703 #endif
704 	      __throw_exception_again;
705 	    }
706 
707 	  char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc));
708 	  char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc));
709 	  char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc));
710 	  _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
711 							__pposn);
712 	  char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc));
713 	  char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc));
714 	  _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
715 							__nposn);
716 
717 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
718 	  __uselocale(__old);
719 #else
720 	  setlocale(LC_ALL, __sav);
721 	  delete [] __sav;
722 #endif
723 	}
724     }
725 
726   template<>
727   void
728   moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc,
729 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
730 						       const char*)
731 #else
732                                                        const char* __name)
733 #endif
734   {
735     if (!_M_data)
736       _M_data = new __moneypunct_cache<wchar_t, false>;
737 
738     if (!__cloc)
739 	{
740 	  // "C" locale
741 	  _M_data->_M_decimal_point = L'.';
742 	  _M_data->_M_thousands_sep = L',';
743 	  _M_data->_M_grouping = "";
744           _M_data->_M_grouping_size = 0;
745 	  _M_data->_M_use_grouping = false;
746 	  _M_data->_M_curr_symbol = L"";
747 	  _M_data->_M_curr_symbol_size = 0;
748 	  _M_data->_M_positive_sign = L"";
749 	  _M_data->_M_positive_sign_size = 0;
750 	  _M_data->_M_negative_sign = L"";
751 	  _M_data->_M_negative_sign_size = 0;
752 	  _M_data->_M_frac_digits = 0;
753 	  _M_data->_M_pos_format = money_base::_S_default_pattern;
754 	  _M_data->_M_neg_format = money_base::_S_default_pattern;
755 
756 	  // Use ctype::widen code without the facet...
757 	  for (size_t __i = 0; __i < money_base::_S_end; ++__i)
758 	    _M_data->_M_atoms[__i] =
759 	      static_cast<wchar_t>(money_base::_S_atoms[__i]);
760 	}
761       else
762 	{
763 	  // Named locale.
764 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
765 	  __c_locale __old = __uselocale(__cloc);
766 #else
767 	  // Switch to named locale so that mbsrtowcs will work.
768 	  char* __old = setlocale(LC_ALL, 0);
769           const size_t __llen = strlen(__old) + 1;
770           char* __sav = new char[__llen];
771           memcpy(__sav, __old, __llen);
772 	  setlocale(LC_ALL, __name);
773 #endif
774 
775           union { char *__s; wchar_t __w; } __u;
776 	  __u.__s = __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC, __cloc);
777 	  _M_data->_M_decimal_point = __u.__w;
778 
779 	  __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc);
780 	  _M_data->_M_thousands_sep = __u.__w;
781 
782 	  // Check for NULL, which implies no fractional digits.
783 	  if (_M_data->_M_decimal_point == L'\0')
784 	    {
785 	      // Like in "C" locale.
786 	      _M_data->_M_frac_digits = 0;
787 	      _M_data->_M_decimal_point = L'.';
788 	    }
789 	  else
790 	    _M_data->_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS,
791 							__cloc));
792 
793 	  const char* __cgroup = __nl_langinfo_l(__MON_GROUPING, __cloc);
794 	  const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
795 	  const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
796 	  const char* __ccurr = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc);
797 
798 	  char* __group = 0;
799 	  wchar_t* __wcs_ps = 0;
800 	  wchar_t* __wcs_ns = 0;
801 	  const char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc));
802 	  __try
803             {
804 	      size_t __len;
805 
806 	      // Check for NULL, which implies no grouping.
807 	      if (_M_data->_M_thousands_sep == L'\0')
808 		{
809 		  // Like in "C" locale.
810 		  _M_data->_M_grouping = "";
811 		  _M_data->_M_grouping_size = 0;
812 		  _M_data->_M_use_grouping = false;
813 		  _M_data->_M_thousands_sep = L',';
814 		}
815 	      else
816 		{
817 		  __len = strlen(__cgroup);
818 		  if (__len)
819 		    {
820 		      __group = new char[__len + 1];
821 		      memcpy(__group, __cgroup, __len + 1);
822 		      _M_data->_M_grouping = __group;
823 		    }
824 		  else
825 		    {
826 		      _M_data->_M_grouping = "";
827 		      _M_data->_M_use_grouping = false;
828 		    }
829 		  _M_data->_M_grouping_size = __len;
830 		}
831 
832               mbstate_t __state;
833               __len = strlen(__cpossign);
834               if (__len)
835                 {
836 		  memset(&__state, 0, sizeof(mbstate_t));
837 		  __wcs_ps = new wchar_t[__len + 1];
838 		  mbsrtowcs(__wcs_ps, &__cpossign, __len + 1, &__state);
839 		  _M_data->_M_positive_sign = __wcs_ps;
840 		}
841 	      else
842 		_M_data->_M_positive_sign = L"";
843               _M_data->_M_positive_sign_size =
844 		wcslen(_M_data->_M_positive_sign);
845 
846 	      __len = strlen(__cnegsign);
847 	      if (!__nposn)
848 		_M_data->_M_negative_sign = L"()";
849 	      else if (__len)
850 		{
851 		  memset(&__state, 0, sizeof(mbstate_t));
852 		  __wcs_ns = new wchar_t[__len + 1];
853 		  mbsrtowcs(__wcs_ns, &__cnegsign, __len + 1, &__state);
854 		  _M_data->_M_negative_sign = __wcs_ns;
855 		}
856 	      else
857 		_M_data->_M_negative_sign = L"";
858               _M_data->_M_negative_sign_size =
859 		wcslen(_M_data->_M_negative_sign);
860 
861 	      // _Intl == true.
862 	      __len = strlen(__ccurr);
863 	      if (__len)
864 		{
865 		  memset(&__state, 0, sizeof(mbstate_t));
866 		  wchar_t* __wcs = new wchar_t[__len + 1];
867 		  mbsrtowcs(__wcs, &__ccurr, __len + 1, &__state);
868 		  _M_data->_M_curr_symbol = __wcs;
869 		}
870 	      else
871 		_M_data->_M_curr_symbol = L"";
872               _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol);
873 	    }
874           __catch(...)
875 	    {
876 	      delete _M_data;
877               _M_data = 0;
878 	      delete [] __group;
879 	      delete [] __wcs_ps;
880 	      delete [] __wcs_ns;
881 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
882 	      __uselocale(__old);
883 #else
884 	      setlocale(LC_ALL, __sav);
885 	      delete [] __sav;
886 #endif
887               __throw_exception_again;
888 	    }
889 
890 	  char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc));
891 	  char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc));
892 	  char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc));
893 	  _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
894 	                                                __pposn);
895 	  char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc));
896 	  char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc));
897 	  _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
898 	                                                __nposn);
899 
900 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
901 	  __uselocale(__old);
902 #else
903 	  setlocale(LC_ALL, __sav);
904 	  delete [] __sav;
905 #endif
906 	}
907     }
908 
909   template<>
910     moneypunct<wchar_t, true>::~moneypunct()
911     {
912       if (_M_data->_M_grouping_size)
913 	delete [] _M_data->_M_grouping;
914       if (_M_data->_M_positive_sign_size)
915 	delete [] _M_data->_M_positive_sign;
916       if (_M_data->_M_negative_sign_size
917           && wcscmp(_M_data->_M_negative_sign, L"()") != 0)
918 	delete [] _M_data->_M_negative_sign;
919       if (_M_data->_M_curr_symbol_size)
920 	delete [] _M_data->_M_curr_symbol;
921       delete _M_data;
922     }
923 
924   template<>
925     moneypunct<wchar_t, false>::~moneypunct()
926     {
927       if (_M_data->_M_grouping_size)
928 	delete [] _M_data->_M_grouping;
929       if (_M_data->_M_positive_sign_size)
930 	delete [] _M_data->_M_positive_sign;
931       if (_M_data->_M_negative_sign_size
932           && wcscmp(_M_data->_M_negative_sign, L"()") != 0)
933 	delete [] _M_data->_M_negative_sign;
934       if (_M_data->_M_curr_symbol_size)
935 	delete [] _M_data->_M_curr_symbol;
936       delete _M_data;
937     }
938 #endif
939 
940 _GLIBCXX_END_NAMESPACE_VERSION
941 } // namespace
942