197403Sobrien// std::moneypunct implementation details, GNU version -*- C++ -*-
297403Sobrien
3169691Skan// Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
497403Sobrien//
597403Sobrien// This file is part of the GNU ISO C++ Library.  This library is free
697403Sobrien// software; you can redistribute it and/or modify it under the
797403Sobrien// terms of the GNU General Public License as published by the
897403Sobrien// Free Software Foundation; either version 2, or (at your option)
997403Sobrien// any later version.
1097403Sobrien
1197403Sobrien// This library is distributed in the hope that it will be useful,
1297403Sobrien// but WITHOUT ANY WARRANTY; without even the implied warranty of
1397403Sobrien// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1497403Sobrien// GNU General Public License for more details.
1597403Sobrien
1697403Sobrien// You should have received a copy of the GNU General Public License along
1797403Sobrien// with this library; see the file COPYING.  If not, write to the Free
18169691Skan// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
1997403Sobrien// USA.
2097403Sobrien
2197403Sobrien// As a special exception, you may use this file as part of a free software
2297403Sobrien// library without restriction.  Specifically, if other files instantiate
2397403Sobrien// templates or use macros or inline functions from this file, or you compile
2497403Sobrien// this file and link it with other files to produce an executable, this
2597403Sobrien// file does not by itself cause the resulting executable to be covered by
2697403Sobrien// the GNU General Public License.  This exception does not however
2797403Sobrien// invalidate any other reasons why the executable file might be covered by
2897403Sobrien// the GNU General Public License.
2997403Sobrien
3097403Sobrien//
3197403Sobrien// ISO C++ 14882: 22.2.6.3.2  moneypunct virtual functions
3297403Sobrien//
3397403Sobrien
3497403Sobrien// Written by Benjamin Kosnik <bkoz@redhat.com>
3597403Sobrien
3697403Sobrien#include <locale>
37117397Skan#include <bits/c++locale_internal.h>
3897403Sobrien
39169691Skan_GLIBCXX_BEGIN_NAMESPACE(std)
40169691Skan
4197403Sobrien  // Construct and return valid pattern consisting of some combination of:
4297403Sobrien  // space none symbol sign value
4397403Sobrien  money_base::pattern
4497403Sobrien  money_base::_S_construct_pattern(char __precedes, char __space, char __posn)
4597403Sobrien  {
4697403Sobrien    pattern __ret;
4797403Sobrien
4897403Sobrien    // This insanely complicated routine attempts to construct a valid
4997403Sobrien    // pattern for use with monyepunct. A couple of invariants:
5097403Sobrien
5197403Sobrien    // if (__precedes) symbol -> value
5297403Sobrien    // else value -> symbol
5397403Sobrien
5497403Sobrien    // if (__space) space
5597403Sobrien    // else none
5697403Sobrien
5797403Sobrien    // none == never first
5897403Sobrien    // space never first or last
5997403Sobrien
6097403Sobrien    // Any elegant implementations of this are welcome.
6197403Sobrien    switch (__posn)
6297403Sobrien      {
6397403Sobrien      case 0:
6497403Sobrien      case 1:
6597403Sobrien	// 1 The sign precedes the value and symbol.
66132720Skan	__ret.field[0] = sign;
6797403Sobrien	if (__space)
6897403Sobrien	  {
6997403Sobrien	    // Pattern starts with sign.
7097403Sobrien	    if (__precedes)
7197403Sobrien	      {
7297403Sobrien		__ret.field[1] = symbol;
7397403Sobrien		__ret.field[3] = value;
7497403Sobrien	      }
7597403Sobrien	    else
7697403Sobrien	      {
7797403Sobrien		__ret.field[1] = value;
7897403Sobrien		__ret.field[3] = symbol;
7997403Sobrien	      }
80132720Skan	    __ret.field[2] = space;
8197403Sobrien	  }
8297403Sobrien	else
8397403Sobrien	  {
8497403Sobrien	    // Pattern starts with sign and ends with none.
8597403Sobrien	    if (__precedes)
8697403Sobrien	      {
8797403Sobrien		__ret.field[1] = symbol;
8897403Sobrien		__ret.field[2] = value;
8997403Sobrien	      }
9097403Sobrien	    else
9197403Sobrien	      {
9297403Sobrien		__ret.field[1] = value;
9397403Sobrien		__ret.field[2] = symbol;
9497403Sobrien	      }
9597403Sobrien	    __ret.field[3] = none;
9697403Sobrien	  }
9797403Sobrien	break;
9897403Sobrien      case 2:
9997403Sobrien	// 2 The sign follows the value and symbol.
10097403Sobrien	if (__space)
10197403Sobrien	  {
10297403Sobrien	    // Pattern either ends with sign.
10397403Sobrien	    if (__precedes)
10497403Sobrien	      {
10597403Sobrien		__ret.field[0] = symbol;
10697403Sobrien		__ret.field[2] = value;
10797403Sobrien	      }
10897403Sobrien	    else
10997403Sobrien	      {
11097403Sobrien		__ret.field[0] = value;
11197403Sobrien		__ret.field[2] = symbol;
11297403Sobrien	      }
113132720Skan	    __ret.field[1] = space;
11497403Sobrien	    __ret.field[3] = sign;
11597403Sobrien	  }
11697403Sobrien	else
11797403Sobrien	  {
11897403Sobrien	    // Pattern ends with sign then none.
11997403Sobrien	    if (__precedes)
12097403Sobrien	      {
12197403Sobrien		__ret.field[0] = symbol;
12297403Sobrien		__ret.field[1] = value;
12397403Sobrien	      }
12497403Sobrien	    else
12597403Sobrien	      {
12697403Sobrien		__ret.field[0] = value;
12797403Sobrien		__ret.field[1] = symbol;
12897403Sobrien	      }
12997403Sobrien	    __ret.field[2] = sign;
13097403Sobrien	    __ret.field[3] = none;
13197403Sobrien	  }
13297403Sobrien	break;
13397403Sobrien      case 3:
13497403Sobrien	// 3 The sign immediately precedes the symbol.
135132720Skan	if (__precedes)
13697403Sobrien	  {
137132720Skan	    __ret.field[0] = sign;
138132720Skan	    __ret.field[1] = symbol;
139132720Skan	    if (__space)
14097403Sobrien	      {
14197403Sobrien		__ret.field[2] = space;
14297403Sobrien		__ret.field[3] = value;
14397403Sobrien	      }
14497403Sobrien	    else
14597403Sobrien	      {
146132720Skan		__ret.field[2] = value;
147132720Skan		__ret.field[3] = none;
14897403Sobrien	      }
14997403Sobrien	  }
15097403Sobrien	else
15197403Sobrien	  {
152132720Skan	    __ret.field[0] = value;
153132720Skan	    if (__space)
15497403Sobrien	      {
155132720Skan		__ret.field[1] = space;
156132720Skan		__ret.field[2] = sign;
157132720Skan		__ret.field[3] = symbol;
15897403Sobrien	      }
15997403Sobrien	    else
16097403Sobrien	      {
16197403Sobrien		__ret.field[1] = sign;
16297403Sobrien		__ret.field[2] = symbol;
163132720Skan		__ret.field[3] = none;
16497403Sobrien	      }
16597403Sobrien	  }
16697403Sobrien	break;
16797403Sobrien      case 4:
168132720Skan	// 4 The sign immediately follows the symbol.
169132720Skan	if (__precedes)
17097403Sobrien	  {
171132720Skan	    __ret.field[0] = symbol;
172132720Skan	    __ret.field[1] = sign;
173132720Skan	    if (__space)
17497403Sobrien	      {
17597403Sobrien		__ret.field[2] = space;
17697403Sobrien		__ret.field[3] = value;
17797403Sobrien	      }
17897403Sobrien	    else
17997403Sobrien	      {
180132720Skan		__ret.field[2] = value;
181132720Skan		__ret.field[3] = none;
18297403Sobrien	      }
18397403Sobrien	  }
18497403Sobrien	else
18597403Sobrien	  {
186132720Skan	    __ret.field[0] = value;
187132720Skan	    if (__space)
18897403Sobrien	      {
189132720Skan		__ret.field[1] = space;
190132720Skan		__ret.field[2] = symbol;
191132720Skan		__ret.field[3] = sign;
19297403Sobrien	      }
19397403Sobrien	    else
19497403Sobrien	      {
19597403Sobrien		__ret.field[1] = symbol;
19697403Sobrien		__ret.field[2] = sign;
197132720Skan		__ret.field[3] = none;
19897403Sobrien	      }
19997403Sobrien	  }
20097403Sobrien	break;
20197403Sobrien      default:
202146897Skan	__ret = pattern();
20397403Sobrien      }
20497403Sobrien    return __ret;
20597403Sobrien  }
20697403Sobrien
20797403Sobrien  template<>
20897403Sobrien    void
209102782Skan    moneypunct<char, true>::_M_initialize_moneypunct(__c_locale __cloc,
210102782Skan						     const char*)
21197403Sobrien    {
212132720Skan      if (!_M_data)
213132720Skan	_M_data = new __moneypunct_cache<char, true>;
214132720Skan
215107606Sobrien      if (!__cloc)
21697403Sobrien	{
21797403Sobrien	  // "C" locale
218132720Skan	  _M_data->_M_decimal_point = '.';
219132720Skan	  _M_data->_M_thousands_sep = ',';
220132720Skan	  _M_data->_M_grouping = "";
221132720Skan	  _M_data->_M_grouping_size = 0;
222132720Skan	  _M_data->_M_curr_symbol = "";
223132720Skan	  _M_data->_M_curr_symbol_size = 0;
224132720Skan	  _M_data->_M_positive_sign = "";
225132720Skan	  _M_data->_M_positive_sign_size = 0;
226132720Skan	  _M_data->_M_negative_sign = "";
227132720Skan	  _M_data->_M_negative_sign_size = 0;
228132720Skan	  _M_data->_M_frac_digits = 0;
229132720Skan	  _M_data->_M_pos_format = money_base::_S_default_pattern;
230132720Skan	  _M_data->_M_neg_format = money_base::_S_default_pattern;
231132720Skan
232132720Skan	  for (size_t __i = 0; __i < money_base::_S_end; ++__i)
233132720Skan	    _M_data->_M_atoms[__i] = money_base::_S_atoms[__i];
23497403Sobrien	}
23597403Sobrien      else
23697403Sobrien	{
23797403Sobrien	  // Named locale.
238132720Skan	  _M_data->_M_decimal_point = *(__nl_langinfo_l(__MON_DECIMAL_POINT,
239132720Skan							__cloc));
240132720Skan	  _M_data->_M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP,
241132720Skan							__cloc));
242132720Skan	  _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
243132720Skan	  _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
244132720Skan	  _M_data->_M_positive_sign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
245132720Skan	  _M_data->_M_positive_sign_size = strlen(_M_data->_M_positive_sign);
24697403Sobrien
24797403Sobrien	  char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc));
24897403Sobrien	  if (!__nposn)
249132720Skan	    _M_data->_M_negative_sign = "()";
25097403Sobrien	  else
251132720Skan	    _M_data->_M_negative_sign = __nl_langinfo_l(__NEGATIVE_SIGN,
252132720Skan							__cloc);
253132720Skan	  _M_data->_M_negative_sign_size = strlen(_M_data->_M_negative_sign);
25497403Sobrien
25597403Sobrien	  // _Intl == true
256132720Skan	  _M_data->_M_curr_symbol = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc);
257132720Skan	  _M_data->_M_curr_symbol_size = strlen(_M_data->_M_curr_symbol);
258132720Skan	  _M_data->_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS,
259132720Skan						      __cloc));
26097403Sobrien	  char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc));
26197403Sobrien	  char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc));
26297403Sobrien	  char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc));
263132720Skan	  _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
264132720Skan							__pposn);
26597403Sobrien	  char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc));
26697403Sobrien	  char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc));
267132720Skan	  _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
268132720Skan							__nposn);
26997403Sobrien	}
27097403Sobrien    }
27197403Sobrien
27297403Sobrien  template<>
27397403Sobrien    void
274102782Skan    moneypunct<char, false>::_M_initialize_moneypunct(__c_locale __cloc,
275102782Skan						      const char*)
27697403Sobrien    {
277132720Skan      if (!_M_data)
278132720Skan	_M_data = new __moneypunct_cache<char, false>;
279132720Skan
280107606Sobrien      if (!__cloc)
28197403Sobrien	{
28297403Sobrien	  // "C" locale
283132720Skan	  _M_data->_M_decimal_point = '.';
284132720Skan	  _M_data->_M_thousands_sep = ',';
285132720Skan	  _M_data->_M_grouping = "";
286132720Skan	  _M_data->_M_grouping_size = 0;
287132720Skan	  _M_data->_M_curr_symbol = "";
288132720Skan	  _M_data->_M_curr_symbol_size = 0;
289132720Skan	  _M_data->_M_positive_sign = "";
290132720Skan	  _M_data->_M_positive_sign_size = 0;
291132720Skan	  _M_data->_M_negative_sign = "";
292132720Skan	  _M_data->_M_negative_sign_size = 0;
293132720Skan	  _M_data->_M_frac_digits = 0;
294132720Skan	  _M_data->_M_pos_format = money_base::_S_default_pattern;
295132720Skan	  _M_data->_M_neg_format = money_base::_S_default_pattern;
296132720Skan
297132720Skan	  for (size_t __i = 0; __i < money_base::_S_end; ++__i)
298132720Skan	    _M_data->_M_atoms[__i] = money_base::_S_atoms[__i];
29997403Sobrien	}
30097403Sobrien      else
30197403Sobrien	{
30297403Sobrien	  // Named locale.
303132720Skan	  _M_data->_M_decimal_point = *(__nl_langinfo_l(__MON_DECIMAL_POINT,
304132720Skan							__cloc));
305132720Skan	  _M_data->_M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP,
306132720Skan							__cloc));
307132720Skan	  _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
308132720Skan	  _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
309132720Skan	  _M_data->_M_positive_sign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
310132720Skan	  _M_data->_M_positive_sign_size = strlen(_M_data->_M_positive_sign);
31197403Sobrien
31297403Sobrien	  char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc));
31397403Sobrien	  if (!__nposn)
314132720Skan	    _M_data->_M_negative_sign = "()";
31597403Sobrien	  else
316132720Skan	    _M_data->_M_negative_sign = __nl_langinfo_l(__NEGATIVE_SIGN,
317132720Skan							__cloc);
318132720Skan	  _M_data->_M_negative_sign_size = strlen(_M_data->_M_negative_sign);
31997403Sobrien
32097403Sobrien	  // _Intl == false
321132720Skan	  _M_data->_M_curr_symbol = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc);
322132720Skan	  _M_data->_M_curr_symbol_size = strlen(_M_data->_M_curr_symbol);
323132720Skan	  _M_data->_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc));
32497403Sobrien	  char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc));
32597403Sobrien	  char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc));
32697403Sobrien	  char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc));
327132720Skan	  _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
328132720Skan							__pposn);
32997403Sobrien	  char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc));
33097403Sobrien	  char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc));
331132720Skan	  _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
332132720Skan							__nposn);
33397403Sobrien	}
33497403Sobrien    }
33597403Sobrien
33697403Sobrien  template<>
33797403Sobrien    moneypunct<char, true>::~moneypunct()
338132720Skan    { delete _M_data; }
33997403Sobrien
34097403Sobrien  template<>
34197403Sobrien    moneypunct<char, false>::~moneypunct()
342132720Skan    { delete _M_data; }
34397403Sobrien
344132720Skan#ifdef _GLIBCXX_USE_WCHAR_T
34597403Sobrien  template<>
34697403Sobrien    void
347102782Skan    moneypunct<wchar_t, true>::_M_initialize_moneypunct(__c_locale __cloc,
348117397Skan#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
349117397Skan							const char*)
350117397Skan#else
351102782Skan							const char* __name)
352117397Skan#endif
35397403Sobrien    {
354132720Skan      if (!_M_data)
355132720Skan	_M_data = new __moneypunct_cache<wchar_t, true>;
356132720Skan
357107606Sobrien      if (!__cloc)
35897403Sobrien	{
35997403Sobrien	  // "C" locale
360132720Skan	  _M_data->_M_decimal_point = L'.';
361132720Skan	  _M_data->_M_thousands_sep = L',';
362132720Skan	  _M_data->_M_grouping = "";
363132720Skan	  _M_data->_M_grouping_size = 0;
364132720Skan	  _M_data->_M_curr_symbol = L"";
365132720Skan	  _M_data->_M_curr_symbol_size = 0;
366132720Skan	  _M_data->_M_positive_sign = L"";
367132720Skan	  _M_data->_M_positive_sign_size = 0;
368132720Skan	  _M_data->_M_negative_sign = L"";
369132720Skan	  _M_data->_M_negative_sign_size = 0;
370132720Skan	  _M_data->_M_frac_digits = 0;
371132720Skan	  _M_data->_M_pos_format = money_base::_S_default_pattern;
372132720Skan	  _M_data->_M_neg_format = money_base::_S_default_pattern;
373132720Skan
374132720Skan	  // Use ctype::widen code without the facet...
375132720Skan	  for (size_t __i = 0; __i < money_base::_S_end; ++__i)
376169691Skan	    _M_data->_M_atoms[__i] =
377169691Skan	      static_cast<wchar_t>(money_base::_S_atoms[__i]);
37897403Sobrien	}
37997403Sobrien      else
38097403Sobrien	{
38197403Sobrien	  // Named locale.
382103447Skan#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
383103447Skan	  __c_locale __old = __uselocale(__cloc);
384103447Skan#else
385103447Skan	  // Switch to named locale so that mbsrtowcs will work.
386102782Skan	  char* __old = strdup(setlocale(LC_ALL, NULL));
387102782Skan	  setlocale(LC_ALL, __name);
388103447Skan#endif
389102782Skan
390169691Skan	  union { char *__s; wchar_t __w; } __u;
391132720Skan	  __u.__s = __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC, __cloc);
392169691Skan	  _M_data->_M_decimal_point = __u.__w;
39397403Sobrien
394132720Skan	  __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc);
395169691Skan	  _M_data->_M_thousands_sep = __u.__w;
396132720Skan	  _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
397132720Skan	  _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
39897403Sobrien
39997403Sobrien	  const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
40097403Sobrien	  const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
40197403Sobrien	  const char* __ccurr = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc);
40297403Sobrien
403132720Skan	  wchar_t* __wcs_ps = 0;
404132720Skan	  wchar_t* __wcs_ns = 0;
405132720Skan	  const char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc));
406132720Skan	  try
40797403Sobrien	    {
408132720Skan	      mbstate_t __state;
409132720Skan	      size_t __len = strlen(__cpossign);
410132720Skan	      if (__len)
411132720Skan		{
412132720Skan		  ++__len;
413132720Skan		  memset(&__state, 0, sizeof(mbstate_t));
414132720Skan		  __wcs_ps = new wchar_t[__len];
415132720Skan		  mbsrtowcs(__wcs_ps, &__cpossign, __len, &__state);
416132720Skan		  _M_data->_M_positive_sign = __wcs_ps;
417132720Skan		}
418132720Skan	      else
419132720Skan		_M_data->_M_positive_sign = L"";
420132720Skan	      _M_data->_M_positive_sign_size = wcslen(_M_data->_M_positive_sign);
421132720Skan
422132720Skan	      __len = strlen(__cnegsign);
423132720Skan	      if (!__nposn)
424132720Skan		_M_data->_M_negative_sign = L"()";
425132720Skan	      else if (__len)
426132720Skan		{
427132720Skan		  ++__len;
428132720Skan		  memset(&__state, 0, sizeof(mbstate_t));
429132720Skan		  __wcs_ns = new wchar_t[__len];
430132720Skan		  mbsrtowcs(__wcs_ns, &__cnegsign, __len, &__state);
431132720Skan		  _M_data->_M_negative_sign = __wcs_ns;
432132720Skan		}
433132720Skan	      else
434132720Skan		_M_data->_M_negative_sign = L"";
435132720Skan	      _M_data->_M_negative_sign_size = wcslen(_M_data->_M_negative_sign);
436132720Skan
437132720Skan	      // _Intl == true.
438132720Skan	      __len = strlen(__ccurr);
439132720Skan	      if (__len)
440132720Skan		{
441132720Skan		  ++__len;
442132720Skan		  memset(&__state, 0, sizeof(mbstate_t));
443132720Skan		  wchar_t* __wcs = new wchar_t[__len];
444132720Skan		  mbsrtowcs(__wcs, &__ccurr, __len, &__state);
445132720Skan		  _M_data->_M_curr_symbol = __wcs;
446132720Skan		}
447132720Skan	      else
448132720Skan		_M_data->_M_curr_symbol = L"";
449132720Skan	      _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol);
45097403Sobrien	    }
451132720Skan	  catch (...)
45297403Sobrien	    {
453132720Skan	      delete _M_data;
454132720Skan	      _M_data = 0;
455132720Skan	      delete __wcs_ps;
456132720Skan	      delete __wcs_ns;
457132720Skan#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
458132720Skan	      __uselocale(__old);
459132720Skan#else
460132720Skan	      setlocale(LC_ALL, __old);
461132720Skan	      free(__old);
462132720Skan#endif
463132720Skan	      __throw_exception_again;
464132720Skan	    }
465132720Skan
466132720Skan	  _M_data->_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS,
467132720Skan						      __cloc));
46897403Sobrien	  char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc));
46997403Sobrien	  char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc));
47097403Sobrien	  char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc));
471132720Skan	  _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
472132720Skan							__pposn);
47397403Sobrien	  char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc));
47497403Sobrien	  char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc));
475132720Skan	  _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
476132720Skan							__nposn);
477102782Skan
478103447Skan#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
479103447Skan	  __uselocale(__old);
480103447Skan#else
481102782Skan	  setlocale(LC_ALL, __old);
482102782Skan	  free(__old);
483103447Skan#endif
48497403Sobrien	}
48597403Sobrien    }
48697403Sobrien
48797403Sobrien  template<>
488132720Skan  void
489132720Skan  moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc,
490132720Skan#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
491132720Skan						       const char*)
492117397Skan#else
493132720Skan                                                       const char* __name)
494117397Skan#endif
495132720Skan  {
496132720Skan    if (!_M_data)
497132720Skan      _M_data = new __moneypunct_cache<wchar_t, false>;
498132720Skan
499132720Skan    if (!__cloc)
50097403Sobrien	{
50197403Sobrien	  // "C" locale
502132720Skan	  _M_data->_M_decimal_point = L'.';
503132720Skan	  _M_data->_M_thousands_sep = L',';
504132720Skan	  _M_data->_M_grouping = "";
505132720Skan          _M_data->_M_grouping_size = 0;
506132720Skan	  _M_data->_M_curr_symbol = L"";
507132720Skan	  _M_data->_M_curr_symbol_size = 0;
508132720Skan	  _M_data->_M_positive_sign = L"";
509132720Skan	  _M_data->_M_positive_sign_size = 0;
510132720Skan	  _M_data->_M_negative_sign = L"";
511132720Skan	  _M_data->_M_negative_sign_size = 0;
512132720Skan	  _M_data->_M_frac_digits = 0;
513132720Skan	  _M_data->_M_pos_format = money_base::_S_default_pattern;
514132720Skan	  _M_data->_M_neg_format = money_base::_S_default_pattern;
515132720Skan
516132720Skan	  // Use ctype::widen code without the facet...
517132720Skan	  for (size_t __i = 0; __i < money_base::_S_end; ++__i)
518169691Skan	    _M_data->_M_atoms[__i] =
519169691Skan	      static_cast<wchar_t>(money_base::_S_atoms[__i]);
52097403Sobrien	}
52197403Sobrien      else
52297403Sobrien	{
52397403Sobrien	  // Named locale.
524103447Skan#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
525103447Skan	  __c_locale __old = __uselocale(__cloc);
526103447Skan#else
527103447Skan	  // Switch to named locale so that mbsrtowcs will work.
528102782Skan	  char* __old = strdup(setlocale(LC_ALL, NULL));
529102782Skan	  setlocale(LC_ALL, __name);
530103447Skan#endif
531102782Skan
532169691Skan          union { char *__s; wchar_t __w; } __u;
533132720Skan	  __u.__s = __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC, __cloc);
534169691Skan	  _M_data->_M_decimal_point = __u.__w;
53597403Sobrien
536132720Skan	  __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc);
537169691Skan	  _M_data->_M_thousands_sep = __u.__w;
538132720Skan	  _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
539132720Skan          _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
540132720Skan
54197403Sobrien	  const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
54297403Sobrien	  const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
54397403Sobrien	  const char* __ccurr = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc);
54497403Sobrien
545132720Skan	  wchar_t* __wcs_ps = 0;
546132720Skan	  wchar_t* __wcs_ns = 0;
547132720Skan	  const char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc));
548132720Skan	  try
549132720Skan            {
550132720Skan              mbstate_t __state;
551132720Skan              size_t __len;
552132720Skan              __len = strlen(__cpossign);
553132720Skan              if (__len)
554132720Skan                {
555132720Skan		  ++__len;
556132720Skan		  memset(&__state, 0, sizeof(mbstate_t));
557132720Skan		  __wcs_ps = new wchar_t[__len];
558132720Skan		  mbsrtowcs(__wcs_ps, &__cpossign, __len, &__state);
559132720Skan		  _M_data->_M_positive_sign = __wcs_ps;
560132720Skan		}
561132720Skan	      else
562132720Skan		_M_data->_M_positive_sign = L"";
563132720Skan              _M_data->_M_positive_sign_size = wcslen(_M_data->_M_positive_sign);
564132720Skan
565132720Skan	      __len = strlen(__cnegsign);
566132720Skan	      if (!__nposn)
567132720Skan		_M_data->_M_negative_sign = L"()";
568132720Skan	      else if (__len)
569132720Skan		{
570132720Skan		  ++__len;
571132720Skan		  memset(&__state, 0, sizeof(mbstate_t));
572132720Skan		  __wcs_ns = new wchar_t[__len];
573132720Skan		  mbsrtowcs(__wcs_ns, &__cnegsign, __len, &__state);
574132720Skan		  _M_data->_M_negative_sign = __wcs_ns;
575132720Skan		}
576132720Skan	      else
577132720Skan		_M_data->_M_negative_sign = L"";
578132720Skan              _M_data->_M_negative_sign_size = wcslen(_M_data->_M_negative_sign);
57997403Sobrien
580132720Skan	      // _Intl == true.
581132720Skan	      __len = strlen(__ccurr);
582132720Skan	      if (__len)
583132720Skan		{
584132720Skan		  ++__len;
585132720Skan		  memset(&__state, 0, sizeof(mbstate_t));
586132720Skan		  wchar_t* __wcs = new wchar_t[__len];
587132720Skan		  mbsrtowcs(__wcs, &__ccurr, __len, &__state);
588132720Skan		  _M_data->_M_curr_symbol = __wcs;
589132720Skan		}
590132720Skan	      else
591132720Skan		_M_data->_M_curr_symbol = L"";
592132720Skan              _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol);
59397403Sobrien	    }
594132720Skan          catch (...)
59597403Sobrien	    {
596132720Skan	      delete _M_data;
597132720Skan              _M_data = 0;
598132720Skan	      delete __wcs_ps;
599132720Skan	      delete __wcs_ns;
600132720Skan#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
601132720Skan	      __uselocale(__old);
602132720Skan#else
603132720Skan	      setlocale(LC_ALL, __old);
604132720Skan	      free(__old);
605132720Skan#endif
606132720Skan              __throw_exception_again;
60797403Sobrien	    }
60897403Sobrien
609132720Skan	  _M_data->_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc));
61097403Sobrien	  char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc));
61197403Sobrien	  char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc));
61297403Sobrien	  char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc));
613132720Skan	  _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
614132720Skan	                                                __pposn);
61597403Sobrien	  char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc));
61697403Sobrien	  char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc));
617132720Skan	  _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
618132720Skan	                                                __nposn);
619102782Skan
620103447Skan#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
621103447Skan	  __uselocale(__old);
622103447Skan#else
623102782Skan	  setlocale(LC_ALL, __old);
624102782Skan	  free(__old);
625103447Skan#endif
62697403Sobrien	}
62797403Sobrien    }
62897403Sobrien
62997403Sobrien  template<>
63097403Sobrien    moneypunct<wchar_t, true>::~moneypunct()
63197403Sobrien    {
632132720Skan      if (_M_data->_M_positive_sign_size)
633132720Skan	delete [] _M_data->_M_positive_sign;
634132720Skan      if (_M_data->_M_negative_sign_size
635132720Skan          && wcscmp(_M_data->_M_negative_sign, L"()") != 0)
636132720Skan	delete [] _M_data->_M_negative_sign;
637132720Skan      if (_M_data->_M_curr_symbol_size)
638132720Skan	delete [] _M_data->_M_curr_symbol;
639132720Skan      delete _M_data;
64097403Sobrien    }
64197403Sobrien
64297403Sobrien  template<>
64397403Sobrien    moneypunct<wchar_t, false>::~moneypunct()
64497403Sobrien    {
645132720Skan      if (_M_data->_M_positive_sign_size)
646132720Skan	delete [] _M_data->_M_positive_sign;
647132720Skan      if (_M_data->_M_negative_sign_size
648132720Skan          && wcscmp(_M_data->_M_negative_sign, L"()") != 0)
649132720Skan	delete [] _M_data->_M_negative_sign;
650132720Skan      if (_M_data->_M_curr_symbol_size)
651132720Skan	delete [] _M_data->_M_curr_symbol;
652132720Skan      delete _M_data;
65397403Sobrien    }
65497403Sobrien#endif
655169691Skan
656169691Skan_GLIBCXX_END_NAMESPACE
657