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