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