localefwd.h (class locale): Add static member _S_num_extra_categories...
authorPaolo Carlini <pcarlini@unitus.it>
Tue, 8 Oct 2002 23:32:23 +0000 (01:32 +0200)
committerBenjamin Kosnik <bkoz@gcc.gnu.org>
Tue, 8 Oct 2002 23:32:23 +0000 (23:32 +0000)
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

23 files changed:
libstdc++-v3/ChangeLog
libstdc++-v3/config/locale/generic/c_locale.cc
libstdc++-v3/config/locale/generic/c_locale.h
libstdc++-v3/config/locale/generic/time_members.cc
libstdc++-v3/config/locale/gnu/c_locale.cc
libstdc++-v3/config/locale/gnu/c_locale.h
libstdc++-v3/config/locale/gnu/ctype_members.cc
libstdc++-v3/config/locale/gnu/monetary_members.cc
libstdc++-v3/config/locale/gnu/numeric_members.cc
libstdc++-v3/config/locale/gnu/time_members.cc
libstdc++-v3/config/os/gnu-linux/ctype_noninline.h
libstdc++-v3/docs/html/22_locale/locale.html
libstdc++-v3/include/bits/locale_facets.h
libstdc++-v3/include/bits/localefwd.h
libstdc++-v3/src/codecvt.cc
libstdc++-v3/src/ctype.cc
libstdc++-v3/src/globals.cc
libstdc++-v3/src/locale-inst.cc
libstdc++-v3/src/locale.cc
libstdc++-v3/src/localename.cc
libstdc++-v3/testsuite/22_locale/ctor_copy_dtor.cc
libstdc++-v3/testsuite/22_locale/facet.cc
libstdc++-v3/testsuite/22_locale/static_members.cc

index 2f93aa97f31a3bed132c9ecfff85355ea5c07a29..5bb78b8422679bbe298cb425681c358351c4418a 100644 (file)
@@ -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,
index e274836fd901d39de172da81f3bcef09335705f2..689bbf592b930651027d844e08e1d8c0d60e6673 100644 (file)
@@ -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
index bfd9bf0a0bf193d9f7e92e0945b98870e8116639..9627d8646afe33e55f1ca974d62d1b65f777e4a3 100644 (file)
@@ -35,6 +35,8 @@
 
 #include <clocale>
 
+#define _GLIBCPP_NUM_CATEGORIES 0
+
 namespace std
 {
   typedef int*                 __c_locale;
index d02f0c3fa0eaf0e1a3dd30efc39703526064e04f..7b5a25c87609973a82d78eb776a0eef1bc356ad8 100644 (file)
@@ -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
index 3982a65ceb6bbf85794724775f7655253b662e00..188f3a2f1c1bcb60db184d6769dcfd529ce8a1e2 100644 (file)
@@ -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
index aabbe6af42564a7a9f069695fa383cdd75f9dba1..130b843d7f9e433c3922a511a3f854da80b2ab52 100644 (file)
@@ -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
 {
index db1e356d038127be553918e4042e912a3ddc864d..3b78c60405a155b2b94ce08536fb6e42a2a5862c 100644 (file)
@@ -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;
index 68b154bdc7ceb80f9fe656533e153217e82accbf..0386ab6dc5469ce43e1db4dbf8817bf66a99d101 100644 (file)
@@ -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)
            {
index b71374c4b8e59f81a1246090dbf9b429ce5c45f0..a502bfb2150f88895112f04161aeb2453332b33c 100644 (file)
@@ -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'.';
index ce3d9bf01066ace4d18466ad04b055cac07b0a9e..b2b6f23120f9b4de144dc8a8b32a21c4cd09f663 100644 (file)
@@ -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";
index 1578828ccedd5c55711edc789a994d73f063bc88..8f06d1397ee0cc397d9cf4a79263777f74401201 100644 (file)
@@ -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;
index 437acce040602bc050f29191cb1b0013ef9d6e83..d4d74b536c93366f9bd205f61f1b2bed33b9347a 100644 (file)
@@ -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>
index f99562fac49eb41f6c98bb5d3129ddac79f60714..55953c0d5b1514b69d7cd5829acf5784f76e4f0a 100644 (file)
@@ -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); 
       }
 
index b92560f0b52c86ec0d94a6338c8f0a4f68621105..762796099215d5e70bf15a3097b2eaec40b75d39 100644 (file)
@@ -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
index 8d4c1b40c7e429fb55a1dac0d678439b364bfd4c..b9575cf70bc5c1b54a1d6422a47ae140a5ce2fdf 100644 (file)
@@ -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>::
index 7ca934eb379c23cb6f43ec00c2e9b7dc5c6192de..3d5ee618c53ee7dfb051b193d59b634a6a084556 100644 (file)
@@ -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
index 36d193fb406b8543a1c2c60f66380349e330d76f..079fff8fdab0eff6cab8653f6c042c3cf715d69d 100644 (file)
@@ -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.
index 5e6c6751bc449bbd86fafd65197da72308552583..8f2c86381779e0f23eab04b87c5cfcf3f26a78c1 100644 (file)
 #include <clocale>
 #include <cstring>
 #include <cassert>
-#include <limits>
-#include <exception>
 #include <locale>
-#include <istream>
-#include <ostream>
 
 namespace std
 {
index 6314ba6a7a57198817b6a2b07595d3d0957a2b5a..641bee21baaad5bc958aec4a0eef823ee7916640 100644 (file)
 #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; }  
index a0c9e75ee8009370dc01334061cd0a0076d7b030..a233eb3ec9dd5be24eafacf9c4ece9dea4abd08e 100644 (file)
@@ -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;
          }
index a27b2457e874245f042f81adf5597caae21af98c..6f4b1bf5cff17ca16fc103cc0344d414834d9774 100644 (file)
@@ -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;
 }
index 431718e783451c7f0fc786ff05ed3f8ac8cd3472..9c613b4c2033564ecb2890207492ebebfc0a9493 100644 (file)
@@ -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;
 }
index 16e856a2ee4c696d91e7a300a180ed4b2aeb3ee8..06b125852c26d031699d2a2e4b19a16aaba74782 100644 (file)
@@ -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;
 }