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