xref: /trueos/contrib/libstdc++/config/locale/gnu/monetary_members.cc (revision 7865836f4b0f698454c31b4593effcb032c22c1e)
1 // std::moneypunct implementation details, GNU version -*- C++ -*-
2 
3 // Copyright (C) 2001, 2002, 2003, 2004, 2005 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 2, 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 // You should have received a copy of the GNU General Public License along
17 // with this library; see the file COPYING.  If not, write to the Free
18 // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19 // USA.
20 
21 // As a special exception, you may use this file as part of a free software
22 // library without restriction.  Specifically, if other files instantiate
23 // templates or use macros or inline functions from this file, or you compile
24 // this file and link it with other files to produce an executable, this
25 // file does not by itself cause the resulting executable to be covered by
26 // the GNU General Public License.  This exception does not however
27 // invalidate any other reasons why the executable file might be covered by
28 // the GNU General Public License.
29 
30 //
31 // ISO C++ 14882: 22.2.6.3.2  moneypunct virtual functions
32 //
33 
34 // Written by Benjamin Kosnik <bkoz@redhat.com>
35 
36 #include <locale>
37 #include <bits/c++locale_internal.h>
38 
_GLIBCXX_BEGIN_NAMESPACE(std)39 _GLIBCXX_BEGIN_NAMESPACE(std)
40 
41   // Construct and return valid pattern consisting of some combination of:
42   // space none symbol sign value
43   money_base::pattern
44   money_base::_S_construct_pattern(char __precedes, char __space, char __posn)
45   {
46     pattern __ret;
47 
48     // This insanely complicated routine attempts to construct a valid
49     // pattern for use with monyepunct. A couple of invariants:
50 
51     // if (__precedes) symbol -> value
52     // else value -> symbol
53 
54     // if (__space) space
55     // else none
56 
57     // none == never first
58     // space never first or last
59 
60     // Any elegant implementations of this are welcome.
61     switch (__posn)
62       {
63       case 0:
64       case 1:
65 	// 1 The sign precedes the value and symbol.
66 	__ret.field[0] = sign;
67 	if (__space)
68 	  {
69 	    // Pattern starts with sign.
70 	    if (__precedes)
71 	      {
72 		__ret.field[1] = symbol;
73 		__ret.field[3] = value;
74 	      }
75 	    else
76 	      {
77 		__ret.field[1] = value;
78 		__ret.field[3] = symbol;
79 	      }
80 	    __ret.field[2] = space;
81 	  }
82 	else
83 	  {
84 	    // Pattern starts with sign and ends with none.
85 	    if (__precedes)
86 	      {
87 		__ret.field[1] = symbol;
88 		__ret.field[2] = value;
89 	      }
90 	    else
91 	      {
92 		__ret.field[1] = value;
93 		__ret.field[2] = symbol;
94 	      }
95 	    __ret.field[3] = none;
96 	  }
97 	break;
98       case 2:
99 	// 2 The sign follows the value and symbol.
100 	if (__space)
101 	  {
102 	    // Pattern either ends with sign.
103 	    if (__precedes)
104 	      {
105 		__ret.field[0] = symbol;
106 		__ret.field[2] = value;
107 	      }
108 	    else
109 	      {
110 		__ret.field[0] = value;
111 		__ret.field[2] = symbol;
112 	      }
113 	    __ret.field[1] = space;
114 	    __ret.field[3] = sign;
115 	  }
116 	else
117 	  {
118 	    // Pattern ends with sign then none.
119 	    if (__precedes)
120 	      {
121 		__ret.field[0] = symbol;
122 		__ret.field[1] = value;
123 	      }
124 	    else
125 	      {
126 		__ret.field[0] = value;
127 		__ret.field[1] = symbol;
128 	      }
129 	    __ret.field[2] = sign;
130 	    __ret.field[3] = none;
131 	  }
132 	break;
133       case 3:
134 	// 3 The sign immediately precedes the symbol.
135 	if (__precedes)
136 	  {
137 	    __ret.field[0] = sign;
138 	    __ret.field[1] = symbol;
139 	    if (__space)
140 	      {
141 		__ret.field[2] = space;
142 		__ret.field[3] = value;
143 	      }
144 	    else
145 	      {
146 		__ret.field[2] = value;
147 		__ret.field[3] = none;
148 	      }
149 	  }
150 	else
151 	  {
152 	    __ret.field[0] = value;
153 	    if (__space)
154 	      {
155 		__ret.field[1] = space;
156 		__ret.field[2] = sign;
157 		__ret.field[3] = symbol;
158 	      }
159 	    else
160 	      {
161 		__ret.field[1] = sign;
162 		__ret.field[2] = symbol;
163 		__ret.field[3] = none;
164 	      }
165 	  }
166 	break;
167       case 4:
168 	// 4 The sign immediately follows the symbol.
169 	if (__precedes)
170 	  {
171 	    __ret.field[0] = symbol;
172 	    __ret.field[1] = sign;
173 	    if (__space)
174 	      {
175 		__ret.field[2] = space;
176 		__ret.field[3] = value;
177 	      }
178 	    else
179 	      {
180 		__ret.field[2] = value;
181 		__ret.field[3] = none;
182 	      }
183 	  }
184 	else
185 	  {
186 	    __ret.field[0] = value;
187 	    if (__space)
188 	      {
189 		__ret.field[1] = space;
190 		__ret.field[2] = symbol;
191 		__ret.field[3] = sign;
192 	      }
193 	    else
194 	      {
195 		__ret.field[1] = symbol;
196 		__ret.field[2] = sign;
197 		__ret.field[3] = none;
198 	      }
199 	  }
200 	break;
201       default:
202 	__ret = pattern();
203       }
204     return __ret;
205   }
206 
207   template<>
208     void
_M_initialize_moneypunct(__c_locale __cloc,const char *)209     moneypunct<char, true>::_M_initialize_moneypunct(__c_locale __cloc,
210 						     const char*)
211     {
212       if (!_M_data)
213 	_M_data = new __moneypunct_cache<char, true>;
214 
215       if (!__cloc)
216 	{
217 	  // "C" locale
218 	  _M_data->_M_decimal_point = '.';
219 	  _M_data->_M_thousands_sep = ',';
220 	  _M_data->_M_grouping = "";
221 	  _M_data->_M_grouping_size = 0;
222 	  _M_data->_M_curr_symbol = "";
223 	  _M_data->_M_curr_symbol_size = 0;
224 	  _M_data->_M_positive_sign = "";
225 	  _M_data->_M_positive_sign_size = 0;
226 	  _M_data->_M_negative_sign = "";
227 	  _M_data->_M_negative_sign_size = 0;
228 	  _M_data->_M_frac_digits = 0;
229 	  _M_data->_M_pos_format = money_base::_S_default_pattern;
230 	  _M_data->_M_neg_format = money_base::_S_default_pattern;
231 
232 	  for (size_t __i = 0; __i < money_base::_S_end; ++__i)
233 	    _M_data->_M_atoms[__i] = money_base::_S_atoms[__i];
234 	}
235       else
236 	{
237 	  // Named locale.
238 	  _M_data->_M_decimal_point = *(__nl_langinfo_l(__MON_DECIMAL_POINT,
239 							__cloc));
240 	  _M_data->_M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP,
241 							__cloc));
242 	  _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
243 	  _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
244 	  _M_data->_M_positive_sign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
245 	  _M_data->_M_positive_sign_size = strlen(_M_data->_M_positive_sign);
246 
247 	  char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc));
248 	  if (!__nposn)
249 	    _M_data->_M_negative_sign = "()";
250 	  else
251 	    _M_data->_M_negative_sign = __nl_langinfo_l(__NEGATIVE_SIGN,
252 							__cloc);
253 	  _M_data->_M_negative_sign_size = strlen(_M_data->_M_negative_sign);
254 
255 	  // _Intl == true
256 	  _M_data->_M_curr_symbol = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc);
257 	  _M_data->_M_curr_symbol_size = strlen(_M_data->_M_curr_symbol);
258 	  _M_data->_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS,
259 						      __cloc));
260 	  char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc));
261 	  char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc));
262 	  char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc));
263 	  _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
264 							__pposn);
265 	  char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc));
266 	  char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc));
267 	  _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
268 							__nposn);
269 	}
270     }
271 
272   template<>
273     void
_M_initialize_moneypunct(__c_locale __cloc,const char *)274     moneypunct<char, false>::_M_initialize_moneypunct(__c_locale __cloc,
275 						      const char*)
276     {
277       if (!_M_data)
278 	_M_data = new __moneypunct_cache<char, false>;
279 
280       if (!__cloc)
281 	{
282 	  // "C" locale
283 	  _M_data->_M_decimal_point = '.';
284 	  _M_data->_M_thousands_sep = ',';
285 	  _M_data->_M_grouping = "";
286 	  _M_data->_M_grouping_size = 0;
287 	  _M_data->_M_curr_symbol = "";
288 	  _M_data->_M_curr_symbol_size = 0;
289 	  _M_data->_M_positive_sign = "";
290 	  _M_data->_M_positive_sign_size = 0;
291 	  _M_data->_M_negative_sign = "";
292 	  _M_data->_M_negative_sign_size = 0;
293 	  _M_data->_M_frac_digits = 0;
294 	  _M_data->_M_pos_format = money_base::_S_default_pattern;
295 	  _M_data->_M_neg_format = money_base::_S_default_pattern;
296 
297 	  for (size_t __i = 0; __i < money_base::_S_end; ++__i)
298 	    _M_data->_M_atoms[__i] = money_base::_S_atoms[__i];
299 	}
300       else
301 	{
302 	  // Named locale.
303 	  _M_data->_M_decimal_point = *(__nl_langinfo_l(__MON_DECIMAL_POINT,
304 							__cloc));
305 	  _M_data->_M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP,
306 							__cloc));
307 	  _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
308 	  _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
309 	  _M_data->_M_positive_sign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
310 	  _M_data->_M_positive_sign_size = strlen(_M_data->_M_positive_sign);
311 
312 	  char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc));
313 	  if (!__nposn)
314 	    _M_data->_M_negative_sign = "()";
315 	  else
316 	    _M_data->_M_negative_sign = __nl_langinfo_l(__NEGATIVE_SIGN,
317 							__cloc);
318 	  _M_data->_M_negative_sign_size = strlen(_M_data->_M_negative_sign);
319 
320 	  // _Intl == false
321 	  _M_data->_M_curr_symbol = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc);
322 	  _M_data->_M_curr_symbol_size = strlen(_M_data->_M_curr_symbol);
323 	  _M_data->_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc));
324 	  char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc));
325 	  char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc));
326 	  char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc));
327 	  _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
328 							__pposn);
329 	  char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc));
330 	  char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc));
331 	  _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
332 							__nposn);
333 	}
334     }
335 
336   template<>
~moneypunct()337     moneypunct<char, true>::~moneypunct()
338     { delete _M_data; }
339 
340   template<>
~moneypunct()341     moneypunct<char, false>::~moneypunct()
342     { delete _M_data; }
343 
344 #ifdef _GLIBCXX_USE_WCHAR_T
345   template<>
346     void
_M_initialize_moneypunct(__c_locale __cloc,const char *)347     moneypunct<wchar_t, true>::_M_initialize_moneypunct(__c_locale __cloc,
348 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
349 							const char*)
350 #else
351 							const char* __name)
352 #endif
353     {
354       if (!_M_data)
355 	_M_data = new __moneypunct_cache<wchar_t, true>;
356 
357       if (!__cloc)
358 	{
359 	  // "C" locale
360 	  _M_data->_M_decimal_point = L'.';
361 	  _M_data->_M_thousands_sep = L',';
362 	  _M_data->_M_grouping = "";
363 	  _M_data->_M_grouping_size = 0;
364 	  _M_data->_M_curr_symbol = L"";
365 	  _M_data->_M_curr_symbol_size = 0;
366 	  _M_data->_M_positive_sign = L"";
367 	  _M_data->_M_positive_sign_size = 0;
368 	  _M_data->_M_negative_sign = L"";
369 	  _M_data->_M_negative_sign_size = 0;
370 	  _M_data->_M_frac_digits = 0;
371 	  _M_data->_M_pos_format = money_base::_S_default_pattern;
372 	  _M_data->_M_neg_format = money_base::_S_default_pattern;
373 
374 	  // Use ctype::widen code without the facet...
375 	  for (size_t __i = 0; __i < money_base::_S_end; ++__i)
376 	    _M_data->_M_atoms[__i] =
377 	      static_cast<wchar_t>(money_base::_S_atoms[__i]);
378 	}
379       else
380 	{
381 	  // Named locale.
382 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
383 	  __c_locale __old = __uselocale(__cloc);
384 #else
385 	  // Switch to named locale so that mbsrtowcs will work.
386 	  char* __old = strdup(setlocale(LC_ALL, NULL));
387 	  setlocale(LC_ALL, __name);
388 #endif
389 
390 	  union { char *__s; wchar_t __w; } __u;
391 	  __u.__s = __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC, __cloc);
392 	  _M_data->_M_decimal_point = __u.__w;
393 
394 	  __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc);
395 	  _M_data->_M_thousands_sep = __u.__w;
396 	  _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
397 	  _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
398 
399 	  const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
400 	  const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
401 	  const char* __ccurr = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc);
402 
403 	  wchar_t* __wcs_ps = 0;
404 	  wchar_t* __wcs_ns = 0;
405 	  const char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc));
406 	  try
407 	    {
408 	      mbstate_t __state;
409 	      size_t __len = strlen(__cpossign);
410 	      if (__len)
411 		{
412 		  ++__len;
413 		  memset(&__state, 0, sizeof(mbstate_t));
414 		  __wcs_ps = new wchar_t[__len];
415 		  mbsrtowcs(__wcs_ps, &__cpossign, __len, &__state);
416 		  _M_data->_M_positive_sign = __wcs_ps;
417 		}
418 	      else
419 		_M_data->_M_positive_sign = L"";
420 	      _M_data->_M_positive_sign_size = wcslen(_M_data->_M_positive_sign);
421 
422 	      __len = strlen(__cnegsign);
423 	      if (!__nposn)
424 		_M_data->_M_negative_sign = L"()";
425 	      else if (__len)
426 		{
427 		  ++__len;
428 		  memset(&__state, 0, sizeof(mbstate_t));
429 		  __wcs_ns = new wchar_t[__len];
430 		  mbsrtowcs(__wcs_ns, &__cnegsign, __len, &__state);
431 		  _M_data->_M_negative_sign = __wcs_ns;
432 		}
433 	      else
434 		_M_data->_M_negative_sign = L"";
435 	      _M_data->_M_negative_sign_size = wcslen(_M_data->_M_negative_sign);
436 
437 	      // _Intl == true.
438 	      __len = strlen(__ccurr);
439 	      if (__len)
440 		{
441 		  ++__len;
442 		  memset(&__state, 0, sizeof(mbstate_t));
443 		  wchar_t* __wcs = new wchar_t[__len];
444 		  mbsrtowcs(__wcs, &__ccurr, __len, &__state);
445 		  _M_data->_M_curr_symbol = __wcs;
446 		}
447 	      else
448 		_M_data->_M_curr_symbol = L"";
449 	      _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol);
450 	    }
451 	  catch (...)
452 	    {
453 	      delete _M_data;
454 	      _M_data = 0;
455 	      delete __wcs_ps;
456 	      delete __wcs_ns;
457 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
458 	      __uselocale(__old);
459 #else
460 	      setlocale(LC_ALL, __old);
461 	      free(__old);
462 #endif
463 	      __throw_exception_again;
464 	    }
465 
466 	  _M_data->_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS,
467 						      __cloc));
468 	  char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc));
469 	  char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc));
470 	  char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc));
471 	  _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
472 							__pposn);
473 	  char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc));
474 	  char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc));
475 	  _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
476 							__nposn);
477 
478 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
479 	  __uselocale(__old);
480 #else
481 	  setlocale(LC_ALL, __old);
482 	  free(__old);
483 #endif
484 	}
485     }
486 
487   template<>
488   void
_M_initialize_moneypunct(__c_locale __cloc,const char *)489   moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc,
490 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
491 						       const char*)
492 #else
493                                                        const char* __name)
494 #endif
495   {
496     if (!_M_data)
497       _M_data = new __moneypunct_cache<wchar_t, false>;
498 
499     if (!__cloc)
500 	{
501 	  // "C" locale
502 	  _M_data->_M_decimal_point = L'.';
503 	  _M_data->_M_thousands_sep = L',';
504 	  _M_data->_M_grouping = "";
505           _M_data->_M_grouping_size = 0;
506 	  _M_data->_M_curr_symbol = L"";
507 	  _M_data->_M_curr_symbol_size = 0;
508 	  _M_data->_M_positive_sign = L"";
509 	  _M_data->_M_positive_sign_size = 0;
510 	  _M_data->_M_negative_sign = L"";
511 	  _M_data->_M_negative_sign_size = 0;
512 	  _M_data->_M_frac_digits = 0;
513 	  _M_data->_M_pos_format = money_base::_S_default_pattern;
514 	  _M_data->_M_neg_format = money_base::_S_default_pattern;
515 
516 	  // Use ctype::widen code without the facet...
517 	  for (size_t __i = 0; __i < money_base::_S_end; ++__i)
518 	    _M_data->_M_atoms[__i] =
519 	      static_cast<wchar_t>(money_base::_S_atoms[__i]);
520 	}
521       else
522 	{
523 	  // Named locale.
524 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
525 	  __c_locale __old = __uselocale(__cloc);
526 #else
527 	  // Switch to named locale so that mbsrtowcs will work.
528 	  char* __old = strdup(setlocale(LC_ALL, NULL));
529 	  setlocale(LC_ALL, __name);
530 #endif
531 
532           union { char *__s; wchar_t __w; } __u;
533 	  __u.__s = __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC, __cloc);
534 	  _M_data->_M_decimal_point = __u.__w;
535 
536 	  __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc);
537 	  _M_data->_M_thousands_sep = __u.__w;
538 	  _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
539           _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
540 
541 	  const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
542 	  const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
543 	  const char* __ccurr = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc);
544 
545 	  wchar_t* __wcs_ps = 0;
546 	  wchar_t* __wcs_ns = 0;
547 	  const char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc));
548 	  try
549             {
550               mbstate_t __state;
551               size_t __len;
552               __len = strlen(__cpossign);
553               if (__len)
554                 {
555 		  ++__len;
556 		  memset(&__state, 0, sizeof(mbstate_t));
557 		  __wcs_ps = new wchar_t[__len];
558 		  mbsrtowcs(__wcs_ps, &__cpossign, __len, &__state);
559 		  _M_data->_M_positive_sign = __wcs_ps;
560 		}
561 	      else
562 		_M_data->_M_positive_sign = L"";
563               _M_data->_M_positive_sign_size = wcslen(_M_data->_M_positive_sign);
564 
565 	      __len = strlen(__cnegsign);
566 	      if (!__nposn)
567 		_M_data->_M_negative_sign = L"()";
568 	      else if (__len)
569 		{
570 		  ++__len;
571 		  memset(&__state, 0, sizeof(mbstate_t));
572 		  __wcs_ns = new wchar_t[__len];
573 		  mbsrtowcs(__wcs_ns, &__cnegsign, __len, &__state);
574 		  _M_data->_M_negative_sign = __wcs_ns;
575 		}
576 	      else
577 		_M_data->_M_negative_sign = L"";
578               _M_data->_M_negative_sign_size = wcslen(_M_data->_M_negative_sign);
579 
580 	      // _Intl == true.
581 	      __len = strlen(__ccurr);
582 	      if (__len)
583 		{
584 		  ++__len;
585 		  memset(&__state, 0, sizeof(mbstate_t));
586 		  wchar_t* __wcs = new wchar_t[__len];
587 		  mbsrtowcs(__wcs, &__ccurr, __len, &__state);
588 		  _M_data->_M_curr_symbol = __wcs;
589 		}
590 	      else
591 		_M_data->_M_curr_symbol = L"";
592               _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol);
593 	    }
594           catch (...)
595 	    {
596 	      delete _M_data;
597               _M_data = 0;
598 	      delete __wcs_ps;
599 	      delete __wcs_ns;
600 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
601 	      __uselocale(__old);
602 #else
603 	      setlocale(LC_ALL, __old);
604 	      free(__old);
605 #endif
606               __throw_exception_again;
607 	    }
608 
609 	  _M_data->_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc));
610 	  char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc));
611 	  char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc));
612 	  char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc));
613 	  _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
614 	                                                __pposn);
615 	  char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc));
616 	  char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc));
617 	  _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
618 	                                                __nposn);
619 
620 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
621 	  __uselocale(__old);
622 #else
623 	  setlocale(LC_ALL, __old);
624 	  free(__old);
625 #endif
626 	}
627     }
628 
629   template<>
~moneypunct()630     moneypunct<wchar_t, true>::~moneypunct()
631     {
632       if (_M_data->_M_positive_sign_size)
633 	delete [] _M_data->_M_positive_sign;
634       if (_M_data->_M_negative_sign_size
635           && wcscmp(_M_data->_M_negative_sign, L"()") != 0)
636 	delete [] _M_data->_M_negative_sign;
637       if (_M_data->_M_curr_symbol_size)
638 	delete [] _M_data->_M_curr_symbol;
639       delete _M_data;
640     }
641 
642   template<>
~moneypunct()643     moneypunct<wchar_t, false>::~moneypunct()
644     {
645       if (_M_data->_M_positive_sign_size)
646 	delete [] _M_data->_M_positive_sign;
647       if (_M_data->_M_negative_sign_size
648           && wcscmp(_M_data->_M_negative_sign, L"()") != 0)
649 	delete [] _M_data->_M_negative_sign;
650       if (_M_data->_M_curr_symbol_size)
651 	delete [] _M_data->_M_curr_symbol;
652       delete _M_data;
653     }
654 #endif
655 
656 _GLIBCXX_END_NAMESPACE
657