OSDN Git Service

* Makefile.in (cse.o): Add params.h dependency.
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / src / localename.cc
1 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
2 // Free Software Foundation, Inc.
3 //
4 // This file is part of the GNU ISO C++ Library.  This library is free
5 // software; you can redistribute it and/or modify it under the
6 // terms of the GNU General Public License as published by the
7 // Free Software Foundation; either version 2, or (at your option)
8 // any later version.
9
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14
15 // You should have received a copy of the GNU General Public License along
16 // with this library; see the file COPYING.  If not, write to the Free
17 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
18 // USA.
19
20 // As a special exception, you may use this file as part of a free software
21 // library without restriction.  Specifically, if other files instantiate
22 // templates or use macros or inline functions from this file, or you compile
23 // this file and link it with other files to produce an executable, this
24 // file does not by itself cause the resulting executable to be covered by
25 // the GNU General Public License.  This exception does not however
26 // invalidate any other reasons why the executable file might be covered by
27 // the GNU General Public License.
28
29 #include <clocale>
30 #include <cstring>
31 #include <locale>
32
33 namespace __gnu_cxx
34 {
35   using namespace std;
36
37   // Defined in globals.cc.
38   extern locale::facet* facet_vec[_GLIBCPP_NUM_FACETS];
39   extern char* name_vec[6 + _GLIBCPP_NUM_CATEGORIES];
40   extern char name_c[6 + _GLIBCPP_NUM_CATEGORIES][2];
41
42   extern std::ctype<char>                       ctype_c;
43   extern std::collate<char>                     collate_c;
44   extern numpunct<char>                         numpunct_c;
45   extern num_get<char>                          num_get_c;
46   extern num_put<char>                          num_put_c;
47   extern codecvt<char, char, mbstate_t>         codecvt_c;
48   extern moneypunct<char, false>                moneypunct_fc;
49   extern moneypunct<char, true>                 moneypunct_tc;
50   extern money_get<char>                        money_get_c;
51   extern money_put<char>                        money_put_c;
52   extern __timepunct<char>                      timepunct_c;
53   extern time_get<char>                         time_get_c;
54   extern time_put<char>                         time_put_c;
55   extern std::messages<char>                    messages_c;
56 #ifdef  _GLIBCPP_USE_WCHAR_T
57   extern std::ctype<wchar_t>                    ctype_w;
58   extern std::collate<wchar_t>                  collate_w;
59   extern numpunct<wchar_t>                      numpunct_w;
60   extern num_get<wchar_t>                       num_get_w;
61   extern num_put<wchar_t>                       num_put_w;
62   extern codecvt<wchar_t, char, mbstate_t>      codecvt_w;
63   extern moneypunct<wchar_t, false>             moneypunct_fw;
64   extern moneypunct<wchar_t, true>              moneypunct_tw;
65   extern money_get<wchar_t>                     money_get_w;
66   extern money_put<wchar_t>                     money_put_w;
67   extern __timepunct<wchar_t>                   timepunct_w;
68   extern time_get<wchar_t>                      time_get_w;
69   extern time_put<wchar_t>                      time_put_w;
70   extern std::messages<wchar_t>                 messages_w;
71 #endif
72 } // namespace __gnu_cxx
73
74 namespace std
75 {
76   using namespace __gnu_cxx;
77
78   locale::_Impl::
79   ~_Impl() throw()
80   {
81     for (size_t __i = 0; __i < _M_facets_size; ++__i)
82       if (_M_facets[__i])
83         _M_facets[__i]->_M_remove_reference();
84     delete [] _M_facets;
85
86     for (size_t __i = 0; __i < _S_categories_size; ++__i)
87       delete [] _M_names[__i];  
88     delete [] _M_names;
89   }
90
91   // Clone existing _Impl object.
92   locale::_Impl::
93   _Impl(const _Impl& __imp, size_t __refs)
94   : _M_references(__refs), _M_facets_size(__imp._M_facets_size) // XXX
95   {
96     try
97       { 
98         _M_facets = new const facet*[_M_facets_size]; 
99         for (size_t __i = 0; __i < _M_facets_size; ++__i)
100           _M_facets[__i] = 0;
101       }
102     catch(...) 
103       {
104         delete [] _M_facets;
105         __throw_exception_again;
106       }
107     for (size_t __i = 0; __i < _M_facets_size; ++__i)
108       {
109         _M_facets[__i] = __imp._M_facets[__i];
110         if (_M_facets[__i])
111           _M_facets[__i]->_M_add_reference();
112       }
113
114     try 
115       {
116         _M_names = new char*[_S_categories_size];
117       }
118     catch(...)
119       {
120         delete [] _M_names;
121         __throw_exception_again;
122       }
123     for (size_t __i = 0; __i < _S_categories_size; ++__i)
124       {
125         char* __new = new char[strlen(__imp._M_names[__i]) + 1];
126         strcpy(__new, __imp._M_names[__i]);
127         _M_names[__i] = __new;
128       }
129   }
130
131   // Construct named _Impl.
132   locale::_Impl::
133   _Impl(const char* __s, size_t __refs) 
134   : _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS) 
135   {
136     // Initialize the underlying locale model, which also checks
137     // to see if the given name is valid.
138     __c_locale __cloc;
139     locale::facet::_S_create_c_locale(__cloc, __s);
140
141     try
142       { 
143         _M_facets = new const facet*[_M_facets_size]; 
144         for (size_t __i = 0; __i < _M_facets_size; ++__i)
145           _M_facets[__i] = 0;
146       }
147     catch(...) 
148       {
149         delete [] _M_facets;
150         __throw_exception_again;
151       }
152
153     // Name all the categories.
154     try 
155       {
156         _M_names = new char*[_S_categories_size];
157       }
158     catch(...)
159       {
160         delete [] _M_names;
161         __throw_exception_again;
162       }
163     size_t __len = strlen(__s);
164     if (!strchr(__s, ';'))
165       {
166         for (size_t __i = 0; __i < _S_categories_size; ++__i)
167           {
168             _M_names[__i] = new char[__len + 1];
169             strcpy(_M_names[__i], __s);
170           }
171       }
172     else
173       {
174         const char* __beg = __s;
175         for (size_t __i = 0; __i < _S_categories_size; ++__i)
176           {
177             __beg = strchr(__beg, '=') + 1;
178             const char* __end = strchr(__beg, ';');
179             if (!__end)
180               __end = __s + __len;
181             char* __new = new char[__end - __beg + 1];
182             memcpy(__new, __beg, __end - __beg);
183             __new[__end - __beg] = '\0';
184             _M_names[__i] = __new;
185           }
186       }
187
188     // Construct all standard facets and add them to _M_facets.  
189     _M_init_facet(new std::ctype<char>(__cloc, 0, false));
190     _M_init_facet(new codecvt<char, char, mbstate_t>(__cloc));
191     _M_init_facet(new numpunct<char>(__cloc));
192     _M_init_facet(new num_get<char>);
193     _M_init_facet(new num_put<char>);
194     _M_init_facet(new std::collate<char>(__cloc));
195     _M_init_facet(new moneypunct<char, false>(__cloc, __s));
196     _M_init_facet(new moneypunct<char, true>(__cloc, __s));
197     _M_init_facet(new money_get<char>);
198     _M_init_facet(new money_put<char>);
199     _M_init_facet(new __timepunct<char>(__cloc, __s));
200     _M_init_facet(new time_get<char>);
201     _M_init_facet(new time_put<char>);
202     _M_init_facet(new std::messages<char>(__cloc, __s));
203         
204 #ifdef  _GLIBCPP_USE_WCHAR_T
205     _M_init_facet(new std::ctype<wchar_t>(__cloc));
206     _M_init_facet(new codecvt<wchar_t, char, mbstate_t>(__cloc));
207     _M_init_facet(new numpunct<wchar_t>(__cloc));
208     _M_init_facet(new num_get<wchar_t>);
209     _M_init_facet(new num_put<wchar_t>);
210     _M_init_facet(new std::collate<wchar_t>(__cloc));
211     _M_init_facet(new moneypunct<wchar_t, false>(__cloc, __s));
212     _M_init_facet(new moneypunct<wchar_t, true>(__cloc, __s));
213     _M_init_facet(new money_get<wchar_t>);
214     _M_init_facet(new money_put<wchar_t>);
215     _M_init_facet(new __timepunct<wchar_t>(__cloc, __s));
216     _M_init_facet(new time_get<wchar_t>);
217     _M_init_facet(new time_put<wchar_t>);
218     _M_init_facet(new std::messages<wchar_t>(__cloc, __s));
219 #endif    
220     locale::facet::_S_destroy_c_locale(__cloc);
221   }
222
223   // Construct "C" _Impl.
224   locale::_Impl::
225   _Impl(facet**, size_t __refs, bool) 
226   : _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS)
227   {
228     // Initialize the underlying locale model.
229     locale::facet::_S_c_name[0] = 'C';
230     locale::facet::_S_c_name[1] = '\0';
231     locale::facet::_S_create_c_locale(locale::facet::_S_c_locale, 
232                                       locale::facet::_S_c_name);
233
234     _M_facets = new (&facet_vec) const facet*[_M_facets_size];
235     for (size_t __i = 0; __i < _M_facets_size; ++__i)
236       _M_facets[__i] = 0;
237
238     // Name all the categories.
239     _M_names = new (&name_vec) char*[_S_categories_size];
240     for (size_t __i = 0; __i < _S_categories_size; ++__i)
241       {
242         _M_names[__i] = new (&name_c[__i]) char[2];
243         strcpy(_M_names[__i], locale::facet::_S_c_name);
244       }
245
246     // This is needed as presently the C++ version of "C" locales
247     // != data in the underlying locale model for __timepunct,
248     // numpunct, and moneypunct. Also, the "C" locales must be
249     // constructed in a way such that they are pre-allocated.
250     // NB: Set locale::facets(ref) count to one so that each individual
251     // facet is not destroyed when the locale (and thus locale::_Impl) is
252     // destroyed.
253     _M_init_facet(new (&ctype_c) std::ctype<char>(0, false, 1));
254     _M_init_facet(new (&codecvt_c) codecvt<char, char, mbstate_t>(1));
255     _M_init_facet(new (&numpunct_c) numpunct<char>(1));
256     _M_init_facet(new (&num_get_c) num_get<char>(1));
257     _M_init_facet(new (&num_put_c) num_put<char>(1));
258     _M_init_facet(new (&collate_c) std::collate<char>(1));
259     _M_init_facet(new (&moneypunct_fc) moneypunct<char, false>(1));
260     _M_init_facet(new (&moneypunct_tc) moneypunct<char, true>(1));
261     _M_init_facet(new (&money_get_c) money_get<char>(1));
262     _M_init_facet(new (&money_put_c) money_put<char>(1));
263     _M_init_facet(new (&timepunct_c) __timepunct<char>(1));
264     _M_init_facet(new (&time_get_c) time_get<char>(1));
265     _M_init_facet(new (&time_put_c) time_put<char>(1));
266     _M_init_facet(new (&messages_c) std::messages<char>(1));    
267 #ifdef  _GLIBCPP_USE_WCHAR_T
268     _M_init_facet(new (&ctype_w) std::ctype<wchar_t>(1));
269     _M_init_facet(new (&codecvt_w) codecvt<wchar_t, char, mbstate_t>(1));
270     _M_init_facet(new (&numpunct_w) numpunct<wchar_t>(1));
271     _M_init_facet(new (&num_get_w) num_get<wchar_t>(1));
272     _M_init_facet(new (&num_put_w) num_put<wchar_t>(1));
273     _M_init_facet(new (&collate_w) std::collate<wchar_t>(1));
274     _M_init_facet(new (&moneypunct_fw) moneypunct<wchar_t, false>(1));
275     _M_init_facet(new (&moneypunct_tw) moneypunct<wchar_t, true>(1));
276     _M_init_facet(new (&money_get_w) money_get<wchar_t>(1));
277     _M_init_facet(new (&money_put_w) money_put<wchar_t>(1));
278     _M_init_facet(new (&timepunct_w) __timepunct<wchar_t>(1));
279     _M_init_facet(new (&time_get_w) time_get<wchar_t>(1));
280     _M_init_facet(new (&time_put_w) time_put<wchar_t>(1));
281     _M_init_facet(new (&messages_w) std::messages<wchar_t>(1));
282 #endif 
283   }
284   
285   void
286   locale::_Impl::
287   _M_replace_categories(const _Impl* __imp, category __cat)
288   {
289     category __mask;
290     for (size_t __ix = 0; __ix < _S_categories_size; ++__ix)
291       {
292         __mask = 1 << __ix;
293         if (__mask & __cat)
294           {
295             // Need to replace entry in _M_facets with other locale's info.
296             _M_replace_category(__imp, _S_facet_categories[__ix]);
297             // If both have names, go ahead and mangle.
298             if (strcmp(_M_names[__ix], "*") != 0 
299                 && strcmp(__imp->_M_names[__ix], "*") != 0)
300               {
301                 delete [] _M_names[__ix];
302                 char* __new = new char[strlen(__imp->_M_names[__ix]) + 1];
303                 strcpy(__new, __imp->_M_names[__ix]);
304                 _M_names[__ix] = __new;
305               }
306           }
307       }
308   }
309
310   void
311   locale::_Impl::
312   _M_replace_category(const _Impl* __imp, const locale::id* const* __idpp)
313   {
314     for (; *__idpp; ++__idpp)
315       _M_replace_facet(__imp, *__idpp);
316   }
317   
318   void
319   locale::_Impl::
320   _M_replace_facet(const _Impl* __imp, const locale::id* __idp)
321   {
322     size_t __index = __idp->_M_id();
323     if ((__index > (__imp->_M_facets_size - 1)) || !__imp->_M_facets[__index])
324       __throw_runtime_error("locale::_Impl::_M_replace_facet");
325     _M_install_facet(__idp, __imp->_M_facets[__index]); 
326   }
327
328   void
329   locale::_Impl::
330   _M_install_facet(const locale::id* __idp, const facet* __fp)
331   {
332     if (__fp)
333       {
334         size_t __index = __idp->_M_id();
335
336         // Check size of facet vector to ensure adequate room.
337         if (__index > _M_facets_size - 1)
338           {
339             const facet** __old = _M_facets;
340             const facet** __new;
341             const size_t __new_size = __index + 4;
342             __new = new const facet*[__new_size]; 
343             for (size_t __i = 0; __i < _M_facets_size; ++__i)
344               __new[__i] = _M_facets[__i];
345             for (size_t __i2 = _M_facets_size; __i2 < __new_size; ++__i2)
346               __new[__i2] = 0;
347
348             _M_facets_size = __new_size;
349             _M_facets = __new;
350             delete [] __old;
351           }
352
353         __fp->_M_add_reference();
354         const facet*& __fpr = _M_facets[__index];
355         if (__fpr)
356           {
357             // Replacing an existing facet. Order matters.
358             __fpr->_M_remove_reference();
359             __fpr = __fp;
360           }
361         else
362           {
363             // Installing a newly created facet into an empty
364             // _M_facets container, say a newly-constructed,
365             // swanky-fresh _Impl.
366             _M_facets[__index] = __fp;
367           }
368       }
369   }
370 } // namespace std