monetary_members.cc revision 146897
1// std::moneypunct implementation details, GNU version -*- C++ -*-
2
3// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library.  This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 2, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License along
17// with this library; see the file COPYING.  If not, write to the Free
18// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19// USA.
20
21// As a special exception, you may use this file as part of a free software
22// library without restriction.  Specifically, if other files instantiate
23// templates or use macros or inline functions from this file, or you compile
24// this file and link it with other files to produce an executable, this
25// file does not by itself cause the resulting executable to be covered by
26// the GNU General Public License.  This exception does not however
27// invalidate any other reasons why the executable file might be covered by
28// the GNU General Public License.
29
30//
31// ISO C++ 14882: 22.2.6.3.2  moneypunct virtual functions
32//
33
34// Written by Benjamin Kosnik <bkoz@redhat.com>
35
36#include <locale>
37#include <bits/c++locale_internal.h>
38
39namespace 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	  unsigned char uc;
376	  for (size_t __i = 0; __i < money_base::_S_end; ++__i)
377	    {
378	      uc = static_cast<unsigned char>(money_base::_S_atoms[__i]);
379	      _M_data->_M_atoms[__i] = btowc(uc);
380	    }
381	}
382      else
383	{
384	  // Named locale.
385#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
386	  __c_locale __old = __uselocale(__cloc);
387#else
388	  // Switch to named locale so that mbsrtowcs will work.
389	  char* __old = strdup(setlocale(LC_ALL, NULL));
390	  setlocale(LC_ALL, __name);
391#endif
392
393	  union __s_and_w { const char *__s; unsigned int __w; } __u;
394	  __u.__s = __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC, __cloc);
395	  _M_data->_M_decimal_point = static_cast<wchar_t>(__u.__w);
396
397	  __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc);
398	  _M_data->_M_thousands_sep = static_cast<wchar_t>(__u.__w);
399	  _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
400	  _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
401
402	  const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
403	  const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
404	  const char* __ccurr = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc);
405
406	  wchar_t* __wcs_ps = 0;
407	  wchar_t* __wcs_ns = 0;
408	  const char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc));
409	  try
410	    {
411	      mbstate_t __state;
412	      size_t __len = strlen(__cpossign);
413	      if (__len)
414		{
415		  ++__len;
416		  memset(&__state, 0, sizeof(mbstate_t));
417		  __wcs_ps = new wchar_t[__len];
418		  mbsrtowcs(__wcs_ps, &__cpossign, __len, &__state);
419		  _M_data->_M_positive_sign = __wcs_ps;
420		}
421	      else
422		_M_data->_M_positive_sign = L"";
423	      _M_data->_M_positive_sign_size = wcslen(_M_data->_M_positive_sign);
424
425	      __len = strlen(__cnegsign);
426	      if (!__nposn)
427		_M_data->_M_negative_sign = L"()";
428	      else if (__len)
429		{
430		  ++__len;
431		  memset(&__state, 0, sizeof(mbstate_t));
432		  __wcs_ns = new wchar_t[__len];
433		  mbsrtowcs(__wcs_ns, &__cnegsign, __len, &__state);
434		  _M_data->_M_negative_sign = __wcs_ns;
435		}
436	      else
437		_M_data->_M_negative_sign = L"";
438	      _M_data->_M_negative_sign_size = wcslen(_M_data->_M_negative_sign);
439
440	      // _Intl == true.
441	      __len = strlen(__ccurr);
442	      if (__len)
443		{
444		  ++__len;
445		  memset(&__state, 0, sizeof(mbstate_t));
446		  wchar_t* __wcs = new wchar_t[__len];
447		  mbsrtowcs(__wcs, &__ccurr, __len, &__state);
448		  _M_data->_M_curr_symbol = __wcs;
449		}
450	      else
451		_M_data->_M_curr_symbol = L"";
452	      _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol);
453	    }
454	  catch (...)
455	    {
456	      delete _M_data;
457	      _M_data = 0;
458	      delete __wcs_ps;
459	      delete __wcs_ns;
460#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
461	      __uselocale(__old);
462#else
463	      setlocale(LC_ALL, __old);
464	      free(__old);
465#endif
466	      __throw_exception_again;
467	    }
468
469	  _M_data->_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS,
470						      __cloc));
471	  char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc));
472	  char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc));
473	  char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc));
474	  _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
475							__pposn);
476	  char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc));
477	  char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc));
478	  _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
479							__nposn);
480
481#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
482	  __uselocale(__old);
483#else
484	  setlocale(LC_ALL, __old);
485	  free(__old);
486#endif
487	}
488    }
489
490  template<>
491  void
492  moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc,
493#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
494						       const char*)
495#else
496                                                       const char* __name)
497#endif
498  {
499    if (!_M_data)
500      _M_data = new __moneypunct_cache<wchar_t, false>;
501
502    if (!__cloc)
503	{
504	  // "C" locale
505	  _M_data->_M_decimal_point = L'.';
506	  _M_data->_M_thousands_sep = L',';
507	  _M_data->_M_grouping = "";
508          _M_data->_M_grouping_size = 0;
509	  _M_data->_M_curr_symbol = L"";
510	  _M_data->_M_curr_symbol_size = 0;
511	  _M_data->_M_positive_sign = L"";
512	  _M_data->_M_positive_sign_size = 0;
513	  _M_data->_M_negative_sign = L"";
514	  _M_data->_M_negative_sign_size = 0;
515	  _M_data->_M_frac_digits = 0;
516	  _M_data->_M_pos_format = money_base::_S_default_pattern;
517	  _M_data->_M_neg_format = money_base::_S_default_pattern;
518
519	  // Use ctype::widen code without the facet...
520	  unsigned char uc;
521	  for (size_t __i = 0; __i < money_base::_S_end; ++__i)
522	    {
523	      uc = static_cast<unsigned char>(money_base::_S_atoms[__i]);
524	      _M_data->_M_atoms[__i] = btowc(uc);
525	    }
526	}
527      else
528	{
529	  // Named locale.
530#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
531	  __c_locale __old = __uselocale(__cloc);
532#else
533	  // Switch to named locale so that mbsrtowcs will work.
534	  char* __old = strdup(setlocale(LC_ALL, NULL));
535	  setlocale(LC_ALL, __name);
536#endif
537
538	  union __s_and_w { const char *__s; unsigned int __w; } __u;
539	  __u.__s = __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC, __cloc);
540	  _M_data->_M_decimal_point = static_cast<wchar_t>(__u.__w);
541
542	  __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc);
543	  _M_data->_M_thousands_sep = static_cast<wchar_t>(__u.__w);
544	  _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
545          _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
546
547	  const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
548	  const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
549	  const char* __ccurr = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc);
550
551	  wchar_t* __wcs_ps = 0;
552	  wchar_t* __wcs_ns = 0;
553	  const char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc));
554	  try
555            {
556              mbstate_t __state;
557              size_t __len;
558              __len = strlen(__cpossign);
559              if (__len)
560                {
561		  ++__len;
562		  memset(&__state, 0, sizeof(mbstate_t));
563		  __wcs_ps = new wchar_t[__len];
564		  mbsrtowcs(__wcs_ps, &__cpossign, __len, &__state);
565		  _M_data->_M_positive_sign = __wcs_ps;
566		}
567	      else
568		_M_data->_M_positive_sign = L"";
569              _M_data->_M_positive_sign_size = wcslen(_M_data->_M_positive_sign);
570
571	      __len = strlen(__cnegsign);
572	      if (!__nposn)
573		_M_data->_M_negative_sign = L"()";
574	      else if (__len)
575		{
576		  ++__len;
577		  memset(&__state, 0, sizeof(mbstate_t));
578		  __wcs_ns = new wchar_t[__len];
579		  mbsrtowcs(__wcs_ns, &__cnegsign, __len, &__state);
580		  _M_data->_M_negative_sign = __wcs_ns;
581		}
582	      else
583		_M_data->_M_negative_sign = L"";
584              _M_data->_M_negative_sign_size = wcslen(_M_data->_M_negative_sign);
585
586	      // _Intl == true.
587	      __len = strlen(__ccurr);
588	      if (__len)
589		{
590		  ++__len;
591		  memset(&__state, 0, sizeof(mbstate_t));
592		  wchar_t* __wcs = new wchar_t[__len];
593		  mbsrtowcs(__wcs, &__ccurr, __len, &__state);
594		  _M_data->_M_curr_symbol = __wcs;
595		}
596	      else
597		_M_data->_M_curr_symbol = L"";
598              _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol);
599	    }
600          catch (...)
601	    {
602	      delete _M_data;
603              _M_data = 0;
604	      delete __wcs_ps;
605	      delete __wcs_ns;
606#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
607	      __uselocale(__old);
608#else
609	      setlocale(LC_ALL, __old);
610	      free(__old);
611#endif
612              __throw_exception_again;
613	    }
614
615	  _M_data->_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc));
616	  char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc));
617	  char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc));
618	  char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc));
619	  _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
620	                                                __pposn);
621	  char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc));
622	  char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc));
623	  _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
624	                                                __nposn);
625
626#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
627	  __uselocale(__old);
628#else
629	  setlocale(LC_ALL, __old);
630	  free(__old);
631#endif
632	}
633    }
634
635  template<>
636    moneypunct<wchar_t, true>::~moneypunct()
637    {
638      if (_M_data->_M_positive_sign_size)
639	delete [] _M_data->_M_positive_sign;
640      if (_M_data->_M_negative_sign_size
641          && wcscmp(_M_data->_M_negative_sign, L"()") != 0)
642	delete [] _M_data->_M_negative_sign;
643      if (_M_data->_M_curr_symbol_size)
644	delete [] _M_data->_M_curr_symbol;
645      delete _M_data;
646    }
647
648  template<>
649    moneypunct<wchar_t, false>::~moneypunct()
650    {
651      if (_M_data->_M_positive_sign_size)
652	delete [] _M_data->_M_positive_sign;
653      if (_M_data->_M_negative_sign_size
654          && wcscmp(_M_data->_M_negative_sign, L"()") != 0)
655	delete [] _M_data->_M_negative_sign;
656      if (_M_data->_M_curr_symbol_size)
657	delete [] _M_data->_M_curr_symbol;
658      delete _M_data;
659    }
660#endif
661}
662