aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Carlini <pcarlini@unitus.it>2002-10-09 01:32:23 +0200
committerBenjamin Kosnik <bkoz@gcc.gnu.org>2002-10-08 23:32:23 +0000
commitaa53f832ac68acf6b5f8dee96bc1aeb57081fe76 (patch)
treeeea072530953d98ce478b1802853a40787210c1f
parent131d2c168d48e54d62a55263c560195ff0eadc9f (diff)
downloadgcc-aa53f832ac68acf6b5f8dee96bc1aeb57081fe76.zip
gcc-aa53f832ac68acf6b5f8dee96bc1aeb57081fe76.tar.gz
gcc-aa53f832ac68acf6b5f8dee96bc1aeb57081fe76.tar.bz2
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
-rw-r--r--libstdc++-v3/ChangeLog64
-rw-r--r--libstdc++-v3/config/locale/generic/c_locale.cc11
-rw-r--r--libstdc++-v3/config/locale/generic/c_locale.h2
-rw-r--r--libstdc++-v3/config/locale/generic/time_members.cc10
-rw-r--r--libstdc++-v3/config/locale/gnu/c_locale.cc22
-rw-r--r--libstdc++-v3/config/locale/gnu/c_locale.h2
-rw-r--r--libstdc++-v3/config/locale/gnu/ctype_members.cc3
-rw-r--r--libstdc++-v3/config/locale/gnu/monetary_members.cc19
-rw-r--r--libstdc++-v3/config/locale/gnu/numeric_members.cc4
-rw-r--r--libstdc++-v3/config/locale/gnu/time_members.cc20
-rw-r--r--libstdc++-v3/config/os/gnu-linux/ctype_noninline.h5
-rw-r--r--libstdc++-v3/docs/html/22_locale/locale.html29
-rw-r--r--libstdc++-v3/include/bits/locale_facets.h22
-rw-r--r--libstdc++-v3/include/bits/localefwd.h45
-rw-r--r--libstdc++-v3/src/codecvt.cc12
-rw-r--r--libstdc++-v3/src/ctype.cc11
-rw-r--r--libstdc++-v3/src/globals.cc5
-rw-r--r--libstdc++-v3/src/locale-inst.cc4
-rw-r--r--libstdc++-v3/src/locale.cc151
-rw-r--r--libstdc++-v3/src/localename.cc148
-rw-r--r--libstdc++-v3/testsuite/22_locale/ctor_copy_dtor.cc85
-rw-r--r--libstdc++-v3/testsuite/22_locale/facet.cc63
-rw-r--r--libstdc++-v3/testsuite/22_locale/static_members.cc50
23 files changed, 609 insertions, 178 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 2f93aa9..5bb78b8 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,67 @@
+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>
* docs/html/configopts.html, docs/html/documentation.html,
diff --git a/libstdc++-v3/config/locale/generic/c_locale.cc b/libstdc++-v3/config/locale/generic/c_locale.cc
index e274836f..689bbf5 100644
--- a/libstdc++-v3/config/locale/generic/c_locale.cc
+++ b/libstdc++-v3/config/locale/generic/c_locale.cc
@@ -223,4 +223,15 @@ namespace std
__c_locale
locale::facet::_S_clone_c_locale(__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
diff --git a/libstdc++-v3/config/locale/generic/c_locale.h b/libstdc++-v3/config/locale/generic/c_locale.h
index bfd9bf0..9627d86 100644
--- a/libstdc++-v3/config/locale/generic/c_locale.h
+++ b/libstdc++-v3/config/locale/generic/c_locale.h
@@ -35,6 +35,8 @@
#include <clocale>
+#define _GLIBCPP_NUM_CATEGORIES 0
+
namespace std
{
typedef int* __c_locale;
diff --git a/libstdc++-v3/config/locale/generic/time_members.cc b/libstdc++-v3/config/locale/generic/time_members.cc
index d02f0c3..7b5a25c 100644
--- a/libstdc++-v3/config/locale/generic/time_members.cc
+++ b/libstdc++-v3/config/locale/generic/time_members.cc
@@ -40,10 +40,7 @@ namespace std
{
template<>
__timepunct<char>::~__timepunct()
- {
- if (_M_c_locale_timepunct != _S_c_locale)
- _S_destroy_c_locale(_M_c_locale_timepunct);
- }
+ { _S_destroy_c_locale(_M_c_locale_timepunct); }
template<>
void
@@ -123,10 +120,7 @@ namespace std
#ifdef _GLIBCPP_USE_WCHAR_T
template<>
__timepunct<wchar_t>::~__timepunct()
- {
- if (_M_c_locale_timepunct != _S_c_locale)
- _S_destroy_c_locale(_M_c_locale_timepunct);
- }
+ { _S_destroy_c_locale(_M_c_locale_timepunct); }
template<>
void
diff --git a/libstdc++-v3/config/locale/gnu/c_locale.cc b/libstdc++-v3/config/locale/gnu/c_locale.cc
index 3982a65..188f3a2 100644
--- a/libstdc++-v3/config/locale/gnu/c_locale.cc
+++ b/libstdc++-v3/config/locale/gnu/c_locale.cc
@@ -178,9 +178,29 @@ namespace std
void
locale::facet::_S_destroy_c_locale(__c_locale& __cloc)
- { __freelocale(__cloc); }
+ {
+ if (_S_c_locale != __cloc)
+ __freelocale(__cloc);
+ }
__c_locale
locale::facet::_S_clone_c_locale(__c_locale& __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
diff --git a/libstdc++-v3/config/locale/gnu/c_locale.h b/libstdc++-v3/config/locale/gnu/c_locale.h
index aabbe6a..130b843 100644
--- a/libstdc++-v3/config/locale/gnu/c_locale.h
+++ b/libstdc++-v3/config/locale/gnu/c_locale.h
@@ -40,6 +40,8 @@
#define _GLIBCPP_C_LOCALE_GNU 1
+#define _GLIBCPP_NUM_CATEGORIES 6
+
#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
namespace __gnu_cxx
{
diff --git a/libstdc++-v3/config/locale/gnu/ctype_members.cc b/libstdc++-v3/config/locale/gnu/ctype_members.cc
index db1e356..3b78c60 100644
--- a/libstdc++-v3/config/locale/gnu/ctype_members.cc
+++ b/libstdc++-v3/config/locale/gnu/ctype_members.cc
@@ -44,8 +44,7 @@ namespace std
ctype_byname<char>::ctype_byname(const char* __s, size_t __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);
_M_toupper = _M_c_locale_ctype->__ctype_toupper;
_M_tolower = _M_c_locale_ctype->__ctype_tolower;
diff --git a/libstdc++-v3/config/locale/gnu/monetary_members.cc b/libstdc++-v3/config/locale/gnu/monetary_members.cc
index 68b154b..0386ab6 100644
--- a/libstdc++-v3/config/locale/gnu/monetary_members.cc
+++ b/libstdc++-v3/config/locale/gnu/monetary_members.cc
@@ -220,7 +220,7 @@ namespace std
moneypunct<char, true>::_M_initialize_moneypunct(__c_locale __cloc,
const char*)
{
- if (__cloc == _S_c_locale)
+ if (!__cloc)
{
// "C" locale
_M_decimal_point = '.';
@@ -265,7 +265,7 @@ namespace std
moneypunct<char, false>::_M_initialize_moneypunct(__c_locale __cloc,
const char*)
{
- if (__cloc == _S_c_locale)
+ if (!__cloc)
{
// "C" locale
_M_decimal_point = '.';
@@ -319,7 +319,7 @@ namespace std
moneypunct<wchar_t, true>::_M_initialize_moneypunct(__c_locale __cloc,
const char* __name)
{
- if (__cloc == _S_c_locale)
+ if (!__cloc)
{
// "C" locale
_M_decimal_point = L'.';
@@ -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_grouping = __nl_langinfo_l(GROUPING, __cloc);
- mbstate_t __state;
- size_t __len;
const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
const char* __ccurr = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc);
- // NB: Should swich to __cloc's ctype info first.
- __len = strlen(__cpossign);
+ mbstate_t __state;
+ size_t __len = strlen(__cpossign);
if (__len)
{
++__len;
@@ -418,7 +416,7 @@ namespace std
moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc,
const char* __name)
{
- if (__cloc == _S_c_locale)
+ if (!__cloc)
{
// "C" locale
_M_decimal_point = L'.';
@@ -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_grouping = __nl_langinfo_l(GROUPING, __cloc);
- mbstate_t __state;
- size_t __len;
const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __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);
if (__len)
{
diff --git a/libstdc++-v3/config/locale/gnu/numeric_members.cc b/libstdc++-v3/config/locale/gnu/numeric_members.cc
index b71374c..a502bfb 100644
--- a/libstdc++-v3/config/locale/gnu/numeric_members.cc
+++ b/libstdc++-v3/config/locale/gnu/numeric_members.cc
@@ -42,7 +42,7 @@ namespace std
void
numpunct<char>::_M_initialize_numpunct(__c_locale __cloc)
{
- if (__cloc == _S_c_locale)
+ if (!__cloc)
{
// "C" locale
_M_decimal_point = '.';
@@ -76,7 +76,7 @@ namespace std
void
numpunct<wchar_t>::_M_initialize_numpunct(__c_locale __cloc)
{
- if (__cloc == _S_c_locale)
+ if (!__cloc)
{
// "C" locale
_M_decimal_point = L'.';
diff --git a/libstdc++-v3/config/locale/gnu/time_members.cc b/libstdc++-v3/config/locale/gnu/time_members.cc
index ce3d9bf..b2b6f23 100644
--- a/libstdc++-v3/config/locale/gnu/time_members.cc
+++ b/libstdc++-v3/config/locale/gnu/time_members.cc
@@ -41,10 +41,7 @@ namespace std
{
template<>
__timepunct<char>::~__timepunct()
- {
- if (_M_c_locale_timepunct != _S_c_locale)
- _S_destroy_c_locale(_M_c_locale_timepunct);
- }
+ { _S_destroy_c_locale(_M_c_locale_timepunct); }
template<>
void
@@ -67,11 +64,10 @@ namespace std
void
__timepunct<char>::_M_initialize_timepunct(__c_locale __cloc)
{
- if (__cloc == _S_c_locale)
+ if (!__cloc)
{
// "C" locale
-
- _M_c_locale_timepunct = _S_c_locale;
+ _M_c_locale_timepunct = _S_c_locale;
_M_date_format = "%m/%d/%y";
_M_date_era_format = "%m/%d/%y";
@@ -194,10 +190,7 @@ namespace std
#ifdef _GLIBCPP_USE_WCHAR_T
template<>
__timepunct<wchar_t>::~__timepunct()
- {
- if (_M_c_locale_timepunct != _S_c_locale)
- _S_destroy_c_locale(_M_c_locale_timepunct);
- }
+ { _S_destroy_c_locale(_M_c_locale_timepunct); }
template<>
void
@@ -220,11 +213,10 @@ namespace std
void
__timepunct<wchar_t>::_M_initialize_timepunct(__c_locale __cloc)
{
- if (__cloc == _S_c_locale)
+ if (!__cloc)
{
// "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_era_format = L"%m/%d/%y";
diff --git a/libstdc++-v3/config/os/gnu-linux/ctype_noninline.h b/libstdc++-v3/config/os/gnu-linux/ctype_noninline.h
index 1578828..8f06d13 100644
--- a/libstdc++-v3/config/os/gnu-linux/ctype_noninline.h
+++ b/libstdc++-v3/config/os/gnu-linux/ctype_noninline.h
@@ -38,8 +38,7 @@
const ctype_base::mask*
ctype<char>::classic_table() throw()
{
- if (!_S_c_locale)
- _S_create_c_locale(_S_c_locale, "C");
+ locale::classic();
return _S_c_locale->__ctype_b;
}
#else
@@ -96,7 +95,7 @@
ctype<char>::ctype(const mask* __table, bool __del, size_t __refs) :
__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_tolower = _M_c_locale_ctype->__ctype_tolower;
_M_table = __table ? __table : _M_c_locale_ctype->__ctype_b;
diff --git a/libstdc++-v3/docs/html/22_locale/locale.html b/libstdc++-v3/docs/html/22_locale/locale.html
index 437acce..d4d74b5 100644
--- a/libstdc++-v3/docs/html/22_locale/locale.html
+++ b/libstdc++-v3/docs/html/22_locale/locale.html
@@ -68,14 +68,36 @@ public:
The only other thing of interest in this class is the memory
management of facets. Each constructor of a facet class takes a
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
-it is no longer reference.
+the locale containing it is destroyed. If __refs == 1, the facet is
+not destroyed, even when it is no longer referenced.
class id
Provides an index for looking up specific facets.
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>
5. Examples
@@ -87,8 +109,7 @@ class _Impl
More information can be found in the following testcases:
<ul>
-<li> testsuite/22_locale/ctype_char_members.cc </li>
-<li> testsuite/22_locale/ctype_wchar_t_members.cc </li>
+<li> testsuite/22_locale/all </li>
</ul>
<h2>
diff --git a/libstdc++-v3/include/bits/locale_facets.h b/libstdc++-v3/include/bits/locale_facets.h
index f99562f..55953c0 100644
--- a/libstdc++-v3/include/bits/locale_facets.h
+++ b/libstdc++-v3/include/bits/locale_facets.h
@@ -525,7 +525,7 @@ namespace std
// For use at construction time only.
void
- _M_initialize_numpunct(__c_locale __cloc = _S_c_locale);
+ _M_initialize_numpunct(__c_locale __cloc = NULL);
};
template<typename _CharT>
@@ -875,10 +875,7 @@ namespace std
protected:
virtual
~collate()
- {
- if (_M_c_locale_collate != _S_c_locale)
- _S_destroy_c_locale(_M_c_locale_collate);
- }
+ { _S_destroy_c_locale(_M_c_locale_collate); }
virtual int
do_compare(const _CharT* __lo1, const _CharT* __hi1,
@@ -924,8 +921,7 @@ namespace std
collate_byname(const char* __s, size_t __refs = 0)
: 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);
}
@@ -1123,7 +1119,7 @@ namespace std
// For use at construction time only.
void
- _M_initialize_timepunct(__c_locale __cloc = _S_c_locale);
+ _M_initialize_timepunct(__c_locale __cloc = NULL);
};
template<typename _CharT>
@@ -1459,7 +1455,7 @@ namespace std
// For use at construction time only.
void
- _M_initialize_moneypunct(__c_locale __cloc = _S_c_locale,
+ _M_initialize_moneypunct(__c_locale __cloc = NULL,
const char* __name = NULL);
};
@@ -1667,10 +1663,7 @@ namespace std
protected:
virtual
~messages()
- {
- if (_M_c_locale_messages != _S_c_locale)
- _S_destroy_c_locale(_M_c_locale_messages);
- }
+ { _S_destroy_c_locale(_M_c_locale_messages); }
virtual catalog
do_open(const basic_string<char>&, const locale&) const;
@@ -1759,8 +1752,7 @@ namespace std
: messages<_CharT>(__refs)
{
_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);
}
diff --git a/libstdc++-v3/include/bits/localefwd.h b/libstdc++-v3/include/bits/localefwd.h
index b92560f..7627960 100644
--- a/libstdc++-v3/include/bits/localefwd.h
+++ b/libstdc++-v3/include/bits/localefwd.h
@@ -207,8 +207,8 @@ namespace std
static const category time = 1L << 3;
static const category monetary = 1L << 4;
static const category messages = 1L << 5;
- static const category all = (collate | ctype | monetary |
- numeric | time | messages);
+ static const category all = (ctype | numeric | collate |
+ time | monetary | messages);
// Construct/copy/destroy:
locale() throw();
@@ -267,7 +267,26 @@ namespace std
// Current global reference locale
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
locale(_Impl*) throw();
@@ -308,7 +327,9 @@ namespace std
_Atomic_word _M_references;
facet** _M_facets;
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_numeric[];
static const locale::id* const _S_id_collate[];
@@ -348,8 +369,10 @@ namespace std
_M_check_same_name()
{
bool __ret = true;
- for (size_t i = 0; __ret && i < _S_num_categories - 1; ++i)
- __ret &= (strcmp(_M_names[i], _M_names[i + 1]) == 0);
+ for (size_t __i = 0;
+ __ret && __i < _S_categories_size + _S_extra_categories_size - 1;
+ ++__i)
+ __ret &= (strcmp(_M_names[__i], _M_names[__i + 1]) == 0);
return __ret;
}
@@ -376,8 +399,14 @@ namespace std
{
_M_impl = new _Impl(*__other._M_impl, 1);
_M_impl->_M_install_facet(&_Facet::id, __f);
- for (size_t __i = 0; __i < _S_num_categories; ++__i)
- _M_impl->_M_names[__i] = "*";
+ for (size_t __i = 0;
+ __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
diff --git a/libstdc++-v3/src/codecvt.cc b/libstdc++-v3/src/codecvt.cc
index 8d4c1b4..b9575cf 100644
--- a/libstdc++-v3/src/codecvt.cc
+++ b/libstdc++-v3/src/codecvt.cc
@@ -55,10 +55,7 @@ namespace std
codecvt<char, char, mbstate_t>::
~codecvt()
- {
- if (_M_c_locale_codecvt != _S_c_locale)
- _S_destroy_c_locale(_M_c_locale_codecvt);
- }
+ { _S_destroy_c_locale(_M_c_locale_codecvt); }
codecvt_base::result
codecvt<char, char, mbstate_t>::
@@ -123,7 +120,7 @@ namespace std
codecvt<wchar_t, char, mbstate_t>::
codecvt(size_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(__c_locale __cloc, size_t __refs)
@@ -132,10 +129,7 @@ namespace std
codecvt<wchar_t, char, mbstate_t>::
~codecvt()
- {
- if (_M_c_locale_codecvt != _S_c_locale)
- _S_destroy_c_locale(_M_c_locale_codecvt);
- }
+ { _S_destroy_c_locale(_M_c_locale_codecvt); }
codecvt_base::result
codecvt<wchar_t, char, mbstate_t>::
diff --git a/libstdc++-v3/src/ctype.cc b/libstdc++-v3/src/ctype.cc
index 7ca934e..3d5ee61 100644
--- a/libstdc++-v3/src/ctype.cc
+++ b/libstdc++-v3/src/ctype.cc
@@ -79,8 +79,7 @@ namespace std
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)
delete[] this->table();
}
@@ -135,17 +134,13 @@ namespace std
{ _M_c_locale_ctype = _S_clone_c_locale(__cloc); }
ctype<wchar_t>::~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); }
template<>
ctype_byname<wchar_t>::ctype_byname(const char* __s, size_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);
}
#endif
diff --git a/libstdc++-v3/src/globals.cc b/libstdc++-v3/src/globals.cc
index 36d193f..079fff8 100644
--- a/libstdc++-v3/src/globals.cc
+++ b/libstdc++-v3/src/globals.cc
@@ -59,6 +59,10 @@ namespace std
__attribute__ ((aligned(__alignof__(locale::facet*))));
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>)]
__attribute__ ((aligned(__alignof__(std::ctype<char>))));
fake_ctype_c ctype_c;
@@ -200,7 +204,6 @@ namespace std
fake_wfilebuf buf_wcerr;
#endif
-
// Globals for once-only runtime initialization of mutex objects. This
// allows static initialization of these objects on systems that need a
// function call to initialize a mutex. For example, see stl_threads.h.
diff --git a/libstdc++-v3/src/locale-inst.cc b/libstdc++-v3/src/locale-inst.cc
index 5e6c675..8f2c863 100644
--- a/libstdc++-v3/src/locale-inst.cc
+++ b/libstdc++-v3/src/locale-inst.cc
@@ -35,11 +35,7 @@
#include <clocale>
#include <cstring>
#include <cassert>
-#include <limits>
-#include <exception>
#include <locale>
-#include <istream>
-#include <ostream>
namespace std
{
diff --git a/libstdc++-v3/src/locale.cc b/libstdc++-v3/src/locale.cc
index 6314ba6..641bee2 100644
--- a/libstdc++-v3/src/locale.cc
+++ b/libstdc++-v3/src/locale.cc
@@ -31,11 +31,7 @@
#include <cassert>
#include <cctype>
#include <cwctype> // For towupper, etc.
-#include <limits>
-#include <exception>
#include <locale>
-#include <istream>
-#include <ostream>
#include <bits/atomicity.h>
namespace std
@@ -43,7 +39,6 @@ namespace std
// Defined in globals.cc.
extern locale c_locale;
extern locale::_Impl c_locale_impl;
- extern locale::facet** facet_vec;
// Definitions for static const data members of locale.
const locale::category locale::none;
@@ -57,7 +52,8 @@ namespace std
locale::_Impl* locale::_S_classic;
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
_Atomic_word locale::id::_S_highwater; // init'd to 0 by linker
@@ -146,8 +142,8 @@ namespace std
locale::_Impl::_S_id_ctype,
locale::_Impl::_S_id_numeric,
locale::_Impl::_S_id_collate,
- locale::_Impl::_S_id_monetary,
locale::_Impl::_S_id_time,
+ locale::_Impl::_S_id_monetary,
locale::_Impl::_S_id_messages,
0
};
@@ -192,18 +188,110 @@ namespace std
_S_initialize();
if (strcmp(__s, "C") == 0 || strcmp(__s, "POSIX") == 0)
(_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");
- if (__env)
- _M_impl = new _Impl(__env, 1);
- else if ((__env = getenv("LANG")))
- _M_impl = new _Impl(__env, 1);
+ // If LC_ALL is set we are done.
+ if (__env && strcmp(__env, "") != 0)
+ {
+ if (strcmp(__env, "C") == 0 || strcmp(__env, "POSIX") == 0)
+ (_M_impl = _S_classic)->_M_add_reference();
+ else
+ _M_impl = new _Impl(__env, 1);
+ }
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
__throw_runtime_error("attempt to create locale from NULL name");
@@ -261,20 +349,22 @@ namespace std
string
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;
if (_M_impl->_M_check_same_name())
__ret = _M_impl->_M_names[0];
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 += _M_impl->_M_names[i];
+ __ret += ";";
+ __ret += _S_categories[__i];
+ __ret += "=";
+ __ret += _M_impl->_M_names[__i];
}
}
return __ret;
@@ -292,11 +382,7 @@ namespace std
{
// 26 Standard facets, 2 references.
// One reference for _M_classic, one for _M_global
- facet** f = new(&facet_vec) facet*[_GLIBCPP_NUM_FACETS];
- for (size_t __i = 0; __i < _GLIBCPP_NUM_FACETS; ++__i)
- f[__i] = 0;
-
- _S_classic = new (&c_locale_impl) _Impl(f, 2, true);
+ _S_classic = new (&c_locale_impl) _Impl(0, 2, true);
_S_global = _S_classic;
new (&c_locale) locale(_S_classic);
}
@@ -361,11 +447,8 @@ namespace std
~facet() { }
locale::facet::
- facet(size_t __refs) throw() : _M_references(__refs)
- {
- if (!_S_c_locale)
- _S_create_c_locale(_S_c_locale, "C");
- }
+ facet(size_t __refs) throw() : _M_references(__refs ? 1 : 0)
+ { }
void
locale::facet::
@@ -376,7 +459,7 @@ namespace std
locale::facet::
_M_remove_reference() throw()
{
- if (__exchange_and_add(&_M_references, -1) == 0)
+ if (__exchange_and_add(&_M_references, -1) == 1)
{
try
{ delete this; }
diff --git a/libstdc++-v3/src/localename.cc b/libstdc++-v3/src/localename.cc
index a0c9e75..a233eb3 100644
--- a/libstdc++-v3/src/localename.cc
+++ b/libstdc++-v3/src/localename.cc
@@ -33,6 +33,9 @@
namespace std
{
// 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::collate<char> collate_c;
extern numpunct<char> numpunct_c;
@@ -71,6 +74,10 @@ namespace std
if (_M_facets[__i])
_M_facets[__i]->_M_remove_reference();
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.
@@ -95,14 +102,19 @@ namespace std
if (_M_facets[__i])
_M_facets[__i]->_M_add_reference();
}
- for (size_t __i = 0; __i < _S_num_categories; ++__i)
- _M_names[__i] = __imp._M_names[__i];
+ for (size_t __i = 0;
+ __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.
locale::_Impl::
_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
// to see if the given name is valid.
@@ -122,11 +134,40 @@ namespace std
}
// Name all the categories.
- for (size_t i = 0; i < _S_num_categories; ++i)
- _M_names[i] = __s;
+ if (!strchr(__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.
- _M_init_facet(new std::ctype<char>(__cloc));
+ free(__tmp);
+ }
+
+ // 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 numpunct<char>(__cloc));
_M_init_facet(new num_get<char>);
@@ -162,47 +203,61 @@ namespace std
// Construct "C" _Impl.
locale::_Impl::
- _Impl(facet** __f, size_t __refs, bool)
- : _M_references(__refs), _M_facets(__f), _M_facets_size(_GLIBCPP_NUM_FACETS)
+ _Impl(facet**, size_t __refs, bool)
+ : _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.
- for (size_t i = 0; i < _S_num_categories; ++i)
- _M_names[i] = "C";
+ for (size_t __i = 0;
+ __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
// != data in the underlying locale model for __timepunct,
// numpunct, and moneypunct. Also, the "C" locales must be
// constructed in a way such that they are pre-allocated.
- _M_init_facet(new (&ctype_c) std::ctype<char>);
- _M_init_facet(new (&codecvt_c) codecvt<char, char, mbstate_t>);
- _M_init_facet(new (&numpunct_c) numpunct<char>);
- _M_init_facet(new (&num_get_c) num_get<char>);
- _M_init_facet(new (&num_put_c) num_put<char>);
- _M_init_facet(new (&collate_c) std::collate<char>);
- _M_init_facet(new (&moneypunct_fc) moneypunct<char, false>);
- _M_init_facet(new (&moneypunct_tc) moneypunct<char, true>);
- _M_init_facet(new (&money_get_c) money_get<char>);
- _M_init_facet(new (&money_put_c) money_put<char>);
- _M_init_facet(new (&timepunct_c) __timepunct<char>);
- _M_init_facet(new (&time_get_c) time_get<char>);
- _M_init_facet(new (&time_put_c) time_put<char>);
- _M_init_facet(new (&messages_c) std::messages<char>);
+ // NB: Set locale::facets(ref) count to one so that each individual
+ // facet is not destroyed when the locale (and thus locale::_Impl) is
+ // destroyed.
+ _M_init_facet(new (&ctype_c) std::ctype<char>(0, false, 1));
+ _M_init_facet(new (&codecvt_c) codecvt<char, char, mbstate_t>(1));
+ _M_init_facet(new (&numpunct_c) numpunct<char>(1));
+ _M_init_facet(new (&num_get_c) num_get<char>(1));
+ _M_init_facet(new (&num_put_c) num_put<char>(1));
+ _M_init_facet(new (&collate_c) std::collate<char>(1));
+ _M_init_facet(new (&moneypunct_fc) moneypunct<char, false>(1));
+ _M_init_facet(new (&moneypunct_tc) moneypunct<char, true>(1));
+ _M_init_facet(new (&money_get_c) money_get<char>(1));
+ _M_init_facet(new (&money_put_c) money_put<char>(1));
+ _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
- _M_init_facet(new (&ctype_w) std::ctype<wchar_t>);
- _M_init_facet(new (&codecvt_w) codecvt<wchar_t, char, mbstate_t>);
- _M_init_facet(new (&numpunct_w) numpunct<wchar_t>);
- _M_init_facet(new (&num_get_w) num_get<wchar_t>);
- _M_init_facet(new (&num_put_w) num_put<wchar_t>);
- _M_init_facet(new (&collate_w) std::collate<wchar_t>);
- _M_init_facet(new (&moneypunct_fw) moneypunct<wchar_t, false>);
- _M_init_facet(new (&moneypunct_tw) moneypunct<wchar_t, true>);
- _M_init_facet(new (&money_get_w) money_get<wchar_t>);
- _M_init_facet(new (&money_put_w) money_put<wchar_t>);
- _M_init_facet(new (&timepunct_w) __timepunct<wchar_t>);
- _M_init_facet(new (&time_get_w) time_get<wchar_t>);
- _M_init_facet(new (&time_put_w) time_put<wchar_t>);
- _M_init_facet(new (&messages_w) std::messages<wchar_t>);
-#endif
+ _M_init_facet(new (&ctype_w) std::ctype<wchar_t>(1));
+ _M_init_facet(new (&codecvt_w) codecvt<wchar_t, char, mbstate_t>(1));
+ _M_init_facet(new (&numpunct_w) numpunct<wchar_t>(1));
+ _M_init_facet(new (&num_get_w) num_get<wchar_t>(1));
+ _M_init_facet(new (&num_put_w) num_put<wchar_t>(1));
+ _M_init_facet(new (&collate_w) std::collate<wchar_t>(1));
+ _M_init_facet(new (&moneypunct_fw) moneypunct<wchar_t, false>(1));
+ _M_init_facet(new (&moneypunct_tw) moneypunct<wchar_t, true>(1));
+ _M_init_facet(new (&money_get_w) money_get<wchar_t>(1));
+ _M_init_facet(new (&money_put_w) money_put<wchar_t>(1));
+ _M_init_facet(new (&timepunct_w) __timepunct<wchar_t>(1));
+ _M_init_facet(new (&time_get_w) time_get<wchar_t>(1));
+ _M_init_facet(new (&time_put_w) time_put<wchar_t>(1));
+ _M_init_facet(new (&messages_w) std::messages<wchar_t>(1));
+#endif
}
void
@@ -210,7 +265,7 @@ namespace std
_M_replace_categories(const _Impl* __imp, category __cat)
{
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;
if (__mask & __cat)
@@ -220,7 +275,12 @@ namespace std
// If both have names, go ahead and mangle.
if (strcmp(_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
if (__fp)
{
size_t __index = __idp->_M_id();
+
+ // Check size of facet vector to ensure adequate room.
if (__index > _M_facets_size - 1)
{
facet** __old = _M_facets;
@@ -266,11 +328,11 @@ namespace std
delete [] __old;
}
+ __fp->_M_add_reference();
facet*& __fpr = _M_facets[__index];
if (__fpr)
{
// Replacing an existing facet. Order matters.
- __fp->_M_add_reference();
__fpr->_M_remove_reference();
__fpr = __fp;
}
diff --git a/libstdc++-v3/testsuite/22_locale/ctor_copy_dtor.cc b/libstdc++-v3/testsuite/22_locale/ctor_copy_dtor.cc
index a27b245..6f4b1bf 100644
--- a/libstdc++-v3/testsuite/22_locale/ctor_copy_dtor.cc
+++ b/libstdc++-v3/testsuite/22_locale/ctor_copy_dtor.cc
@@ -121,7 +121,7 @@ void test01()
string str1, str2;
// construct a locale object with the C facet
- const locale& loc01 = locale::classic();
+ const locale loc01 = locale::classic();
// 1
// template <class Facet> locale(const locale& other, Facet* f)
@@ -315,16 +315,92 @@ void test03()
{
bool test = true;
#ifdef _GLIBCPP_HAVE_SETENV
- const char* oldLANG = getenv("LANG");
- if (!setenv("LANG", "it_IT", 1))
+ const char* oldLC_ALL = getenv("LC_ALL");
+ if (!setenv("LC_ALL", "it_IT", 1))
{
std::locale loc("");
VERIFY( loc.name() == "it_IT" );
- setenv("LANG", oldLANG ? oldLANG : "", 1);
+ setenv("LC_ALL", oldLC_ALL ? oldLC_ALL : "", 1);
}
#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()
{
test00();
@@ -335,6 +411,7 @@ int main()
test02();
test03();
+ test04();
return 0;
}
diff --git a/libstdc++-v3/testsuite/22_locale/facet.cc b/libstdc++-v3/testsuite/22_locale/facet.cc
index 431718e..9c613b4 100644
--- a/libstdc++-v3/testsuite/22_locale/facet.cc
+++ b/libstdc++-v3/testsuite/22_locale/facet.cc
@@ -1,6 +1,6 @@
// 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
// software; you can redistribute it and/or modify it under the
@@ -25,6 +25,7 @@
#include <stdexcept>
#include <string>
#include <iterator>
+#include <limits>
#include <testsuite_hooks.h>
// 1 a class if a facet if it is publicly derived from another facet
@@ -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 ()
{
test01();
+ test02();
return 0;
}
diff --git a/libstdc++-v3/testsuite/22_locale/static_members.cc b/libstdc++-v3/testsuite/22_locale/static_members.cc
index 16e856a..06b1258 100644
--- a/libstdc++-v3/testsuite/22_locale/static_members.cc
+++ b/libstdc++-v3/testsuite/22_locale/static_members.cc
@@ -1,6 +1,6 @@
// 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
// software; you can redistribute it and/or modify it under the
@@ -22,7 +22,9 @@
#include <cwchar> // for mbstate_t
#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;
class gnu_codecvt: public ccodecvt { };
@@ -34,10 +36,12 @@ void test01()
bool test = true;
string str1, str2;
- // construct a locale object with the C facet
- const locale& loc01 = locale::classic();
- // construct a locale object with the specialized facet.
- locale loc02(locale::classic(), new gnu_codecvt);
+ // Construct a locale object with the C facet.
+ const locale loc_env("");
+ const locale loc01 = locale::classic();
+
+ // Construct a locale object with the specialized facet.
+ locale loc02(locale::classic(), new gnu_codecvt);
VERIFY ( loc01 != loc02 );
VERIFY ( !(loc01 == loc02) );
@@ -54,11 +58,45 @@ void test01()
locale loc05;
VERIFY (loc05 != loc03);
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 ()
{
test01();
+ test02();
return 0;
}