1 // std::moneypunct implementation details, GNU version -*- C++ -*-
2 
3 // Copyright (C) 2001, 2002, 2003, 2004 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
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 
39 namespace std
40 {
41   // Construct and return valid pattern consisting of some combination of:
42   // space none symbol sign value
43   money_base::pattern
_S_construct_pattern(char __precedes,char __space,char __posn)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 	;
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 	  unsigned char uc;
376 	  for (size_t __i = 0; __i < money_base::_S_end; ++__i)
377 	    {
378 	      uc = static_cast<unsigned char>(money_base::_S_atoms[__i]);
379 	      _M_data->_M_atoms[__i] = btowc(uc);
380 	    }
381 	}
382       else
383 	{
384 	  // Named locale.
385 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
386 	  __c_locale __old = __uselocale(__cloc);
387 #else
388 	  // Switch to named locale so that mbsrtowcs will work.
389 	  char* __old = strdup(setlocale(LC_ALL, NULL));
390 	  setlocale(LC_ALL, __name);
391 #endif
392 
393 	  union __s_and_w { const char *__s; unsigned int __w; } __u;
394 	  __u.__s = __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC, __cloc);
395 	  _M_data->_M_decimal_point = static_cast<wchar_t>(__u.__w);
396 
397 	  __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc);
398 	  _M_data->_M_thousands_sep = static_cast<wchar_t>(__u.__w);
399 	  _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
400 	  _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
401 
402 	  const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
403 	  const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
404 	  const char* __ccurr = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc);
405 
406 	  wchar_t* __wcs_ps = 0;
407 	  wchar_t* __wcs_ns = 0;
408 	  const char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc));
409 	  try
410 	    {
411 	      mbstate_t __state;
412 	      size_t __len = strlen(__cpossign);
413 	      if (__len)
414 		{
415 		  ++__len;
416 		  memset(&__state, 0, sizeof(mbstate_t));
417 		  __wcs_ps = new wchar_t[__len];
418 		  mbsrtowcs(__wcs_ps, &__cpossign, __len, &__state);
419 		  _M_data->_M_positive_sign = __wcs_ps;
420 		}
421 	      else
422 		_M_data->_M_positive_sign = L"";
423 	      _M_data->_M_positive_sign_size = wcslen(_M_data->_M_positive_sign);
424 
425 	      __len = strlen(__cnegsign);
426 	      if (!__nposn)
427 		_M_data->_M_negative_sign = L"()";
428 	      else if (__len)
429 		{
430 		  ++__len;
431 		  memset(&__state, 0, sizeof(mbstate_t));
432 		  __wcs_ns = new wchar_t[__len];
433 		  mbsrtowcs(__wcs_ns, &__cnegsign, __len, &__state);
434 		  _M_data->_M_negative_sign = __wcs_ns;
435 		}
436 	      else
437 		_M_data->_M_negative_sign = L"";
438 	      _M_data->_M_negative_sign_size = wcslen(_M_data->_M_negative_sign);
439 
440 	      // _Intl == true.
441 	      __len = strlen(__ccurr);
442 	      if (__len)
443 		{
444 		  ++__len;
445 		  memset(&__state, 0, sizeof(mbstate_t));
446 		  wchar_t* __wcs = new wchar_t[__len];
447 		  mbsrtowcs(__wcs, &__ccurr, __len, &__state);
448 		  _M_data->_M_curr_symbol = __wcs;
449 		}
450 	      else
451 		_M_data->_M_curr_symbol = L"";
452 	      _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol);
453 	    }
454 	  catch (...)
455 	    {
456 	      delete _M_data;
457 	      _M_data = 0;
458 	      delete __wcs_ps;
459 	      delete __wcs_ns;
460 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
461 	      __uselocale(__old);
462 #else
463 	      setlocale(LC_ALL, __old);
464 	      free(__old);
465 #endif
466 	      __throw_exception_again;
467 	    }
468 
469 	  _M_data->_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS,
470 						      __cloc));
471 	  char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc));
472 	  char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc));
473 	  char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc));
474 	  _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
475 							__pposn);
476 	  char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc));
477 	  char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc));
478 	  _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
479 							__nposn);
480 
481 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
482 	  __uselocale(__old);
483 #else
484 	  setlocale(LC_ALL, __old);
485 	  free(__old);
486 #endif
487 	}
488     }
489 
490   template<>
491   void
_M_initialize_moneypunct(__c_locale __cloc,const char *)492   moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc,
493 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
494 						       const char*)
495 #else
496                                                        const char* __name)
497 #endif
498   {
499     if (!_M_data)
500       _M_data = new __moneypunct_cache<wchar_t, false>;
501 
502     if (!__cloc)
503 	{
504 	  // "C" locale
505 	  _M_data->_M_decimal_point = L'.';
506 	  _M_data->_M_thousands_sep = L',';
507 	  _M_data->_M_grouping = "";
508           _M_data->_M_grouping_size = 0;
509 	  _M_data->_M_curr_symbol = L"";
510 	  _M_data->_M_curr_symbol_size = 0;
511 	  _M_data->_M_positive_sign = L"";
512 	  _M_data->_M_positive_sign_size = 0;
513 	  _M_data->_M_negative_sign = L"";
514 	  _M_data->_M_negative_sign_size = 0;
515 	  _M_data->_M_frac_digits = 0;
516 	  _M_data->_M_pos_format = money_base::_S_default_pattern;
517 	  _M_data->_M_neg_format = money_base::_S_default_pattern;
518 
519 	  // Use ctype::widen code without the facet...
520 	  unsigned char uc;
521 	  for (size_t __i = 0; __i < money_base::_S_end; ++__i)
522 	    {
523 	      uc = static_cast<unsigned char>(money_base::_S_atoms[__i]);
524 	      _M_data->_M_atoms[__i] = btowc(uc);
525 	    }
526 	}
527       else
528 	{
529 	  // Named locale.
530 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
531 	  __c_locale __old = __uselocale(__cloc);
532 #else
533 	  // Switch to named locale so that mbsrtowcs will work.
534 	  char* __old = strdup(setlocale(LC_ALL, NULL));
535 	  setlocale(LC_ALL, __name);
536 #endif
537 
538 	  union __s_and_w { const char *__s; unsigned int __w; } __u;
539 	  __u.__s = __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC, __cloc);
540 	  _M_data->_M_decimal_point = static_cast<wchar_t>(__u.__w);
541 
542 	  __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc);
543 	  _M_data->_M_thousands_sep = static_cast<wchar_t>(__u.__w);
544 	  _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
545           _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
546 
547 	  const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
548 	  const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
549 	  const char* __ccurr = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc);
550 
551 	  wchar_t* __wcs_ps = 0;
552 	  wchar_t* __wcs_ns = 0;
553 	  const char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc));
554 	  try
555             {
556               mbstate_t __state;
557               size_t __len;
558               __len = strlen(__cpossign);
559               if (__len)
560                 {
561 		  ++__len;
562 		  memset(&__state, 0, sizeof(mbstate_t));
563 		  __wcs_ps = new wchar_t[__len];
564 		  mbsrtowcs(__wcs_ps, &__cpossign, __len, &__state);
565 		  _M_data->_M_positive_sign = __wcs_ps;
566 		}
567 	      else
568 		_M_data->_M_positive_sign = L"";
569               _M_data->_M_positive_sign_size = wcslen(_M_data->_M_positive_sign);
570 
571 	      __len = strlen(__cnegsign);
572 	      if (!__nposn)
573 		_M_data->_M_negative_sign = L"()";
574 	      else if (__len)
575 		{
576 		  ++__len;
577 		  memset(&__state, 0, sizeof(mbstate_t));
578 		  __wcs_ns = new wchar_t[__len];
579 		  mbsrtowcs(__wcs_ns, &__cnegsign, __len, &__state);
580 		  _M_data->_M_negative_sign = __wcs_ns;
581 		}
582 	      else
583 		_M_data->_M_negative_sign = L"";
584               _M_data->_M_negative_sign_size = wcslen(_M_data->_M_negative_sign);
585 
586 	      // _Intl == true.
587 	      __len = strlen(__ccurr);
588 	      if (__len)
589 		{
590 		  ++__len;
591 		  memset(&__state, 0, sizeof(mbstate_t));
592 		  wchar_t* __wcs = new wchar_t[__len];
593 		  mbsrtowcs(__wcs, &__ccurr, __len, &__state);
594 		  _M_data->_M_curr_symbol = __wcs;
595 		}
596 	      else
597 		_M_data->_M_curr_symbol = L"";
598               _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol);
599 	    }
600           catch (...)
601 	    {
602 	      delete _M_data;
603               _M_data = 0;
604 	      delete __wcs_ps;
605 	      delete __wcs_ns;
606 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
607 	      __uselocale(__old);
608 #else
609 	      setlocale(LC_ALL, __old);
610 	      free(__old);
611 #endif
612               __throw_exception_again;
613 	    }
614 
615 	  _M_data->_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc));
616 	  char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc));
617 	  char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc));
618 	  char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc));
619 	  _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
620 	                                                __pposn);
621 	  char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc));
622 	  char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc));
623 	  _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
624 	                                                __nposn);
625 
626 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
627 	  __uselocale(__old);
628 #else
629 	  setlocale(LC_ALL, __old);
630 	  free(__old);
631 #endif
632 	}
633     }
634 
635   template<>
~moneypunct()636     moneypunct<wchar_t, true>::~moneypunct()
637     {
638       if (_M_data->_M_positive_sign_size)
639 	delete [] _M_data->_M_positive_sign;
640       if (_M_data->_M_negative_sign_size
641           && wcscmp(_M_data->_M_negative_sign, L"()") != 0)
642 	delete [] _M_data->_M_negative_sign;
643       if (_M_data->_M_curr_symbol_size)
644 	delete [] _M_data->_M_curr_symbol;
645       delete _M_data;
646     }
647 
648   template<>
~moneypunct()649     moneypunct<wchar_t, false>::~moneypunct()
650     {
651       if (_M_data->_M_positive_sign_size)
652 	delete [] _M_data->_M_positive_sign;
653       if (_M_data->_M_negative_sign_size
654           && wcscmp(_M_data->_M_negative_sign, L"()") != 0)
655 	delete [] _M_data->_M_negative_sign;
656       if (_M_data->_M_curr_symbol_size)
657 	delete [] _M_data->_M_curr_symbol;
658       delete _M_data;
659     }
660 #endif
661 }
662