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