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