1/*
2 * Copyright (c) 1999
3 * Silicon Graphics Computer Systems, Inc.
4 *
5 * Copyright (c) 1999
6 * Boris Fomitchev
7 *
8 * This material is provided "as is", with absolutely no warranty expressed
9 * or implied. Any use is at your own risk.
10 *
11 * Permission to use or copy this software for any purpose is hereby granted
12 * without fee, provided the above notices are retained on all copies.
13 * Permission to modify the code and to distribute modified code is granted,
14 * provided the above notices are retained, and a notice that the code was
15 * modified is included with the above copyright notice.
16 *
17 */
18#include "stlport_prefix.h"
19
20#include <locale>
21#include <algorithm>
22#include <typeinfo>
23
24#include "c_locale.h"
25#include "aligned_buffer.h"
26#include "acquire_release.h"
27#include "locale_impl.h"
28
29_STLP_BEGIN_NAMESPACE
30
31static const string _Nameless("*");
32
33static inline bool is_C_locale_name (const char* name)
34{ return ((name[0] == 'C') && (name[1] == 0)); }
35
36locale::facet * _STLP_CALL _get_facet(locale::facet *f)
37{
38  if (f != 0)
39    f->_M_incr();
40  return f;
41}
42
43void _STLP_CALL _release_facet(locale::facet *&f)
44{
45  if ((f != 0) && (f->_M_decr() == 0)) {
46    delete f;
47    f = 0;
48  }
49}
50
51size_t locale::id::_S_max = 27;
52
53static void _Stl_loc_assign_ids();
54
55static _Stl_aligned_buffer<_Locale_impl::Init> __Loc_init_buf;
56
57_Locale_impl::Init::Init() {
58  if (_M_count()._M_incr() == 1) {
59    _Locale_impl::_S_initialize();
60  }
61}
62
63_Locale_impl::Init::~Init() {
64  if (_M_count()._M_decr() == 0) {
65    _Locale_impl::_S_uninitialize();
66  }
67}
68
69_Refcount_Base& _Locale_impl::Init::_M_count() const {
70  static _Refcount_Base _S_count(0);
71  return _S_count;
72}
73
74_Locale_impl::_Locale_impl(const char* s)
75  : _Refcount_Base(0), name(s), facets_vec() {
76  facets_vec.reserve( locale::id::_S_max );
77  new (&__Loc_init_buf) Init();
78}
79
80_Locale_impl::_Locale_impl( _Locale_impl const& locimpl )
81  : _Refcount_Base(0), name(locimpl.name), facets_vec() {
82  for_each( locimpl.facets_vec.begin(), locimpl.facets_vec.end(), _get_facet);
83  facets_vec = locimpl.facets_vec;
84  new (&__Loc_init_buf) Init();
85}
86
87_Locale_impl::_Locale_impl( size_t n, const char* s)
88  : _Refcount_Base(0), name(s), facets_vec(n, 0) {
89  new (&__Loc_init_buf) Init();
90}
91
92_Locale_impl::~_Locale_impl() {
93  (&__Loc_init_buf)->~Init();
94  for_each( facets_vec.begin(), facets_vec.end(), _release_facet);
95}
96
97// Initialization of the locale system.  This must be called before
98// any locales are constructed.  (Meaning that it must be called when
99// the I/O library itself is initialized.)
100void _STLP_CALL _Locale_impl::_S_initialize() {
101  _Stl_loc_assign_ids();
102  make_classic_locale();
103}
104
105// Release of the classic locale ressources. Has to be called after the last
106// locale destruction and not only after the classic locale destruction as
107// the facets can be shared between different facets.
108void _STLP_CALL _Locale_impl::_S_uninitialize() {
109  //Not necessary anymore as classic facets are now 'normal' dynamically allocated
110  //facets with a reference counter telling to _release_facet when the facet can be
111  //deleted.
112  //free_classic_locale();
113}
114
115// _Locale_impl non-inline member functions.
116void _STLP_CALL _Locale_impl::_M_throw_bad_cast() {
117  _STLP_THROW(bad_cast());
118}
119
120void _Locale_impl::insert(_Locale_impl *from, const locale::id& n) {
121  if (n._M_index > 0 && n._M_index < from->size()) {
122    this->insert(from->facets_vec[n._M_index], n);
123  }
124}
125
126locale::facet* _Locale_impl::insert(locale::facet *f, const locale::id& n) {
127  if (f == 0 || n._M_index == 0)
128    return 0;
129
130  if (n._M_index >= facets_vec.size()) {
131    facets_vec.resize(n._M_index + 1);
132  }
133
134  if (f != facets_vec[n._M_index])
135  {
136    _release_facet(facets_vec[n._M_index]);
137    facets_vec[n._M_index] = _get_facet(f);
138  }
139
140  return f;
141}
142
143//
144// <locale> content which is dependent on the name
145//
146
147/* Six functions, one for each category.  Each of them takes a
148 * a name, constructs that appropriate category facets by name,
149 * and inserts them into the locale. */
150_Locale_name_hint* _Locale_impl::insert_ctype_facets(const char* &name, char *buf, _Locale_name_hint* hint) {
151  if (name[0] == 0)
152    name = _Locale_ctype_default(buf);
153
154  if (name == 0 || name[0] == 0 || is_C_locale_name(name)) {
155    _Locale_impl* i2 = locale::classic()._M_impl;
156    this->insert(i2, ctype<char>::id);
157    this->insert(i2, codecvt<char, char, mbstate_t>::id);
158#ifndef _STLP_NO_WCHAR_T
159    this->insert(i2, ctype<wchar_t>::id);
160    this->insert(i2, codecvt<wchar_t, char, mbstate_t>::id);
161#endif
162  } else {
163    locale::facet*    ct  = 0;
164    locale::facet*    cvt = 0;
165#ifndef _STLP_NO_WCHAR_T
166    locale::facet* wct    = 0;
167    locale::facet* wcvt   = 0;
168#endif
169    int __err_code;
170    _Locale_ctype *__lct = _STLP_PRIV __acquire_ctype(name, buf, hint, &__err_code);
171    if (!__lct) {
172      locale::_M_throw_on_creation_failure(__err_code, name, "ctype");
173      return hint;
174    }
175
176    if (hint == 0) hint = _Locale_get_ctype_hint(__lct);
177
178    _STLP_TRY {
179      ct   = new ctype_byname<char>(__lct);
180    }
181    _STLP_UNWIND(_STLP_PRIV __release_ctype(__lct));
182
183    _STLP_TRY {
184      cvt  = new codecvt_byname<char, char, mbstate_t>(name);
185    }
186    _STLP_UNWIND(delete ct);
187
188#ifndef _STLP_NO_WCHAR_T
189    _STLP_TRY {
190      _Locale_ctype *__lwct = _STLP_PRIV __acquire_ctype(name, buf, hint, &__err_code);
191      if (!__lwct) {
192        locale::_M_throw_on_creation_failure(__err_code, name, "ctype");
193        return hint;
194      }
195
196      _STLP_TRY {
197        wct  = new ctype_byname<wchar_t>(__lwct);
198      }
199      _STLP_UNWIND(_STLP_PRIV __release_ctype(__lwct));
200
201      _Locale_codecvt *__lwcvt = _STLP_PRIV __acquire_codecvt(name, buf, hint, &__err_code);
202      if (__lwcvt) {
203        _STLP_TRY {
204          wcvt = new codecvt_byname<wchar_t, char, mbstate_t>(__lwcvt);
205        }
206        _STLP_UNWIND(_STLP_PRIV __release_codecvt(__lwcvt); delete wct);
207      }
208    }
209    _STLP_UNWIND(delete cvt; delete ct);
210#endif
211
212    this->insert(ct, ctype<char>::id);
213    this->insert(cvt, codecvt<char, char, mbstate_t>::id);
214#ifndef _STLP_NO_WCHAR_T
215    this->insert(wct, ctype<wchar_t>::id);
216    if (wcvt) this->insert(wcvt, codecvt<wchar_t, char, mbstate_t>::id);
217#endif
218  }
219  return hint;
220}
221
222_Locale_name_hint* _Locale_impl::insert_numeric_facets(const char* &name, char *buf, _Locale_name_hint* hint) {
223  if (name[0] == 0)
224    name = _Locale_numeric_default(buf);
225
226  _Locale_impl* i2 = locale::classic()._M_impl;
227
228  // We first insert name independant facets taken from the classic locale instance:
229  this->insert(i2,
230               num_put<char, ostreambuf_iterator<char, char_traits<char> >  >::id);
231  this->insert(i2,
232               num_get<char, istreambuf_iterator<char, char_traits<char> > >::id);
233#ifndef _STLP_NO_WCHAR_T
234  this->insert(i2,
235               num_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> >  >::id);
236  this->insert(i2,
237               num_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id);
238#endif
239
240  if (name == 0 || name[0] == 0 || is_C_locale_name(name)) {
241    this->insert(i2, numpunct<char>::id);
242#ifndef _STLP_NO_WCHAR_T
243    this->insert(i2, numpunct<wchar_t>::id);
244#endif
245  }
246  else {
247    locale::facet* punct  = 0;
248#ifndef _STLP_NO_WCHAR_T
249    locale::facet* wpunct = 0;
250#endif
251
252    int __err_code;
253    _Locale_numeric *__lpunct = _STLP_PRIV __acquire_numeric(name, buf, hint, &__err_code);
254    if (!__lpunct) {
255      locale::_M_throw_on_creation_failure(__err_code, name, "numpunct");
256      return hint;
257    }
258
259    if (hint == 0) hint = _Locale_get_numeric_hint(__lpunct);
260    _STLP_TRY {
261      punct = new numpunct_byname<char>(__lpunct);
262    }
263    _STLP_UNWIND(_STLP_PRIV __release_numeric(__lpunct));
264
265#ifndef _STLP_NO_WCHAR_T
266    _Locale_numeric *__lwpunct = _STLP_PRIV __acquire_numeric(name, buf, hint, &__err_code);
267    if (!__lwpunct) {
268      delete punct;
269      locale::_M_throw_on_creation_failure(__err_code, name, "numpunct");
270      return hint;
271    }
272    if (__lwpunct) {
273      _STLP_TRY {
274        wpunct  = new numpunct_byname<wchar_t>(__lwpunct);
275      }
276      _STLP_UNWIND(_STLP_PRIV __release_numeric(__lwpunct); delete punct);
277    }
278#endif
279
280    this->insert(punct, numpunct<char>::id);
281#ifndef _STLP_NO_WCHAR_T
282    this->insert(wpunct, numpunct<wchar_t>::id);
283#endif
284  }
285  return hint;
286}
287
288_Locale_name_hint* _Locale_impl::insert_time_facets(const char* &name, char *buf, _Locale_name_hint* hint) {
289  if (name[0] == 0)
290    name = _Locale_time_default(buf);
291
292  if (name == 0 || name[0] == 0 || is_C_locale_name(name)) {
293    _Locale_impl* i2 = locale::classic()._M_impl;
294    this->insert(i2,
295                 time_get<char, istreambuf_iterator<char, char_traits<char> > >::id);
296    this->insert(i2,
297                 time_put<char, ostreambuf_iterator<char, char_traits<char> > >::id);
298#ifndef _STLP_NO_WCHAR_T
299    this->insert(i2,
300                 time_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id);
301    this->insert(i2,
302                 time_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id);
303#endif
304  } else {
305    locale::facet *get = 0;
306    locale::facet *put = 0;
307#ifndef _STLP_NO_WCHAR_T
308    locale::facet *wget = 0;
309    locale::facet *wput = 0;
310#endif
311
312    int __err_code;
313    _Locale_time *__time = _STLP_PRIV __acquire_time(name, buf, hint, &__err_code);
314    if (!__time) {
315      // time facets category is not mandatory for correct stream behavior so if platform
316      // do not support it we do not generate a runtime_error exception.
317      if (__err_code == _STLP_LOC_NO_MEMORY) {
318        _STLP_THROW_BAD_ALLOC;
319      }
320      return hint;
321    }
322
323    if (!hint) hint = _Locale_get_time_hint(__time);
324    _STLP_TRY {
325      get = new time_get_byname<char, istreambuf_iterator<char, char_traits<char> > >(__time);
326      put = new time_put_byname<char, ostreambuf_iterator<char, char_traits<char> > >(__time);
327#ifndef _STLP_NO_WCHAR_T
328      wget = new time_get_byname<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >(__time);
329      wput = new time_put_byname<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >(__time);
330#endif
331    }
332#ifndef _STLP_NO_WCHAR_T
333    _STLP_UNWIND(delete wget; delete put; delete get; _STLP_PRIV __release_time(__time));
334#else
335    _STLP_UNWIND(delete get; _STLP_PRIV __release_time(__time));
336#endif
337
338    _STLP_PRIV __release_time(__time);
339
340    this->insert(get, time_get<char, istreambuf_iterator<char, char_traits<char> > >::id);
341    this->insert(put, time_put<char, ostreambuf_iterator<char, char_traits<char> > >::id);
342#ifndef _STLP_NO_WCHAR_T
343    this->insert(wget, time_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id);
344    this->insert(wput, time_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id);
345#endif
346  }
347  return hint;
348}
349
350_Locale_name_hint* _Locale_impl::insert_collate_facets(const char* &name, char *buf, _Locale_name_hint* hint) {
351  if (name[0] == 0)
352    name = _Locale_collate_default(buf);
353
354  if (name == 0 || name[0] == 0 || is_C_locale_name(name)) {
355    _Locale_impl* i2 = locale::classic()._M_impl;
356    this->insert(i2, collate<char>::id);
357#ifndef _STLP_NO_WCHAR_T
358    this->insert(i2, collate<wchar_t>::id);
359#endif
360  }
361  else {
362    locale::facet *col = 0;
363#ifndef _STLP_NO_WCHAR_T
364    locale::facet *wcol = 0;
365#endif
366
367    int __err_code;
368    _Locale_collate *__coll = _STLP_PRIV __acquire_collate(name, buf, hint, &__err_code);
369    if (!__coll) {
370      if (__err_code == _STLP_LOC_NO_MEMORY) {
371        _STLP_THROW_BAD_ALLOC;
372      }
373      return hint;
374    }
375
376    if (hint == 0) hint = _Locale_get_collate_hint(__coll);
377    _STLP_TRY {
378      col = new collate_byname<char>(__coll);
379    }
380    _STLP_UNWIND(_STLP_PRIV __release_collate(__coll));
381
382#ifndef _STLP_NO_WCHAR_T
383    _Locale_collate *__wcoll = _STLP_PRIV __acquire_collate(name, buf, hint, &__err_code);
384    if (!__wcoll) {
385      if (__err_code == _STLP_LOC_NO_MEMORY) {
386        delete col;
387        _STLP_THROW_BAD_ALLOC;
388      }
389    }
390    if (__wcoll) {
391      _STLP_TRY {
392        wcol  = new collate_byname<wchar_t>(__wcoll);
393      }
394      _STLP_UNWIND(_STLP_PRIV __release_collate(__wcoll); delete col);
395    }
396#endif
397
398    this->insert(col, collate<char>::id);
399#ifndef _STLP_NO_WCHAR_T
400    if (wcol) this->insert(wcol, collate<wchar_t>::id);
401#endif
402  }
403  return hint;
404}
405
406_Locale_name_hint* _Locale_impl::insert_monetary_facets(const char* &name, char *buf, _Locale_name_hint* hint) {
407  if (name[0] == 0)
408    name = _Locale_monetary_default(buf);
409
410  _Locale_impl* i2 = locale::classic()._M_impl;
411
412  // We first insert name independant facets taken from the classic locale instance:
413  this->insert(i2, money_get<char, istreambuf_iterator<char, char_traits<char> > >::id);
414  this->insert(i2, money_put<char, ostreambuf_iterator<char, char_traits<char> > >::id);
415#ifndef _STLP_NO_WCHAR_T
416  this->insert(i2, money_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id);
417  this->insert(i2, money_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id);
418#endif
419
420  if (name == 0 || name[0] == 0 || is_C_locale_name(name)) {
421    this->insert(i2, moneypunct<char, false>::id);
422    this->insert(i2, moneypunct<char, true>::id);
423#ifndef _STLP_NO_WCHAR_T
424    this->insert(i2, moneypunct<wchar_t, false>::id);
425    this->insert(i2, moneypunct<wchar_t, true>::id);
426#endif
427  }
428  else {
429    locale::facet *punct   = 0;
430    locale::facet *ipunct  = 0;
431
432#ifndef _STLP_NO_WCHAR_T
433    locale::facet* wpunct  = 0;
434    locale::facet* wipunct = 0;
435#endif
436
437    int __err_code;
438    _Locale_monetary *__mon = _STLP_PRIV __acquire_monetary(name, buf, hint, &__err_code);
439    if (!__mon) {
440      if (__err_code == _STLP_LOC_NO_MEMORY) {
441        _STLP_THROW_BAD_ALLOC;
442      }
443      return hint;
444    }
445
446    if (hint == 0) hint = _Locale_get_monetary_hint(__mon);
447
448    _STLP_TRY {
449      punct   = new moneypunct_byname<char, false>(__mon);
450    }
451    _STLP_UNWIND(_STLP_PRIV __release_monetary(__mon));
452
453    _Locale_monetary *__imon = _STLP_PRIV __acquire_monetary(name, buf, hint, &__err_code);
454    if (!__imon) {
455      delete punct;
456      if (__err_code == _STLP_LOC_NO_MEMORY) {
457        _STLP_THROW_BAD_ALLOC;
458      }
459      return hint;
460    }
461
462    _STLP_TRY {
463      ipunct  = new moneypunct_byname<char, true>(__imon);
464    }
465    _STLP_UNWIND(_STLP_PRIV __release_monetary(__imon); delete punct);
466
467#ifndef _STLP_NO_WCHAR_T
468    _STLP_TRY {
469      _Locale_monetary *__wmon = _STLP_PRIV __acquire_monetary(name, buf, hint, &__err_code);
470      if (!__wmon) {
471        if (__err_code == _STLP_LOC_NO_MEMORY) {
472          _STLP_THROW_BAD_ALLOC;
473        }
474      }
475
476      if (__wmon) {
477        _STLP_TRY {
478          wpunct  = new moneypunct_byname<wchar_t, false>(__wmon);
479        }
480        _STLP_UNWIND(_STLP_PRIV __release_monetary(__wmon));
481
482        _Locale_monetary *__wimon = _STLP_PRIV __acquire_monetary(name, buf, hint, &__err_code);
483        if (!__wimon) {
484          delete wpunct;
485          if (__err_code == _STLP_LOC_NO_MEMORY) {
486            _STLP_THROW_BAD_ALLOC;
487          }
488          wpunct = 0;
489        }
490        else {
491          _STLP_TRY {
492            wipunct = new moneypunct_byname<wchar_t, true>(__wimon);
493          }
494          _STLP_UNWIND(_STLP_PRIV __release_monetary(__wimon); delete wpunct);
495        }
496      }
497    }
498    _STLP_UNWIND(delete ipunct; delete punct);
499#endif
500
501    this->insert(punct, moneypunct<char, false>::id);
502    this->insert(ipunct, moneypunct<char, true>::id);
503#ifndef _STLP_NO_WCHAR_T
504    if (wpunct) this->insert(wpunct, moneypunct<wchar_t, false>::id);
505    if (wipunct) this->insert(wipunct, moneypunct<wchar_t, true>::id);
506#endif
507  }
508  return hint;
509}
510
511_Locale_name_hint* _Locale_impl::insert_messages_facets(const char* &name, char *buf, _Locale_name_hint* hint) {
512  if (name[0] == 0)
513    name = _Locale_messages_default(buf);
514
515  if (name == 0 || name[0] == 0 || is_C_locale_name(name)) {
516    _Locale_impl* i2 = locale::classic()._M_impl;
517    this->insert(i2, messages<char>::id);
518#ifndef _STLP_NO_WCHAR_T
519    this->insert(i2, messages<wchar_t>::id);
520#endif
521  }
522  else {
523    locale::facet *msg  = 0;
524#ifndef _STLP_NO_WCHAR_T
525    locale::facet *wmsg = 0;
526#endif
527
528    int __err_code;
529    _Locale_messages *__msg = _STLP_PRIV __acquire_messages(name, buf, hint, &__err_code);
530    if (!__msg) {
531      if (__err_code == _STLP_LOC_NO_MEMORY) {
532        _STLP_THROW_BAD_ALLOC;
533      }
534      return hint;
535    }
536
537    _STLP_TRY {
538      msg  = new messages_byname<char>(__msg);
539    }
540    _STLP_UNWIND(_STLP_PRIV __release_messages(__msg));
541
542#ifndef _STLP_NO_WCHAR_T
543    _STLP_TRY {
544      _Locale_messages *__wmsg = _STLP_PRIV __acquire_messages(name, buf, hint, &__err_code);
545      if (!__wmsg) {
546        if (__err_code == _STLP_LOC_NO_MEMORY) {
547          _STLP_THROW_BAD_ALLOC;
548        }
549      }
550
551      if (__wmsg) {
552        _STLP_TRY {
553          wmsg = new messages_byname<wchar_t>(__wmsg);
554        }
555        _STLP_UNWIND(_STLP_PRIV __release_messages(__wmsg));
556      }
557    }
558    _STLP_UNWIND(delete msg);
559#endif
560
561    this->insert(msg, messages<char>::id);
562#ifndef _STLP_NO_WCHAR_T
563    if (wmsg) this->insert(wmsg, messages<wchar_t>::id);
564#endif
565  }
566  return hint;
567}
568
569static void _Stl_loc_assign_ids() {
570  // This assigns ids to every facet that is a member of a category,
571  // and also to money_get/put, num_get/put, and time_get/put
572  // instantiated using ordinary pointers as the input/output
573  // iterators.  (The default is [io]streambuf_iterator.)
574
575  money_get<char, istreambuf_iterator<char, char_traits<char> > >::id._M_index          = 8;
576  money_put<char, ostreambuf_iterator<char, char_traits<char> > >::id._M_index          = 9;
577  num_get<char, istreambuf_iterator<char, char_traits<char> > >::id._M_index            = 10;
578  num_put<char, ostreambuf_iterator<char, char_traits<char> > >::id._M_index            = 11;
579  time_get<char, istreambuf_iterator<char, char_traits<char> > >::id._M_index           = 12;
580  time_put<char, ostreambuf_iterator<char, char_traits<char> > >::id._M_index           = 13;
581
582#ifndef _STLP_NO_WCHAR_T
583  money_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id._M_index = 21;
584  money_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id._M_index = 22;
585  num_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id._M_index   = 23;
586  num_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > > ::id._M_index  = 24;
587  time_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id._M_index  = 25;
588  time_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id._M_index  = 26;
589#endif
590  //  locale::id::_S_max                               = 27;
591}
592
593// To access those static instance use the getter below, they guaranty
594// a correct initialization.
595static locale *_Stl_classic_locale = 0;
596static locale *_Stl_global_locale = 0;
597
598locale* _Stl_get_classic_locale() {
599  static _Locale_impl::Init init;
600  return _Stl_classic_locale;
601}
602
603locale* _Stl_get_global_locale() {
604  static _Locale_impl::Init init;
605  return _Stl_global_locale;
606}
607
608#if defined (_STLP_MSVC) || defined (__ICL) || defined (__ISCPP__) || defined (__DMC__)
609/*
610 * The following static variable needs to be initialized before STLport
611 * users static variable in order for him to be able to use Standard
612 * streams in its variable initialization.
613 * This variable is here because MSVC do not allow to change the initialization
614 * segment in a given translation unit, iostream.cpp already contains an
615 * initialization segment specification.
616 */
617#  pragma warning (disable : 4073)
618#  pragma init_seg(lib)
619#endif
620
621static ios_base::Init _IosInit;
622
623void _Locale_impl::make_classic_locale() {
624  // This funcion will be called once: during build classic _Locale_impl
625
626  // The classic locale contains every facet that belongs to a category.
627  static _Stl_aligned_buffer<_Locale_impl> _Locale_classic_impl_buf;
628  _Locale_impl *classic = new(&_Locale_classic_impl_buf) _Locale_impl("C");
629
630  locale::facet* classic_facets[] = {
631    0,
632    new collate<char>(1),
633    new ctype<char>(0, false, 1),
634    new codecvt<char, char, mbstate_t>(1),
635    new moneypunct<char, true>(1),
636    new moneypunct<char, false>(1),
637    new numpunct<char>(1),
638    new messages<char>(1),
639    new money_get<char, istreambuf_iterator<char, char_traits<char> > >(1),
640    new money_put<char, ostreambuf_iterator<char, char_traits<char> > >(1),
641    new num_get<char, istreambuf_iterator<char, char_traits<char> > >(1),
642    new num_put<char, ostreambuf_iterator<char, char_traits<char> > >(1),
643    new time_get<char, istreambuf_iterator<char, char_traits<char> > >(1),
644    new time_put<char, ostreambuf_iterator<char, char_traits<char> > >(1),
645#ifndef _STLP_NO_WCHAR_T
646    new collate<wchar_t>(1),
647    new ctype<wchar_t>(1),
648    new codecvt<wchar_t, char, mbstate_t>(1),
649    new moneypunct<wchar_t, true>(1),
650    new moneypunct<wchar_t, false>(1),
651    new numpunct<wchar_t>(1),
652    new messages<wchar_t>(1),
653    new money_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >(1),
654    new money_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >(1),
655    new num_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >(1),
656    new num_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >(1),
657    new time_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >(1),
658    new time_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >(1),
659#endif
660    0
661  };
662
663  const size_t nb_classic_facets = sizeof(classic_facets) / sizeof(locale::facet *);
664  classic->facets_vec.reserve(nb_classic_facets);
665  classic->facets_vec.assign(&classic_facets[0], &classic_facets[0] + nb_classic_facets);
666
667  static locale _Locale_classic(classic);
668  _Stl_classic_locale = &_Locale_classic;
669
670  static locale _Locale_global(classic);
671  _Stl_global_locale = &_Locale_global;
672}
673
674// Declarations of (non-template) facets' static data members
675// size_t locale::id::_S_max = 27; // made before
676
677locale::id collate<char>::id = { 1 };
678locale::id ctype<char>::id = { 2 };
679locale::id codecvt<char, char, mbstate_t>::id = { 3 };
680locale::id moneypunct<char, true>::id = { 4 };
681locale::id moneypunct<char, false>::id = { 5 };
682locale::id numpunct<char>::id = { 6 } ;
683locale::id messages<char>::id = { 7 };
684
685#ifndef _STLP_NO_WCHAR_T
686locale::id collate<wchar_t>::id = { 14 };
687locale::id ctype<wchar_t>::id = { 15 };
688locale::id codecvt<wchar_t, char, mbstate_t>::id = { 16 };
689locale::id moneypunct<wchar_t, true>::id = { 17 } ;
690locale::id moneypunct<wchar_t, false>::id = { 18 } ;
691locale::id numpunct<wchar_t>::id = { 19 };
692locale::id messages<wchar_t>::id = { 20 };
693#endif
694
695_STLP_DECLSPEC _Locale_impl* _STLP_CALL _get_Locale_impl(_Locale_impl *loc)
696{
697  _STLP_ASSERT( loc != 0 );
698  loc->_M_incr();
699  return loc;
700}
701
702void _STLP_CALL _release_Locale_impl(_Locale_impl *& loc)
703{
704  _STLP_ASSERT( loc != 0 );
705  if (loc->_M_decr() == 0) {
706    if (*loc != *_Stl_classic_locale)
707      delete loc;
708    else
709      loc->~_Locale_impl();
710    loc = 0;
711  }
712}
713
714_STLP_DECLSPEC _Locale_impl* _STLP_CALL _copy_Nameless_Locale_impl(_Locale_impl *loc)
715{
716  _STLP_ASSERT( loc != 0 );
717  _Locale_impl *loc_new = new _Locale_impl(*loc);
718  loc_new->name = _Nameless;
719  return loc_new;
720}
721
722/* _GetFacetId implementation have to be here in order to be in the same translation unit
723 * as where id are initialize (in _Stl_loc_assign_ids) */
724_STLP_MOVE_TO_PRIV_NAMESPACE
725
726_STLP_DECLSPEC locale::id& _STLP_CALL _GetFacetId(const money_get<char, istreambuf_iterator<char, char_traits<char> > >*)
727{ return money_get<char, istreambuf_iterator<char, char_traits<char> > >::id; }
728_STLP_DECLSPEC locale::id& _STLP_CALL _GetFacetId(const money_put<char, ostreambuf_iterator<char, char_traits<char> > >*)
729{ return money_put<char, ostreambuf_iterator<char, char_traits<char> > >::id; }
730#ifndef _STLP_NO_WCHAR_T
731_STLP_DECLSPEC locale::id& _STLP_CALL _GetFacetId(const money_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >*)
732{ return money_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id; }
733_STLP_DECLSPEC locale::id& _STLP_CALL _GetFacetId(const money_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >*)
734{ return money_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id; }
735#endif
736
737_STLP_DECLSPEC locale::id& _STLP_CALL _GetFacetId(const num_get<char, istreambuf_iterator<char, char_traits<char> > >*)
738{ return num_get<char, istreambuf_iterator<char, char_traits<char> > >::id; }
739#ifndef _STLP_NO_WCHAR_T
740_STLP_DECLSPEC locale::id& _STLP_CALL _GetFacetId(const num_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >*)
741{ return num_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id; }
742#endif
743
744_STLP_DECLSPEC locale::id& _STLP_CALL _GetFacetId(const num_put<char, ostreambuf_iterator<char, char_traits<char> > >*)
745{ return num_put<char, ostreambuf_iterator<char, char_traits<char> > >::id; }
746#ifndef _STLP_NO_WCHAR_T
747_STLP_DECLSPEC locale::id& _STLP_CALL _GetFacetId(const num_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >*)
748{ return num_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id; }
749#endif
750
751_STLP_DECLSPEC locale::id& _STLP_CALL _GetFacetId(const time_get<char, istreambuf_iterator<char, char_traits<char> > >*)
752{ return time_get<char, istreambuf_iterator<char, char_traits<char> > >::id; }
753_STLP_DECLSPEC locale::id& _STLP_CALL _GetFacetId(const time_put<char, ostreambuf_iterator<char, char_traits<char> > >*)
754{ return time_put<char, ostreambuf_iterator<char, char_traits<char> > >::id; }
755#ifndef _STLP_NO_WCHAR_T
756_STLP_DECLSPEC locale::id& _STLP_CALL _GetFacetId(const time_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >*)
757{ return time_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id; }
758_STLP_DECLSPEC locale::id& _STLP_CALL _GetFacetId(const time_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >*)
759{ return time_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id; }
760#endif
761
762_STLP_MOVE_TO_STD_NAMESPACE
763
764_STLP_END_NAMESPACE
765
766