Commit aa53f832 by Paolo Carlini Committed by Benjamin Kosnik

localefwd.h (class locale): Add static member _S_num_extra_categories...


2002-10-08  Paolo Carlini  <pcarlini@unitus.it>
	    Benjamin Kosnik  <bkoz@redhat.com>

	* include/bits/localefwd.h (class locale): Add static member
	_S_num_extra_categories, encoding the number of additional
	categories.
	Change _S_num_categories to _S_categories_size.
	(class locale::_Impl): Add _M_c_cats.
	(class locale::_Impl::_M_names): Change to array of chars.
	(class locale::_Impl::_M_check_same_name): Use
	_S_extra_categories_size, tweak.
	(locale::locale(const locale&, _Facet*)): Ditto.
    	* src/locale.cc (locale::locale(const char* )): Rewrite to deal
	with the environment in a POSIX-compliant way while being thread
	safe.
	(locale::name()): Update to output POSIX environment strings.
	* src/localename.cc
	(locale::_Impl::_Impl(const _Impl&, size_t): Use
	_S_categories_size_*, tweak.
	(locale::_Impl::_Impl(facet**, size_t, bool)): Ditto.
	(locale::_Impl::_Impl(const char*, size_t)): Name each category
	individually.
	(locale::_Impl::_M_replace_categories): Use strcpy.

	* include/bits/locale_facets.h (numpunct::_M_initialize_numpunct):
	Change default argument to NULL from _S_c_locale.
	(timepunct::_M_initialize_timepunct): Same.
	_S_c_locale cleanups.
	* src/codecvt.c: _S_c_locale simplification.
	* src/ctype.c: Same.
	* src/globals.cc: Add fake_name.
	* src/locale-inst.cc: Remove extra includes.
	* src/locale.cc: Remove extra includes.
	Add _S_extra_categories_size definition.
	Correct "C" initialization.
	(locale::facet::facet): Don't initialize _S_c_locale.
	(locale::facet::_M_remove_reference): Adjust.
	* src/localename: Use facet_vec, facet_name.
	(locale::_Impl::_Impl(facet** __f, size_t __refs, bool)): Set
	facet ref counts to one. Initialize _S_c_locale.
	(locale::_Impl::_M_install_facet(id*, facet*)): Adjust facet ref
	counts when installing unilaterally.

	* config/locale/generic/c_locale.cc: Add _S_categories definition.
	* config/locale/generic/c_locale.h: Add _GLIBCPP_NUM_CATEGORIES macro.
	* config/locale/generic/time_members.cc: _S_c_locale cleanup.

	* config/locale/gnu/c_locale.cc: Add _S_categories definition.
	(_S_destroy_c_locale): Move checks against _S_c_locale here.
	* config/locale/gnu/c_locale.h: Add _GLIBCPP_NUM_CATEGORIES macro.
	* config/locale/gnu/ctype_members.cc: Simplify _S_destroy_c_locale
	calls, _S_c_locale usage.
	* config/locale/gnu/monetary_members.cc: Same, tweaks.
	* config/locale/gnu/monetary_members.cc: Same.
	* config/locale/gnu/time_members.cc: Same.
	* config/os/gnu-linux/ctype_noninline.h: Use locale::classic().

	* docs/html/22_locale/locale.html: Add bits about global locales
	and "C" setlocale.

	* testsuite/22_locale/facet.cc (test02): Add.
	* testsuite/22_locale/static_members.cc (test02): Add.
	* testsuite/22_locale/ctor_copy_dtor.cc (test04): Add.

Co-Authored-By: Benjamin Kosnik <bkoz@redhat.com>

From-SVN: r57964
parent 131d2c16
2002-10-08 Paolo Carlini <pcarlini@unitus.it>
Benjamin Kosnik <bkoz@redhat.com>
* include/bits/localefwd.h (class locale): Add static member
_S_num_extra_categories, encoding the number of additional
categories.
Change _S_num_categories to _S_categories_size.
(class locale::_Impl): Add _M_c_cats.
(class locale::_Impl::_M_names): Change to array of chars.
(class locale::_Impl::_M_check_same_name): Use
_S_extra_categories_size, tweak.
(locale::locale(const locale&, _Facet*)): Ditto.
* src/locale.cc (locale::locale(const char* )): Rewrite to deal
with the environment in a POSIX-compliant way while being thread
safe.
(locale::name()): Update to output POSIX environment strings.
* src/localename.cc
(locale::_Impl::_Impl(const _Impl&, size_t): Use
_S_categories_size_*, tweak.
(locale::_Impl::_Impl(facet**, size_t, bool)): Ditto.
(locale::_Impl::_Impl(const char*, size_t)): Name each category
individually.
(locale::_Impl::_M_replace_categories): Use strcpy.
* include/bits/locale_facets.h (numpunct::_M_initialize_numpunct):
Change default argument to NULL from _S_c_locale.
(timepunct::_M_initialize_timepunct): Same.
_S_c_locale cleanups.
* src/codecvt.c: _S_c_locale simplification.
* src/ctype.c: Same.
* src/globals.cc: Add fake_name.
* src/locale-inst.cc: Remove extra includes.
* src/locale.cc: Remove extra includes.
Add _S_extra_categories_size definition.
Correct "C" initialization.
(locale::facet::facet): Don't initialize _S_c_locale.
(locale::facet::_M_remove_reference): Adjust.
* src/localename: Use facet_vec, facet_name.
(locale::_Impl::_Impl(facet** __f, size_t __refs, bool)): Set
facet ref counts to one. Initialize _S_c_locale.
(locale::_Impl::_M_install_facet(id*, facet*)): Adjust facet ref
counts when installing unilaterally.
* config/locale/generic/c_locale.cc: Add _S_categories definition.
* config/locale/generic/c_locale.h: Add _GLIBCPP_NUM_CATEGORIES macro.
* config/locale/generic/time_members.cc: _S_c_locale cleanup.
* config/locale/gnu/c_locale.cc: Add _S_categories definition.
(_S_destroy_c_locale): Move checks against _S_c_locale here.
* config/locale/gnu/c_locale.h: Add _GLIBCPP_NUM_CATEGORIES macro.
* config/locale/gnu/ctype_members.cc: Simplify _S_destroy_c_locale
calls, _S_c_locale usage.
* config/locale/gnu/monetary_members.cc: Same, tweaks.
* config/locale/gnu/monetary_members.cc: Same.
* config/locale/gnu/time_members.cc: Same.
* config/os/gnu-linux/ctype_noninline.h: Use locale::classic().
* docs/html/22_locale/locale.html: Add bits about global locales
and "C" setlocale.
* testsuite/22_locale/facet.cc (test02): Add.
* testsuite/22_locale/static_members.cc (test02): Add.
* testsuite/22_locale/ctor_copy_dtor.cc (test04): Add.
2002-10-07 Jonathan Wakely <jw@kayari.org> 2002-10-07 Jonathan Wakely <jw@kayari.org>
* docs/html/configopts.html, docs/html/documentation.html, * docs/html/configopts.html, docs/html/documentation.html,
......
...@@ -223,4 +223,15 @@ namespace std ...@@ -223,4 +223,15 @@ namespace std
__c_locale __c_locale
locale::facet::_S_clone_c_locale(__c_locale&) locale::facet::_S_clone_c_locale(__c_locale&)
{ return __c_locale(); } { return __c_locale(); }
const char* locale::_S_categories[_S_categories_size
+ _S_extra_categories_size] =
{
"LC_CTYPE",
"LC_NUMERIC",
"LC_COLLATE",
"LC_TIME",
"LC_MONETARY",
"LC_MESSAGES"
};
} // namespace std } // namespace std
...@@ -35,6 +35,8 @@ ...@@ -35,6 +35,8 @@
#include <clocale> #include <clocale>
#define _GLIBCPP_NUM_CATEGORIES 0
namespace std namespace std
{ {
typedef int* __c_locale; typedef int* __c_locale;
......
...@@ -40,10 +40,7 @@ namespace std ...@@ -40,10 +40,7 @@ namespace std
{ {
template<> template<>
__timepunct<char>::~__timepunct() __timepunct<char>::~__timepunct()
{ { _S_destroy_c_locale(_M_c_locale_timepunct); }
if (_M_c_locale_timepunct != _S_c_locale)
_S_destroy_c_locale(_M_c_locale_timepunct);
}
template<> template<>
void void
...@@ -123,10 +120,7 @@ namespace std ...@@ -123,10 +120,7 @@ namespace std
#ifdef _GLIBCPP_USE_WCHAR_T #ifdef _GLIBCPP_USE_WCHAR_T
template<> template<>
__timepunct<wchar_t>::~__timepunct() __timepunct<wchar_t>::~__timepunct()
{ { _S_destroy_c_locale(_M_c_locale_timepunct); }
if (_M_c_locale_timepunct != _S_c_locale)
_S_destroy_c_locale(_M_c_locale_timepunct);
}
template<> template<>
void void
......
...@@ -178,9 +178,29 @@ namespace std ...@@ -178,9 +178,29 @@ namespace std
void void
locale::facet::_S_destroy_c_locale(__c_locale& __cloc) locale::facet::_S_destroy_c_locale(__c_locale& __cloc)
{ __freelocale(__cloc); } {
if (_S_c_locale != __cloc)
__freelocale(__cloc);
}
__c_locale __c_locale
locale::facet::_S_clone_c_locale(__c_locale& __cloc) locale::facet::_S_clone_c_locale(__c_locale& __cloc)
{ return __duplocale(__cloc); } { return __duplocale(__cloc); }
const char* locale::_S_categories[_S_categories_size
+ _S_extra_categories_size] =
{
"LC_CTYPE",
"LC_NUMERIC",
"LC_COLLATE",
"LC_TIME",
"LC_MONETARY",
"LC_MESSAGES",
"LC_PAPER",
"LC_NAME",
"LC_ADDRESS",
"LC_TELEPHONE",
"LC_MEASUREMENT",
"LC_IDENTIFICATION"
};
} // namespace std } // namespace std
...@@ -40,6 +40,8 @@ ...@@ -40,6 +40,8 @@
#define _GLIBCPP_C_LOCALE_GNU 1 #define _GLIBCPP_C_LOCALE_GNU 1
#define _GLIBCPP_NUM_CATEGORIES 6
#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
namespace __gnu_cxx namespace __gnu_cxx
{ {
......
...@@ -44,8 +44,7 @@ namespace std ...@@ -44,8 +44,7 @@ namespace std
ctype_byname<char>::ctype_byname(const char* __s, size_t __refs) ctype_byname<char>::ctype_byname(const char* __s, size_t __refs)
: ctype<char>(0, false, __refs) : ctype<char>(0, false, __refs)
{ {
if (_M_c_locale_ctype != _S_c_locale) _S_destroy_c_locale(_M_c_locale_ctype);
_S_destroy_c_locale(_M_c_locale_ctype);
_S_create_c_locale(_M_c_locale_ctype, __s); _S_create_c_locale(_M_c_locale_ctype, __s);
_M_toupper = _M_c_locale_ctype->__ctype_toupper; _M_toupper = _M_c_locale_ctype->__ctype_toupper;
_M_tolower = _M_c_locale_ctype->__ctype_tolower; _M_tolower = _M_c_locale_ctype->__ctype_tolower;
......
...@@ -220,7 +220,7 @@ namespace std ...@@ -220,7 +220,7 @@ namespace std
moneypunct<char, true>::_M_initialize_moneypunct(__c_locale __cloc, moneypunct<char, true>::_M_initialize_moneypunct(__c_locale __cloc,
const char*) const char*)
{ {
if (__cloc == _S_c_locale) if (!__cloc)
{ {
// "C" locale // "C" locale
_M_decimal_point = '.'; _M_decimal_point = '.';
...@@ -265,7 +265,7 @@ namespace std ...@@ -265,7 +265,7 @@ namespace std
moneypunct<char, false>::_M_initialize_moneypunct(__c_locale __cloc, moneypunct<char, false>::_M_initialize_moneypunct(__c_locale __cloc,
const char*) const char*)
{ {
if (__cloc == _S_c_locale) if (!__cloc)
{ {
// "C" locale // "C" locale
_M_decimal_point = '.'; _M_decimal_point = '.';
...@@ -319,7 +319,7 @@ namespace std ...@@ -319,7 +319,7 @@ namespace std
moneypunct<wchar_t, true>::_M_initialize_moneypunct(__c_locale __cloc, moneypunct<wchar_t, true>::_M_initialize_moneypunct(__c_locale __cloc,
const char* __name) const char* __name)
{ {
if (__cloc == _S_c_locale) if (!__cloc)
{ {
// "C" locale // "C" locale
_M_decimal_point = L'.'; _M_decimal_point = L'.';
...@@ -348,14 +348,12 @@ namespace std ...@@ -348,14 +348,12 @@ namespace std
_M_thousands_sep = static_cast<wchar_t>(((union { const char *__s; unsigned int __w; }){ __s: __nl_langinfo_l(_NL_NUMERIC_THOUSANDS_SEP_WC, __cloc)}).__w); _M_thousands_sep = static_cast<wchar_t>(((union { const char *__s; unsigned int __w; }){ __s: __nl_langinfo_l(_NL_NUMERIC_THOUSANDS_SEP_WC, __cloc)}).__w);
_M_grouping = __nl_langinfo_l(GROUPING, __cloc); _M_grouping = __nl_langinfo_l(GROUPING, __cloc);
mbstate_t __state;
size_t __len;
const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
const char* __ccurr = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc); const char* __ccurr = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc);
// NB: Should swich to __cloc's ctype info first. mbstate_t __state;
__len = strlen(__cpossign); size_t __len = strlen(__cpossign);
if (__len) if (__len)
{ {
++__len; ++__len;
...@@ -418,7 +416,7 @@ namespace std ...@@ -418,7 +416,7 @@ namespace std
moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc, moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc,
const char* __name) const char* __name)
{ {
if (__cloc == _S_c_locale) if (!__cloc)
{ {
// "C" locale // "C" locale
_M_decimal_point = L'.'; _M_decimal_point = L'.';
...@@ -446,13 +444,12 @@ namespace std ...@@ -446,13 +444,12 @@ namespace std
_M_thousands_sep = static_cast<wchar_t>(((union { const char *__s; unsigned int __w; }){ __s: __nl_langinfo_l(_NL_NUMERIC_THOUSANDS_SEP_WC, __cloc)}).__w); _M_thousands_sep = static_cast<wchar_t>(((union { const char *__s; unsigned int __w; }){ __s: __nl_langinfo_l(_NL_NUMERIC_THOUSANDS_SEP_WC, __cloc)}).__w);
_M_grouping = __nl_langinfo_l(GROUPING, __cloc); _M_grouping = __nl_langinfo_l(GROUPING, __cloc);
mbstate_t __state;
size_t __len;
const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
const char* __ccurr = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc); const char* __ccurr = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc);
// NB: Should swich to __cloc's ctype info first. mbstate_t __state;
size_t __len;
__len = strlen(__cpossign); __len = strlen(__cpossign);
if (__len) if (__len)
{ {
......
...@@ -42,7 +42,7 @@ namespace std ...@@ -42,7 +42,7 @@ namespace std
void void
numpunct<char>::_M_initialize_numpunct(__c_locale __cloc) numpunct<char>::_M_initialize_numpunct(__c_locale __cloc)
{ {
if (__cloc == _S_c_locale) if (!__cloc)
{ {
// "C" locale // "C" locale
_M_decimal_point = '.'; _M_decimal_point = '.';
...@@ -76,7 +76,7 @@ namespace std ...@@ -76,7 +76,7 @@ namespace std
void void
numpunct<wchar_t>::_M_initialize_numpunct(__c_locale __cloc) numpunct<wchar_t>::_M_initialize_numpunct(__c_locale __cloc)
{ {
if (__cloc == _S_c_locale) if (!__cloc)
{ {
// "C" locale // "C" locale
_M_decimal_point = L'.'; _M_decimal_point = L'.';
......
...@@ -41,10 +41,7 @@ namespace std ...@@ -41,10 +41,7 @@ namespace std
{ {
template<> template<>
__timepunct<char>::~__timepunct() __timepunct<char>::~__timepunct()
{ { _S_destroy_c_locale(_M_c_locale_timepunct); }
if (_M_c_locale_timepunct != _S_c_locale)
_S_destroy_c_locale(_M_c_locale_timepunct);
}
template<> template<>
void void
...@@ -67,11 +64,10 @@ namespace std ...@@ -67,11 +64,10 @@ namespace std
void void
__timepunct<char>::_M_initialize_timepunct(__c_locale __cloc) __timepunct<char>::_M_initialize_timepunct(__c_locale __cloc)
{ {
if (__cloc == _S_c_locale) if (!__cloc)
{ {
// "C" locale // "C" locale
_M_c_locale_timepunct = _S_c_locale;
_M_c_locale_timepunct = _S_c_locale;
_M_date_format = "%m/%d/%y"; _M_date_format = "%m/%d/%y";
_M_date_era_format = "%m/%d/%y"; _M_date_era_format = "%m/%d/%y";
...@@ -194,10 +190,7 @@ namespace std ...@@ -194,10 +190,7 @@ namespace std
#ifdef _GLIBCPP_USE_WCHAR_T #ifdef _GLIBCPP_USE_WCHAR_T
template<> template<>
__timepunct<wchar_t>::~__timepunct() __timepunct<wchar_t>::~__timepunct()
{ { _S_destroy_c_locale(_M_c_locale_timepunct); }
if (_M_c_locale_timepunct != _S_c_locale)
_S_destroy_c_locale(_M_c_locale_timepunct);
}
template<> template<>
void void
...@@ -220,11 +213,10 @@ namespace std ...@@ -220,11 +213,10 @@ namespace std
void void
__timepunct<wchar_t>::_M_initialize_timepunct(__c_locale __cloc) __timepunct<wchar_t>::_M_initialize_timepunct(__c_locale __cloc)
{ {
if (__cloc == _S_c_locale) if (!__cloc)
{ {
// "C" locale // "C" locale
_M_c_locale_timepunct = _S_c_locale;
_M_c_locale_timepunct = _S_c_locale;
_M_date_format = L"%m/%d/%y"; _M_date_format = L"%m/%d/%y";
_M_date_era_format = L"%m/%d/%y"; _M_date_era_format = L"%m/%d/%y";
......
...@@ -38,8 +38,7 @@ ...@@ -38,8 +38,7 @@
const ctype_base::mask* const ctype_base::mask*
ctype<char>::classic_table() throw() ctype<char>::classic_table() throw()
{ {
if (!_S_c_locale) locale::classic();
_S_create_c_locale(_S_c_locale, "C");
return _S_c_locale->__ctype_b; return _S_c_locale->__ctype_b;
} }
#else #else
...@@ -96,7 +95,7 @@ ...@@ -96,7 +95,7 @@
ctype<char>::ctype(const mask* __table, bool __del, size_t __refs) : ctype<char>::ctype(const mask* __table, bool __del, size_t __refs) :
__ctype_abstract_base<char>(__refs), _M_del(__table != 0 && __del) __ctype_abstract_base<char>(__refs), _M_del(__table != 0 && __del)
{ {
_M_c_locale_ctype = _S_c_locale; _M_c_locale_ctype = _S_c_locale;
_M_toupper = _M_c_locale_ctype->__ctype_toupper; _M_toupper = _M_c_locale_ctype->__ctype_toupper;
_M_tolower = _M_c_locale_ctype->__ctype_tolower; _M_tolower = _M_c_locale_ctype->__ctype_tolower;
_M_table = __table ? __table : _M_c_locale_ctype->__ctype_b; _M_table = __table ? __table : _M_c_locale_ctype->__ctype_b;
......
...@@ -68,14 +68,36 @@ public: ...@@ -68,14 +68,36 @@ public:
The only other thing of interest in this class is the memory The only other thing of interest in this class is the memory
management of facets. Each constructor of a facet class takes a management of facets. Each constructor of a facet class takes a
std::size_t __refs argument: if __refs == 0, the facet is deleted when std::size_t __refs argument: if __refs == 0, the facet is deleted when
no longer used. if __refs == 1, the facet is not destroyed, even when the locale containing it is destroyed. If __refs == 1, the facet is
it is no longer reference. not destroyed, even when it is no longer referenced.
class id class id
Provides an index for looking up specific facets. Provides an index for looking up specific facets.
class _Impl class _Impl
The internal representation of the std::locale object.
<h2>
5. Relationship to traditional "C" locales.
</h2>
From Josuttis, p. 697-698, which says, that "there is only *one*
relation (of the C++ locale mechanism) to the C locale mechanism: the
global C locale is modified if a named C++ locale object is set as the
global locale" (emphasis Paolo), that is:
std::locale::global(std::locale(""));
affects the C functions as if the following call was made:
std::setlocale(LC_ALL, "");
On the other hand, there is *no* viceversa, that is, calling setlocale
has *no* whatsoever on the C++ locale mechanism, in particular on the
working of locale(""), which constructs the locale object from the
environment of the running program, that is, in practice, the set of
LC_ALL, LANG, etc. variable of the shell.
<h2> <h2>
5. Examples 5. Examples
...@@ -87,8 +109,7 @@ class _Impl ...@@ -87,8 +109,7 @@ class _Impl
More information can be found in the following testcases: More information can be found in the following testcases:
<ul> <ul>
<li> testsuite/22_locale/ctype_char_members.cc </li> <li> testsuite/22_locale/all </li>
<li> testsuite/22_locale/ctype_wchar_t_members.cc </li>
</ul> </ul>
<h2> <h2>
......
...@@ -525,7 +525,7 @@ namespace std ...@@ -525,7 +525,7 @@ namespace std
// For use at construction time only. // For use at construction time only.
void void
_M_initialize_numpunct(__c_locale __cloc = _S_c_locale); _M_initialize_numpunct(__c_locale __cloc = NULL);
}; };
template<typename _CharT> template<typename _CharT>
...@@ -875,10 +875,7 @@ namespace std ...@@ -875,10 +875,7 @@ namespace std
protected: protected:
virtual virtual
~collate() ~collate()
{ { _S_destroy_c_locale(_M_c_locale_collate); }
if (_M_c_locale_collate != _S_c_locale)
_S_destroy_c_locale(_M_c_locale_collate);
}
virtual int virtual int
do_compare(const _CharT* __lo1, const _CharT* __hi1, do_compare(const _CharT* __lo1, const _CharT* __hi1,
...@@ -924,8 +921,7 @@ namespace std ...@@ -924,8 +921,7 @@ namespace std
collate_byname(const char* __s, size_t __refs = 0) collate_byname(const char* __s, size_t __refs = 0)
: collate<_CharT>(__refs) : collate<_CharT>(__refs)
{ {
if (_M_c_locale_collate != _S_c_locale) _S_destroy_c_locale(_M_c_locale_collate);
_S_destroy_c_locale(_M_c_locale_collate);
_S_create_c_locale(_M_c_locale_collate, __s); _S_create_c_locale(_M_c_locale_collate, __s);
} }
...@@ -1123,7 +1119,7 @@ namespace std ...@@ -1123,7 +1119,7 @@ namespace std
// For use at construction time only. // For use at construction time only.
void void
_M_initialize_timepunct(__c_locale __cloc = _S_c_locale); _M_initialize_timepunct(__c_locale __cloc = NULL);
}; };
template<typename _CharT> template<typename _CharT>
...@@ -1459,7 +1455,7 @@ namespace std ...@@ -1459,7 +1455,7 @@ namespace std
// For use at construction time only. // For use at construction time only.
void void
_M_initialize_moneypunct(__c_locale __cloc = _S_c_locale, _M_initialize_moneypunct(__c_locale __cloc = NULL,
const char* __name = NULL); const char* __name = NULL);
}; };
...@@ -1667,10 +1663,7 @@ namespace std ...@@ -1667,10 +1663,7 @@ namespace std
protected: protected:
virtual virtual
~messages() ~messages()
{ { _S_destroy_c_locale(_M_c_locale_messages); }
if (_M_c_locale_messages != _S_c_locale)
_S_destroy_c_locale(_M_c_locale_messages);
}
virtual catalog virtual catalog
do_open(const basic_string<char>&, const locale&) const; do_open(const basic_string<char>&, const locale&) const;
...@@ -1759,8 +1752,7 @@ namespace std ...@@ -1759,8 +1752,7 @@ namespace std
: messages<_CharT>(__refs) : messages<_CharT>(__refs)
{ {
_M_name_messages = __s; _M_name_messages = __s;
if (_M_c_locale_messages != _S_c_locale) _S_destroy_c_locale(_M_c_locale_messages);
_S_destroy_c_locale(_M_c_locale_messages);
_S_create_c_locale(_M_c_locale_messages, __s); _S_create_c_locale(_M_c_locale_messages, __s);
} }
......
...@@ -207,8 +207,8 @@ namespace std ...@@ -207,8 +207,8 @@ namespace std
static const category time = 1L << 3; static const category time = 1L << 3;
static const category monetary = 1L << 4; static const category monetary = 1L << 4;
static const category messages = 1L << 5; static const category messages = 1L << 5;
static const category all = (collate | ctype | monetary | static const category all = (ctype | numeric | collate |
numeric | time | messages); time | monetary | messages);
// Construct/copy/destroy: // Construct/copy/destroy:
locale() throw(); locale() throw();
...@@ -267,7 +267,26 @@ namespace std ...@@ -267,7 +267,26 @@ namespace std
// Current global reference locale // Current global reference locale
static _Impl* _S_global; static _Impl* _S_global;
static const size_t _S_num_categories = 6; // Number of standard categories. For C++, these categories are
// collate, ctype, monetary, numeric, time, and messages. These
// directly correspond to ISO C99 macros LC_COLLATE, LC_CTYPE,
// LC_MONETARY, LC_NUMERIC, and LC_TIME. In addition, POSIX (IEEE
// 1003.1-2001) specifies LC_MESSAGES.
static const size_t _S_categories_size = 6;
// In addition to the standard categories, the underlying
// operating system is allowed to define extra LC_*
// macros. For GNU systems, the following are also valid:
// LC_PAPER, LC_NAME, LC_ADDRESS, LC_TELEPHONE, LC_MEASUREMENT,
// and LC_IDENTIFICATION.
static const size_t _S_extra_categories_size = _GLIBCPP_NUM_CATEGORIES;
// Names of underlying locale categories.
// NB: locale::global() has to know how to modify all the
// underlying categories, not just the ones required by the C++
// standard.
static const char* _S_categories[_S_categories_size
+ _S_extra_categories_size];
explicit explicit
locale(_Impl*) throw(); locale(_Impl*) throw();
...@@ -308,7 +327,9 @@ namespace std ...@@ -308,7 +327,9 @@ namespace std
_Atomic_word _M_references; _Atomic_word _M_references;
facet** _M_facets; facet** _M_facets;
size_t _M_facets_size; size_t _M_facets_size;
const char* _M_names[_S_num_categories];
char* _M_names[_S_categories_size
+ _S_extra_categories_size];
static const locale::id* const _S_id_ctype[]; static const locale::id* const _S_id_ctype[];
static const locale::id* const _S_id_numeric[]; static const locale::id* const _S_id_numeric[];
static const locale::id* const _S_id_collate[]; static const locale::id* const _S_id_collate[];
...@@ -348,8 +369,10 @@ namespace std ...@@ -348,8 +369,10 @@ namespace std
_M_check_same_name() _M_check_same_name()
{ {
bool __ret = true; bool __ret = true;
for (size_t i = 0; __ret && i < _S_num_categories - 1; ++i) for (size_t __i = 0;
__ret &= (strcmp(_M_names[i], _M_names[i + 1]) == 0); __ret && __i < _S_categories_size + _S_extra_categories_size - 1;
++__i)
__ret &= (strcmp(_M_names[__i], _M_names[__i + 1]) == 0);
return __ret; return __ret;
} }
...@@ -376,8 +399,14 @@ namespace std ...@@ -376,8 +399,14 @@ namespace std
{ {
_M_impl = new _Impl(*__other._M_impl, 1); _M_impl = new _Impl(*__other._M_impl, 1);
_M_impl->_M_install_facet(&_Facet::id, __f); _M_impl->_M_install_facet(&_Facet::id, __f);
for (size_t __i = 0; __i < _S_num_categories; ++__i) for (size_t __i = 0;
_M_impl->_M_names[__i] = "*"; __i < _S_categories_size + _S_extra_categories_size; ++__i)
{
delete [] _M_impl->_M_names[__i];
char* __new = new char[2];
strcpy(__new, "*");
_M_impl->_M_names[__i] = __new;
}
} }
// 22.1.1.1.2 Class locale::facet // 22.1.1.1.2 Class locale::facet
......
...@@ -55,10 +55,7 @@ namespace std ...@@ -55,10 +55,7 @@ namespace std
codecvt<char, char, mbstate_t>:: codecvt<char, char, mbstate_t>::
~codecvt() ~codecvt()
{ { _S_destroy_c_locale(_M_c_locale_codecvt); }
if (_M_c_locale_codecvt != _S_c_locale)
_S_destroy_c_locale(_M_c_locale_codecvt);
}
codecvt_base::result codecvt_base::result
codecvt<char, char, mbstate_t>:: codecvt<char, char, mbstate_t>::
...@@ -123,7 +120,7 @@ namespace std ...@@ -123,7 +120,7 @@ namespace std
codecvt<wchar_t, char, mbstate_t>:: codecvt<wchar_t, char, mbstate_t>::
codecvt(size_t __refs) codecvt(size_t __refs)
: __codecvt_abstract_base<wchar_t, char, mbstate_t>(__refs) : __codecvt_abstract_base<wchar_t, char, mbstate_t>(__refs)
{ _M_c_locale_codecvt = _S_c_locale; } { _M_c_locale_codecvt = _S_c_locale; }
codecvt<wchar_t, char, mbstate_t>:: codecvt<wchar_t, char, mbstate_t>::
codecvt(__c_locale __cloc, size_t __refs) codecvt(__c_locale __cloc, size_t __refs)
...@@ -132,10 +129,7 @@ namespace std ...@@ -132,10 +129,7 @@ namespace std
codecvt<wchar_t, char, mbstate_t>:: codecvt<wchar_t, char, mbstate_t>::
~codecvt() ~codecvt()
{ { _S_destroy_c_locale(_M_c_locale_codecvt); }
if (_M_c_locale_codecvt != _S_c_locale)
_S_destroy_c_locale(_M_c_locale_codecvt);
}
codecvt_base::result codecvt_base::result
codecvt<wchar_t, char, mbstate_t>:: codecvt<wchar_t, char, mbstate_t>::
......
...@@ -79,8 +79,7 @@ namespace std ...@@ -79,8 +79,7 @@ namespace std
ctype<char>::~ctype() ctype<char>::~ctype()
{ {
if (_M_c_locale_ctype != _S_c_locale) _S_destroy_c_locale(_M_c_locale_ctype);
_S_destroy_c_locale(_M_c_locale_ctype);
if (_M_del) if (_M_del)
delete[] this->table(); delete[] this->table();
} }
...@@ -135,17 +134,13 @@ namespace std ...@@ -135,17 +134,13 @@ namespace std
{ _M_c_locale_ctype = _S_clone_c_locale(__cloc); } { _M_c_locale_ctype = _S_clone_c_locale(__cloc); }
ctype<wchar_t>::~ctype() ctype<wchar_t>::~ctype()
{ { _S_destroy_c_locale(_M_c_locale_ctype); }
if (_M_c_locale_ctype != _S_c_locale)
_S_destroy_c_locale(_M_c_locale_ctype);
}
template<> template<>
ctype_byname<wchar_t>::ctype_byname(const char* __s, size_t __refs) ctype_byname<wchar_t>::ctype_byname(const char* __s, size_t __refs)
: ctype<wchar_t>(__refs) : ctype<wchar_t>(__refs)
{ {
if (_M_c_locale_ctype != _S_c_locale) _S_destroy_c_locale(_M_c_locale_ctype);
_S_destroy_c_locale(_M_c_locale_ctype);
_S_create_c_locale(_M_c_locale_ctype, __s); _S_create_c_locale(_M_c_locale_ctype, __s);
} }
#endif #endif
......
...@@ -59,6 +59,10 @@ namespace std ...@@ -59,6 +59,10 @@ namespace std
__attribute__ ((aligned(__alignof__(locale::facet*)))); __attribute__ ((aligned(__alignof__(locale::facet*))));
fake_facet_vec facet_vec[_GLIBCPP_NUM_FACETS]; fake_facet_vec facet_vec[_GLIBCPP_NUM_FACETS];
typedef char fake_facet_name[sizeof(char*)]
__attribute__ ((aligned(__alignof__(char*))));
fake_facet_name facet_name[6 + _GLIBCPP_NUM_CATEGORIES];
typedef char fake_ctype_c[sizeof(std::ctype<char>)] typedef char fake_ctype_c[sizeof(std::ctype<char>)]
__attribute__ ((aligned(__alignof__(std::ctype<char>)))); __attribute__ ((aligned(__alignof__(std::ctype<char>))));
fake_ctype_c ctype_c; fake_ctype_c ctype_c;
...@@ -200,7 +204,6 @@ namespace std ...@@ -200,7 +204,6 @@ namespace std
fake_wfilebuf buf_wcerr; fake_wfilebuf buf_wcerr;
#endif #endif
// Globals for once-only runtime initialization of mutex objects. This // Globals for once-only runtime initialization of mutex objects. This
// allows static initialization of these objects on systems that need a // allows static initialization of these objects on systems that need a
// function call to initialize a mutex. For example, see stl_threads.h. // function call to initialize a mutex. For example, see stl_threads.h.
......
...@@ -35,11 +35,7 @@ ...@@ -35,11 +35,7 @@
#include <clocale> #include <clocale>
#include <cstring> #include <cstring>
#include <cassert> #include <cassert>
#include <limits>
#include <exception>
#include <locale> #include <locale>
#include <istream>
#include <ostream>
namespace std namespace std
{ {
......
...@@ -31,11 +31,7 @@ ...@@ -31,11 +31,7 @@
#include <cassert> #include <cassert>
#include <cctype> #include <cctype>
#include <cwctype> // For towupper, etc. #include <cwctype> // For towupper, etc.
#include <limits>
#include <exception>
#include <locale> #include <locale>
#include <istream>
#include <ostream>
#include <bits/atomicity.h> #include <bits/atomicity.h>
namespace std namespace std
...@@ -43,7 +39,6 @@ namespace std ...@@ -43,7 +39,6 @@ namespace std
// Defined in globals.cc. // Defined in globals.cc.
extern locale c_locale; extern locale c_locale;
extern locale::_Impl c_locale_impl; extern locale::_Impl c_locale_impl;
extern locale::facet** facet_vec;
// Definitions for static const data members of locale. // Definitions for static const data members of locale.
const locale::category locale::none; const locale::category locale::none;
...@@ -57,7 +52,8 @@ namespace std ...@@ -57,7 +52,8 @@ namespace std
locale::_Impl* locale::_S_classic; locale::_Impl* locale::_S_classic;
locale::_Impl* locale::_S_global; locale::_Impl* locale::_S_global;
const size_t locale::_S_num_categories; const size_t locale::_S_categories_size;
const size_t locale::_S_extra_categories_size;
// Definitions for static const data members of locale::id // Definitions for static const data members of locale::id
_Atomic_word locale::id::_S_highwater; // init'd to 0 by linker _Atomic_word locale::id::_S_highwater; // init'd to 0 by linker
...@@ -146,8 +142,8 @@ namespace std ...@@ -146,8 +142,8 @@ namespace std
locale::_Impl::_S_id_ctype, locale::_Impl::_S_id_ctype,
locale::_Impl::_S_id_numeric, locale::_Impl::_S_id_numeric,
locale::_Impl::_S_id_collate, locale::_Impl::_S_id_collate,
locale::_Impl::_S_id_monetary,
locale::_Impl::_S_id_time, locale::_Impl::_S_id_time,
locale::_Impl::_S_id_monetary,
locale::_Impl::_S_id_messages, locale::_Impl::_S_id_messages,
0 0
}; };
...@@ -192,18 +188,110 @@ namespace std ...@@ -192,18 +188,110 @@ namespace std
_S_initialize(); _S_initialize();
if (strcmp(__s, "C") == 0 || strcmp(__s, "POSIX") == 0) if (strcmp(__s, "C") == 0 || strcmp(__s, "POSIX") == 0)
(_M_impl = _S_classic)->_M_add_reference(); (_M_impl = _S_classic)->_M_add_reference();
else if (strcmp(__s, "") == 0) else if (strcmp(__s, "") != 0)
_M_impl = new _Impl(__s, 1);
else
{ {
// Get it from the environment.
char* __env = getenv("LC_ALL"); char* __env = getenv("LC_ALL");
if (__env) // If LC_ALL is set we are done.
_M_impl = new _Impl(__env, 1); if (__env && strcmp(__env, "") != 0)
else if ((__env = getenv("LANG"))) {
_M_impl = new _Impl(__env, 1); if (strcmp(__env, "C") == 0 || strcmp(__env, "POSIX") == 0)
(_M_impl = _S_classic)->_M_add_reference();
else
_M_impl = new _Impl(__env, 1);
}
else else
(_M_impl = _S_classic)->_M_add_reference(); {
char* __res;
// LANG may set a default different from "C".
char* __env = getenv("LANG");
if (!__env || strcmp(__env, "") == 0 || strcmp(__env, "C") == 0
|| strcmp(__env, "POSIX") == 0)
__res = strdup("C");
else
__res = strdup(__env);
// Scan the categories looking for the first one
// different from LANG.
size_t __i = 0;
if (strcmp(__res, "C") == 0)
for (__i = 0;
__i < _S_categories_size + _S_extra_categories_size;
++__i)
{
__env = getenv(_S_categories[__i]);
if (__env && strcmp(__env, "") != 0
&& strcmp(__env, "C") != 0
&& strcmp(__env, "POSIX") != 0)
break;
}
else
for (__i = 0;
__i < _S_categories_size + _S_extra_categories_size;
++__i)
{
__env = getenv(_S_categories[__i]);
if (__env && strcmp(__env, "") != 0
&& strcmp(__env, __res) != 0)
break;
}
// If one is found, build the complete string of
// the form LC_CTYPE=xxx;LC_NUMERIC=yyy; and so on...
if (__i < _S_categories_size + _S_extra_categories_size)
{
string __str;
for (size_t __j = 0; __j < __i; ++__j)
{
__str += _S_categories[__j];
__str += "=";
__str += __res;
__str += ";";
}
__str += _S_categories[__i];
__str += "=";
__str += __env;
__str += ";";
__i++;
for (; __i < _S_categories_size
+ _S_extra_categories_size; ++__i)
{
__env = getenv(_S_categories[__i]);
if (!__env || strcmp(__env, "") == 0)
{
__str += _S_categories[__i];
__str += '=';
__str += __res;
__str += ';';
}
else if (strcmp(__env, "C") == 0
|| strcmp(__env, "POSIX") == 0)
{
__str += _S_categories[__i];
__str += "=C;";
}
else
{
__str += _S_categories[__i];
__str += "=";
__str += __env;
__str += ";";
}
}
__str.erase(__str.end() - 1);
_M_impl = new _Impl(__str.c_str(), 1);
}
// ... otherwise either an additional instance of
// the "C" locale or LANG.
else if (strcmp(__res, "C") == 0)
(_M_impl = _S_classic)->_M_add_reference();
else
_M_impl = new _Impl(__res, 1);
free(__res);
}
} }
else
_M_impl = new _Impl(__s, 1);
} }
else else
__throw_runtime_error("attempt to create locale from NULL name"); __throw_runtime_error("attempt to create locale from NULL name");
...@@ -261,20 +349,22 @@ namespace std ...@@ -261,20 +349,22 @@ namespace std
string string
locale::name() const locale::name() const
{ {
// Need some kind of separator character. This one was pretty much
// arbitrarily chosen as to not conflict with glibc locales: the
// exact formatting is not set in stone.
const char __separator = '|';
string __ret; string __ret;
if (_M_impl->_M_check_same_name()) if (_M_impl->_M_check_same_name())
__ret = _M_impl->_M_names[0]; __ret = _M_impl->_M_names[0];
else else
{ {
for (size_t i = 0; i < _S_num_categories; ++i) __ret += _S_categories[0];
__ret += "=";
__ret += _M_impl->_M_names[0];
for (size_t __i = 1;
__i < _S_categories_size + _S_extra_categories_size;
++__i)
{ {
__ret += __separator; __ret += ";";
__ret += _M_impl->_M_names[i]; __ret += _S_categories[__i];
__ret += "=";
__ret += _M_impl->_M_names[__i];
} }
} }
return __ret; return __ret;
...@@ -292,11 +382,7 @@ namespace std ...@@ -292,11 +382,7 @@ namespace std
{ {
// 26 Standard facets, 2 references. // 26 Standard facets, 2 references.
// One reference for _M_classic, one for _M_global // One reference for _M_classic, one for _M_global
facet** f = new(&facet_vec) facet*[_GLIBCPP_NUM_FACETS]; _S_classic = new (&c_locale_impl) _Impl(0, 2, true);
for (size_t __i = 0; __i < _GLIBCPP_NUM_FACETS; ++__i)
f[__i] = 0;
_S_classic = new (&c_locale_impl) _Impl(f, 2, true);
_S_global = _S_classic; _S_global = _S_classic;
new (&c_locale) locale(_S_classic); new (&c_locale) locale(_S_classic);
} }
...@@ -361,11 +447,8 @@ namespace std ...@@ -361,11 +447,8 @@ namespace std
~facet() { } ~facet() { }
locale::facet:: locale::facet::
facet(size_t __refs) throw() : _M_references(__refs) facet(size_t __refs) throw() : _M_references(__refs ? 1 : 0)
{ { }
if (!_S_c_locale)
_S_create_c_locale(_S_c_locale, "C");
}
void void
locale::facet:: locale::facet::
...@@ -376,7 +459,7 @@ namespace std ...@@ -376,7 +459,7 @@ namespace std
locale::facet:: locale::facet::
_M_remove_reference() throw() _M_remove_reference() throw()
{ {
if (__exchange_and_add(&_M_references, -1) == 0) if (__exchange_and_add(&_M_references, -1) == 1)
{ {
try try
{ delete this; } { delete this; }
......
...@@ -33,6 +33,9 @@ ...@@ -33,6 +33,9 @@
namespace std namespace std
{ {
// Defined in globals.cc. // Defined in globals.cc.
extern locale::facet** facet_vec;
extern char* facet_name[6 + _GLIBCPP_NUM_CATEGORIES];
extern std::ctype<char> ctype_c; extern std::ctype<char> ctype_c;
extern std::collate<char> collate_c; extern std::collate<char> collate_c;
extern numpunct<char> numpunct_c; extern numpunct<char> numpunct_c;
...@@ -71,6 +74,10 @@ namespace std ...@@ -71,6 +74,10 @@ namespace std
if (_M_facets[__i]) if (_M_facets[__i])
_M_facets[__i]->_M_remove_reference(); _M_facets[__i]->_M_remove_reference();
delete [] _M_facets; delete [] _M_facets;
for (size_t __i = 0;
__i < _S_categories_size + _S_extra_categories_size; ++__i)
delete [] _M_names[__i];
} }
// Clone existing _Impl object. // Clone existing _Impl object.
...@@ -95,14 +102,19 @@ namespace std ...@@ -95,14 +102,19 @@ namespace std
if (_M_facets[__i]) if (_M_facets[__i])
_M_facets[__i]->_M_add_reference(); _M_facets[__i]->_M_add_reference();
} }
for (size_t __i = 0; __i < _S_num_categories; ++__i) for (size_t __i = 0;
_M_names[__i] = __imp._M_names[__i]; __i < _S_categories_size + _S_extra_categories_size; ++__i)
{
char* __new = new char[strlen(__imp._M_names[__i]) + 1];
strcpy(__new, __imp._M_names[__i]);
_M_names[__i] = __new;
}
} }
// Construct named _Impl. // Construct named _Impl.
locale::_Impl:: locale::_Impl::
_Impl(const char* __s, size_t __refs) _Impl(const char* __s, size_t __refs)
: _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS) // XXX : _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS)
{ {
// Initialize the underlying locale model, which also checks // Initialize the underlying locale model, which also checks
// to see if the given name is valid. // to see if the given name is valid.
...@@ -122,11 +134,40 @@ namespace std ...@@ -122,11 +134,40 @@ namespace std
} }
// Name all the categories. // Name all the categories.
for (size_t i = 0; i < _S_num_categories; ++i) if (!strchr(__s, ';'))
_M_names[i] = __s; {
size_t __len = strlen(__s) + 1;
for (size_t __i = 0;
__i < _S_categories_size + _S_extra_categories_size; ++__i)
{
_M_names[__i] = new char[__len];
strcpy(_M_names[__i], __s);
}
}
else
{
char* __tmp = strdup(__s);
__tmp[strlen(__tmp)] = ';';
strtok(__tmp, "=;");
for (size_t __i = 0;
__i < _S_categories_size + _S_extra_categories_size - 1; ++__i)
{
char* __src = strtok(NULL, "=;");
char* __new = new char[strlen(__src) + 1];
strcpy(__new, __src);
_M_names[__i] = __new;
strtok(NULL, "=;");
}
char* __src = strtok(NULL, "=;");
char* __new = new char[strlen(__src) + 1];
strcpy(__new, __src);
_M_names[_S_categories_size + _S_extra_categories_size - 1] = __new;
// Construct all standard facets and add them to _M_facets. free(__tmp);
_M_init_facet(new std::ctype<char>(__cloc)); }
// Construct all standard facets and add them to _M_facets.
_M_init_facet(new std::ctype<char>(__cloc, 0, false));
_M_init_facet(new codecvt<char, char, mbstate_t>(__cloc)); _M_init_facet(new codecvt<char, char, mbstate_t>(__cloc));
_M_init_facet(new numpunct<char>(__cloc)); _M_init_facet(new numpunct<char>(__cloc));
_M_init_facet(new num_get<char>); _M_init_facet(new num_get<char>);
...@@ -162,47 +203,61 @@ namespace std ...@@ -162,47 +203,61 @@ namespace std
// Construct "C" _Impl. // Construct "C" _Impl.
locale::_Impl:: locale::_Impl::
_Impl(facet** __f, size_t __refs, bool) _Impl(facet**, size_t __refs, bool)
: _M_references(__refs), _M_facets(__f), _M_facets_size(_GLIBCPP_NUM_FACETS) : _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS)
{ {
// Initialize the underlying locale model.
locale::facet::_S_create_c_locale(locale::facet::_S_c_locale, "C");
_M_facets = new(&facet_vec) facet*[_M_facets_size];
for (size_t __i = 0; __i < _M_facets_size; ++__i)
_M_facets[__i] = 0;
// Name all the categories. // Name all the categories.
for (size_t i = 0; i < _S_num_categories; ++i) for (size_t __i = 0;
_M_names[i] = "C"; __i < _S_categories_size + _S_extra_categories_size; ++__i)
{
_M_names[__i] = new (&facet_name[__i]) char[2];
strcpy(_M_names[__i], "C");
}
// This is needed as presently the C++ version of "C" locales // This is needed as presently the C++ version of "C" locales
// != data in the underlying locale model for __timepunct, // != data in the underlying locale model for __timepunct,
// numpunct, and moneypunct. Also, the "C" locales must be // numpunct, and moneypunct. Also, the "C" locales must be
// constructed in a way such that they are pre-allocated. // constructed in a way such that they are pre-allocated.
_M_init_facet(new (&ctype_c) std::ctype<char>); // NB: Set locale::facets(ref) count to one so that each individual
_M_init_facet(new (&codecvt_c) codecvt<char, char, mbstate_t>); // facet is not destroyed when the locale (and thus locale::_Impl) is
_M_init_facet(new (&numpunct_c) numpunct<char>); // destroyed.
_M_init_facet(new (&num_get_c) num_get<char>); _M_init_facet(new (&ctype_c) std::ctype<char>(0, false, 1));
_M_init_facet(new (&num_put_c) num_put<char>); _M_init_facet(new (&codecvt_c) codecvt<char, char, mbstate_t>(1));
_M_init_facet(new (&collate_c) std::collate<char>); _M_init_facet(new (&numpunct_c) numpunct<char>(1));
_M_init_facet(new (&moneypunct_fc) moneypunct<char, false>); _M_init_facet(new (&num_get_c) num_get<char>(1));
_M_init_facet(new (&moneypunct_tc) moneypunct<char, true>); _M_init_facet(new (&num_put_c) num_put<char>(1));
_M_init_facet(new (&money_get_c) money_get<char>); _M_init_facet(new (&collate_c) std::collate<char>(1));
_M_init_facet(new (&money_put_c) money_put<char>); _M_init_facet(new (&moneypunct_fc) moneypunct<char, false>(1));
_M_init_facet(new (&timepunct_c) __timepunct<char>); _M_init_facet(new (&moneypunct_tc) moneypunct<char, true>(1));
_M_init_facet(new (&time_get_c) time_get<char>); _M_init_facet(new (&money_get_c) money_get<char>(1));
_M_init_facet(new (&time_put_c) time_put<char>); _M_init_facet(new (&money_put_c) money_put<char>(1));
_M_init_facet(new (&messages_c) std::messages<char>); _M_init_facet(new (&timepunct_c) __timepunct<char>(1));
_M_init_facet(new (&time_get_c) time_get<char>(1));
_M_init_facet(new (&time_put_c) time_put<char>(1));
_M_init_facet(new (&messages_c) std::messages<char>(1));
#ifdef _GLIBCPP_USE_WCHAR_T #ifdef _GLIBCPP_USE_WCHAR_T
_M_init_facet(new (&ctype_w) std::ctype<wchar_t>); _M_init_facet(new (&ctype_w) std::ctype<wchar_t>(1));
_M_init_facet(new (&codecvt_w) codecvt<wchar_t, char, mbstate_t>); _M_init_facet(new (&codecvt_w) codecvt<wchar_t, char, mbstate_t>(1));
_M_init_facet(new (&numpunct_w) numpunct<wchar_t>); _M_init_facet(new (&numpunct_w) numpunct<wchar_t>(1));
_M_init_facet(new (&num_get_w) num_get<wchar_t>); _M_init_facet(new (&num_get_w) num_get<wchar_t>(1));
_M_init_facet(new (&num_put_w) num_put<wchar_t>); _M_init_facet(new (&num_put_w) num_put<wchar_t>(1));
_M_init_facet(new (&collate_w) std::collate<wchar_t>); _M_init_facet(new (&collate_w) std::collate<wchar_t>(1));
_M_init_facet(new (&moneypunct_fw) moneypunct<wchar_t, false>); _M_init_facet(new (&moneypunct_fw) moneypunct<wchar_t, false>(1));
_M_init_facet(new (&moneypunct_tw) moneypunct<wchar_t, true>); _M_init_facet(new (&moneypunct_tw) moneypunct<wchar_t, true>(1));
_M_init_facet(new (&money_get_w) money_get<wchar_t>); _M_init_facet(new (&money_get_w) money_get<wchar_t>(1));
_M_init_facet(new (&money_put_w) money_put<wchar_t>); _M_init_facet(new (&money_put_w) money_put<wchar_t>(1));
_M_init_facet(new (&timepunct_w) __timepunct<wchar_t>); _M_init_facet(new (&timepunct_w) __timepunct<wchar_t>(1));
_M_init_facet(new (&time_get_w) time_get<wchar_t>); _M_init_facet(new (&time_get_w) time_get<wchar_t>(1));
_M_init_facet(new (&time_put_w) time_put<wchar_t>); _M_init_facet(new (&time_put_w) time_put<wchar_t>(1));
_M_init_facet(new (&messages_w) std::messages<wchar_t>); _M_init_facet(new (&messages_w) std::messages<wchar_t>(1));
#endif #endif
} }
void void
...@@ -210,7 +265,7 @@ namespace std ...@@ -210,7 +265,7 @@ namespace std
_M_replace_categories(const _Impl* __imp, category __cat) _M_replace_categories(const _Impl* __imp, category __cat)
{ {
category __mask; category __mask;
for (unsigned int __ix = 0; __ix < _S_num_categories; ++__ix) for (size_t __ix = 0; __ix < _S_categories_size; ++__ix)
{ {
__mask = 1 << __ix; __mask = 1 << __ix;
if (__mask & __cat) if (__mask & __cat)
...@@ -220,7 +275,12 @@ namespace std ...@@ -220,7 +275,12 @@ namespace std
// If both have names, go ahead and mangle. // If both have names, go ahead and mangle.
if (strcmp(_M_names[__ix], "*") != 0 if (strcmp(_M_names[__ix], "*") != 0
&& strcmp(__imp->_M_names[__ix], "*") != 0) && strcmp(__imp->_M_names[__ix], "*") != 0)
_M_names[__ix] = __imp->_M_names[__ix]; {
delete [] _M_names[__ix];
char* __new = new char[strlen(__imp->_M_names[__ix]) + 1];
strcpy(__new, __imp->_M_names[__ix]);
_M_names[__ix] = __new;
}
} }
} }
} }
...@@ -250,6 +310,8 @@ namespace std ...@@ -250,6 +310,8 @@ namespace std
if (__fp) if (__fp)
{ {
size_t __index = __idp->_M_id(); size_t __index = __idp->_M_id();
// Check size of facet vector to ensure adequate room.
if (__index > _M_facets_size - 1) if (__index > _M_facets_size - 1)
{ {
facet** __old = _M_facets; facet** __old = _M_facets;
...@@ -266,11 +328,11 @@ namespace std ...@@ -266,11 +328,11 @@ namespace std
delete [] __old; delete [] __old;
} }
__fp->_M_add_reference();
facet*& __fpr = _M_facets[__index]; facet*& __fpr = _M_facets[__index];
if (__fpr) if (__fpr)
{ {
// Replacing an existing facet. Order matters. // Replacing an existing facet. Order matters.
__fp->_M_add_reference();
__fpr->_M_remove_reference(); __fpr->_M_remove_reference();
__fpr = __fp; __fpr = __fp;
} }
......
...@@ -121,7 +121,7 @@ void test01() ...@@ -121,7 +121,7 @@ void test01()
string str1, str2; string str1, str2;
// construct a locale object with the C facet // construct a locale object with the C facet
const locale& loc01 = locale::classic(); const locale loc01 = locale::classic();
// 1 // 1
// template <class Facet> locale(const locale& other, Facet* f) // template <class Facet> locale(const locale& other, Facet* f)
...@@ -315,16 +315,92 @@ void test03() ...@@ -315,16 +315,92 @@ void test03()
{ {
bool test = true; bool test = true;
#ifdef _GLIBCPP_HAVE_SETENV #ifdef _GLIBCPP_HAVE_SETENV
const char* oldLANG = getenv("LANG"); const char* oldLC_ALL = getenv("LC_ALL");
if (!setenv("LANG", "it_IT", 1)) if (!setenv("LC_ALL", "it_IT", 1))
{ {
std::locale loc(""); std::locale loc("");
VERIFY( loc.name() == "it_IT" ); VERIFY( loc.name() == "it_IT" );
setenv("LANG", oldLANG ? oldLANG : "", 1); setenv("LC_ALL", oldLC_ALL ? oldLC_ALL : "", 1);
} }
#endif #endif
} }
// More tests for Posix locale::name.
void test04()
{
bool test = true;
#ifdef _GLIBCPP_HAVE_SETENV
const char* oldLC_ALL = getenv("LC_ALL") ? strdup(getenv("LC_ALL")) : "";
const char* oldLANG = getenv("LANG") ? strdup(getenv("LANG")) : "";
// Check that a "POSIX" LC_ALL is equivalent to "C".
if (!setenv("LC_ALL", "POSIX", 1))
{
std::locale loc("");
VERIFY( loc.name() == "C" );
}
// Check the default set by LANG.
if (!setenv("LC_ALL", "", 1) && !setenv("LANG", "fr_FR", 1))
{
std::locale loc("");
VERIFY( loc.name() == "fr_FR" );
}
// Check that a "POSIX" LANG is equivalent to "C".
if (!setenv("LANG", "POSIX", 1))
{
std::locale loc("");
VERIFY( loc.name() == "C" );
}
// Setting a category in the "C" default.
const char* oldLC_COLLATE =
getenv("LC_COLLATE") ? strdup(getenv("LC_COLLATE")) : "";
if (!setenv("LC_COLLATE", "de_DE", 1))
{
std::locale loc("");
VERIFY( loc.name() == "LC_CTYPE=C;LC_NUMERIC=C;LC_COLLATE=de_DE;"
"LC_TIME=C;LC_MONETARY=C;LC_MESSAGES=C;LC_PAPER=C;"
"LC_NAME=C;LC_ADDRESS=C;LC_TELEPHONE=C;LC_MEASUREMENT=C;"
"LC_IDENTIFICATION=C" );
}
// Changing the LANG default while LC_COLLATE is set.
if (!setenv("LANG", "fr_FR", 1))
{
std::locale loc("");
VERIFY( loc.name() == "LC_CTYPE=fr_FR;LC_NUMERIC=fr_FR;"
"LC_COLLATE=de_DE;LC_TIME=fr_FR;LC_MONETARY=fr_FR;"
"LC_MESSAGES=fr_FR;LC_PAPER=fr_FR;LC_NAME=fr_FR;"
"LC_ADDRESS=fr_FR;LC_TELEPHONE=fr_FR;LC_MEASUREMENT=fr_FR;"
"LC_IDENTIFICATION=fr_FR" );
}
// Changing another (C only) category.
const char* oldLC_IDENTIFICATION =
getenv("LC_IDENTIFICATION") ? strdup(getenv("LC_IDENTIFICATION")) : "";
if (!setenv("LC_IDENTIFICATION", "it_IT", 1))
{
std::locale loc("");
VERIFY( loc.name() == "LC_CTYPE=fr_FR;LC_NUMERIC=fr_FR;"
"LC_COLLATE=de_DE;LC_TIME=fr_FR;LC_MONETARY=fr_FR;"
"LC_MESSAGES=fr_FR;LC_PAPER=fr_FR;LC_NAME=fr_FR;"
"LC_ADDRESS=fr_FR;LC_TELEPHONE=fr_FR;LC_MEASUREMENT=fr_FR;"
"LC_IDENTIFICATION=it_IT" );
}
// Restore the environment.
setenv("LC_ALL", oldLC_ALL ? oldLC_ALL : "", 1);
setenv("LANG", oldLANG ? oldLANG : "", 1);
setenv("LC_COLLATE", oldLC_COLLATE ? oldLC_COLLATE : "", 1);
setenv("LC_IDENTIFICATION",
oldLC_IDENTIFICATION ? oldLC_IDENTIFICATION : "", 1);
#endif
}
int main() int main()
{ {
test00(); test00();
...@@ -335,6 +411,7 @@ int main() ...@@ -335,6 +411,7 @@ int main()
test02(); test02();
test03(); test03();
test04();
return 0; return 0;
} }
// 2000-08-31 Benjamin Kosnik <bkoz@redhat.com> // 2000-08-31 Benjamin Kosnik <bkoz@redhat.com>
// Copyright (C) 2000 Free Software Foundation // Copyright (C) 2000, 2002 Free Software Foundation
// //
// This file is part of the GNU ISO C++ Library. This library is free // This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the // software; you can redistribute it and/or modify it under the
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
#include <iterator> #include <iterator>
#include <limits>
#include <testsuite_hooks.h> #include <testsuite_hooks.h>
// 1 a class if a facet if it is publicly derived from another facet // 1 a class if a facet if it is publicly derived from another facet
...@@ -233,9 +234,69 @@ void test01() ...@@ -233,9 +234,69 @@ void test01()
} }
} }
// Static counter for use in checking ctors/dtors.
static std::size_t counter;
class surf : public std::locale::facet
{
public:
static std::locale::id id;
surf(size_t refs = 0): std::locale::facet(refs) { ++counter; }
~surf() { --counter; }
};
std::locale::id surf::id;
typedef surf facet_type;
void test02()
{
using namespace std;
bool test = true;
// 1: Destroyed when out of scope.
VERIFY( counter == 0 );
{
locale loc01(locale::classic(), new facet_type);
VERIFY( counter == 1 );
}
VERIFY( counter == 0 );
// 2: Not destroyed when out of scope, deliberately leaked.
VERIFY( counter == 0 );
{
// Default refs argument is zero.
locale loc02(locale::classic(), new facet_type(1));
VERIFY( counter == 1 );
}
VERIFY( counter == 1 );
// 3: Pathological.
counter = 0;
{
// Test bounds.
facet_type* f = new facet_type(numeric_limits<size_t>::max());
VERIFY( counter == 1 );
// Add a reference.
locale loc01(locale::classic(), f);
{
// Add another reference...
locale loc02(locale::classic(), f);
}
VERIFY( counter == 1 );
}
// 4: Named locale should destroy facets when it goes out of scope.
// Not quite sure how to test for this w/o valgrind at the moment.
{
locale loc03("es_MX");
}
}
int main () int main ()
{ {
test01(); test01();
test02();
return 0; return 0;
} }
// 2000-09-13 Benjamin Kosnik <bkoz@redhat.com> // 2000-09-13 Benjamin Kosnik <bkoz@redhat.com>
// Copyright (C) 2000 Free Software Foundation // Copyright (C) 2000, 2002 Free Software Foundation
// //
// This file is part of the GNU ISO C++ Library. This library is free // This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the // software; you can redistribute it and/or modify it under the
...@@ -22,7 +22,9 @@ ...@@ -22,7 +22,9 @@
#include <cwchar> // for mbstate_t #include <cwchar> // for mbstate_t
#include <locale> #include <locale>
#include <testsuite_hooks.h> #include <iostream>
//#include <testsuite_hooks.h>
#define VERIFY(x) test &= x
typedef std::codecvt<char, char, std::mbstate_t> ccodecvt; typedef std::codecvt<char, char, std::mbstate_t> ccodecvt;
class gnu_codecvt: public ccodecvt { }; class gnu_codecvt: public ccodecvt { };
...@@ -34,10 +36,12 @@ void test01() ...@@ -34,10 +36,12 @@ void test01()
bool test = true; bool test = true;
string str1, str2; string str1, str2;
// construct a locale object with the C facet // Construct a locale object with the C facet.
const locale& loc01 = locale::classic(); const locale loc_env("");
// construct a locale object with the specialized facet. const locale loc01 = locale::classic();
locale loc02(locale::classic(), new gnu_codecvt);
// Construct a locale object with the specialized facet.
locale loc02(locale::classic(), new gnu_codecvt);
VERIFY ( loc01 != loc02 ); VERIFY ( loc01 != loc02 );
VERIFY ( !(loc01 == loc02) ); VERIFY ( !(loc01 == loc02) );
...@@ -54,11 +58,45 @@ void test01() ...@@ -54,11 +58,45 @@ void test01()
locale loc05; locale loc05;
VERIFY (loc05 != loc03); VERIFY (loc05 != loc03);
VERIFY (loc05 == loc02); VERIFY (loc05 == loc02);
// Reset global locale.
locale::global(loc_env);
}
// Sanity check locale::global(loc) and setlocale.
void test02()
{
using namespace std;
bool test = true;
const string ph("en_PH");
const string mx("es_MX");
const locale loc_ph(ph.c_str());
const locale loc_mx(mx.c_str());
// Get underlying current locale and environment settings.
const string lc_all_orig = std::setlocale(LC_ALL, NULL);
const locale loc_orig("");
// setlocale to en_PH
string lc_all_ph = std::setlocale(LC_ALL, ph.c_str());
const locale loc_env("");
VERIFY( loc_env == loc_orig );
locale::global(loc_mx);
string lc_all_mx = std::setlocale(LC_ALL, NULL);
VERIFY( lc_all_mx == mx.c_str() );
// Restore global info.
locale::global(loc_orig);
} }
int main () int main ()
{ {
test01(); test01();
test02();
return 0; return 0;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment