]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[multiple changes]
authorBenjamin Kosnik <bkoz@gcc.gnu.org>
Thu, 17 Oct 2002 02:04:18 +0000 (02:04 +0000)
committerBenjamin Kosnik <bkoz@gcc.gnu.org>
Thu, 17 Oct 2002 02:04:18 +0000 (02:04 +0000)
2002-10-16  Benjamin Kosnik  <bkoz@redhat.com>

        * include/bits/locale_facets.h (__timepunct::__timepunct): Allocate
        _M_name_timepunct.
        (__timepunct::~__timepunct): Deallocate, remove specialization
        declarations.
        (messages::messages): Allocate _M_name_messages.
        (messages::~messages): Deallocate.
        (messages_byname): Same.
        * config/locale/gnu/time_members.cc (__timepunct::~__timepunct):
        Remove.
        * config/locale/generic/time_members.cc (__timepunct::~__timepunct):
        Remove.

        * docs/html/install.html: Add eqs_MX, en_PH to required locales list.

2002-10-16  Benjamin Kosnik  <bkoz@redhat.com>

* src/globals.cc (__gnu_cxx::c_locale_impl_compat): Add, alias to
c_locale_impl.
* testsuite/abi_check.cc (line_to_symbol_info): Collect size info.
* docs/html/abi.txt: Update.

2002-10-16  Benjamin Kosnik  <bkoz@redhat.com>

* testsuite/22_locale/static_members.cc (test02): Less provincial.

2002-10-16  Benjamin Kosnik  <bkoz@redhat.com>

* testsuite/22_locale/static_members.cc (test02): Disable for
systems without named locale support.
* testsuite/22_locale/ctor_copy_dtor.cc (test04): Don't assume
running the testsuites in "C" environment.
Add new tests.
* docs/html/22_locale/locale.html: Update.

2002-10-16  Benjamin Kosnik  <bkoz@redhat.com>

* testsuite/abi_check.cc (hash<string>): Specialize.
Simplify. Check compatible symbol versions.
* config/linker-map.gnu: Clarify, explicitly export
std::codecvt::c* symbols.

* testsuite/22_locale/static_members.cc (test02): Avoid null strings.

2002-10-16  Benjamin Kosnik  <bkoz@redhat.com>

* testsuite/22_locale/static_members.cc (test02): Fix.

2002-10-16  Benjamin Kosnik  <bkoz@redhat.com>

* acconfig.h (_GLIBCPP_SYMVER): Add.
(_GLIBCPP_ASM_SYMVER): Add.
* acinclude.m4 (GLIBCPP_ENABLE_SYMVERS): Define _GLIBCPP_SYMVER.
* aclocal.m4: Regenerate.
* config.h.in: Regenerate.
* configure: Regenerate.
* include/bits/c++config (_GLIBCPP_AT_AT): Define, as an expedient
hack around m4 issues with quoting '@'.
* src/locale.cc: Use _GLIBCPP_ASM_SYMVER.
* src/globals.cc (__gnu_cxx): Same.

* testsuite/22_locale/ctor_copy_dtor.cc (test04): Fix for

2002-10-16  Benjamin Kosnik  <bkoz@redhat.com>

* config/linker-map.gnu (GLIBCPP_3.2.1): Add.
(GLIBCPP_3.2): Don't export locale::_S_*.
* src/ios.cc: Move globals into __gnu_cxx. Make old exported
symbols match.
* src/locale.cc: Same.
* src/localename.cc: Same.

2002-10-16  Benjamin Kosnik  <bkoz@redhat.com>

* src/locale.cc: Fix comments, move ctors together.
* testsuite/22_locale/static_members.cc (test03): Add.

2002-10-16  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.

From-SVN: r58233

35 files changed:
libstdc++-v3/ChangeLog
libstdc++-v3/Makefile.in
libstdc++-v3/acconfig.h
libstdc++-v3/acinclude.m4
libstdc++-v3/aclocal.m4
libstdc++-v3/config.h.in
libstdc++-v3/config/linker-map.gnu
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/bits/ctype_noninline.h
libstdc++-v3/configure
libstdc++-v3/docs/html/22_locale/locale.html
libstdc++-v3/docs/html/abi.txt
libstdc++-v3/docs/html/install.html
libstdc++-v3/include/bits/c++config
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/ios.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
libstdc++-v3/testsuite/abi_check.cc

index ce3c3a2b0065516094c7f23202fa4470e9e61b1b..30f77dd967104745e3d772843bae25e09e5336f6 100644 (file)
@@ -1,3 +1,145 @@
+2002-10-16  Benjamin Kosnik  <bkoz@redhat.com>
+
+        * include/bits/locale_facets.h (__timepunct::__timepunct): Allocate
+        _M_name_timepunct.
+        (__timepunct::~__timepunct): Deallocate, remove specialization
+        declarations.
+        (messages::messages): Allocate _M_name_messages.
+        (messages::~messages): Deallocate.
+        (messages_byname): Same.
+        * config/locale/gnu/time_members.cc (__timepunct::~__timepunct):
+        Remove.
+        * config/locale/generic/time_members.cc (__timepunct::~__timepunct):
+        Remove.
+
+        * docs/html/install.html: Add eqs_MX, en_PH to required locales list.
+  
+2002-10-16  Benjamin Kosnik  <bkoz@redhat.com>
+
+       * src/globals.cc (__gnu_cxx::c_locale_impl_compat): Add, alias to
+       c_locale_impl.
+       * testsuite/abi_check.cc (line_to_symbol_info): Collect size info.
+       * docs/html/abi.txt: Update.
+
+2002-10-16  Benjamin Kosnik  <bkoz@redhat.com>
+
+       * testsuite/22_locale/static_members.cc (test02): Less provincial.
+
+2002-10-16  Benjamin Kosnik  <bkoz@redhat.com>
+
+       * testsuite/22_locale/static_members.cc (test02): Disable for 
+       systems without named locale support.
+       * testsuite/22_locale/ctor_copy_dtor.cc (test04): Don't assume
+       running the testsuites in "C" environment.
+       Add new tests.
+       * docs/html/22_locale/locale.html: Update.
+
+2002-10-16  Benjamin Kosnik  <bkoz@redhat.com>
+
+       * testsuite/abi_check.cc (hash<string>): Specialize.
+       Simplify. Check compatible symbol versions.
+       * config/linker-map.gnu: Clarify, explicitly export
+       std::codecvt::c* symbols.
+
+       * testsuite/22_locale/static_members.cc (test02): Avoid null strings.
+
+2002-10-16  Benjamin Kosnik  <bkoz@redhat.com>
+
+       * testsuite/22_locale/static_members.cc (test02): Fix.
+
+2002-10-16  Benjamin Kosnik  <bkoz@redhat.com>
+
+       * acconfig.h (_GLIBCPP_SYMVER): Add.
+       (_GLIBCPP_ASM_SYMVER): Add.
+       * acinclude.m4 (GLIBCPP_ENABLE_SYMVERS): Define _GLIBCPP_SYMVER.
+       * aclocal.m4: Regenerate.
+       * config.h.in: Regenerate.
+       * configure: Regenerate.
+       * include/bits/c++config (_GLIBCPP_AT_AT): Define, as an expedient
+       hack around m4 issues with quoting '@'.
+       * src/locale.cc: Use _GLIBCPP_ASM_SYMVER.
+       * src/globals.cc (__gnu_cxx): Same.
+       
+       * testsuite/22_locale/ctor_copy_dtor.cc (test04): Fix for
+
+2002-10-16  Benjamin Kosnik  <bkoz@redhat.com>
+
+       * config/linker-map.gnu (GLIBCPP_3.2.1): Add.
+       (GLIBCPP_3.2): Don't export locale::_S_*. 
+       * src/ios.cc: Move globals into __gnu_cxx. Make old exported
+       symbols match.
+       * src/locale.cc: Same.
+       * src/localename.cc: Same.      
+
+2002-10-16  Benjamin Kosnik  <bkoz@redhat.com> 
+
+       * src/locale.cc: Fix comments, move ctors together.
+       * testsuite/22_locale/static_members.cc (test03): Add.
+
+2002-10-16  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-11  Gabriel Dos Reis  <gdr@integrable-solutions.net>
 
        * include/std/std_limits.h (__glibcpp_char_digits10): Fix Typo.
index 718150791b1d7a3363f6b352491785235b1fd45d..7a427226f11ce4f6cbd3270adb59d4d3edb105f3 100644 (file)
@@ -1,4 +1,4 @@
-# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
+# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
 
 # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
 # This Makefile.in is free software; the Free Software Foundation
@@ -157,7 +157,44 @@ MULTICLEAN = true
 # Work around what appears to be a GNU make bug handling MAKEFLAGS
 # values defined in terms of make variables, as is the case for CC and
 # friends when we are called from the top level Makefile.
-AM_MAKEFLAGS =         "AR_FLAGS=$(AR_FLAGS)"  "CC_FOR_BUILD=$(CC_FOR_BUILD)"  "CC_FOR_TARGET=$(CC_FOR_TARGET)"        "CFLAGS=$(CFLAGS)"      "CXXFLAGS=$(CXXFLAGS)"  "CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)"  "CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)"        "INSTALL=$(INSTALL)"    "INSTALL_DATA=$(INSTALL_DATA)"  "INSTALL_PROGRAM=$(INSTALL_PROGRAM)"    "INSTALL_SCRIPT=$(INSTALL_SCRIPT)"      "LDFLAGS=$(LDFLAGS)"    "LIBCFLAGS=$(LIBCFLAGS)"        "LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)"  "MAKE=$(MAKE)"  "MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)"         "PICFLAG=$(PICFLAG)"    "PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)"      "SHELL=$(SHELL)"        "RUNTESTFLAGS=$(RUNTESTFLAGS)"  "exec_prefix=$(exec_prefix)"    "infodir=$(infodir)"    "libdir=$(libdir)"      "includedir=$(includedir)"      "prefix=$(prefix)"      "tooldir=$(tooldir)"    "AR=$(AR)"      "AS=$(AS)"      "LD=$(LD)"      "LIBCFLAGS=$(LIBCFLAGS)"        "PICFLAG=$(PICFLAG)"    "RANLIB=$(RANLIB)"      "NM=$(NM)"      "NM_FOR_BUILD=$(NM_FOR_BUILD)"  "NM_FOR_TARGET=$(NM_FOR_TARGET)"        "DESTDIR=$(DESTDIR)"    "WERROR=$(WERROR)" 
+AM_MAKEFLAGS = \
+       "AR_FLAGS=$(AR_FLAGS)" \
+       "CC_FOR_BUILD=$(CC_FOR_BUILD)" \
+       "CC_FOR_TARGET=$(CC_FOR_TARGET)" \
+       "CFLAGS=$(CFLAGS)" \
+       "CXXFLAGS=$(CXXFLAGS)" \
+       "CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" \
+       "CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" \
+       "INSTALL=$(INSTALL)" \
+       "INSTALL_DATA=$(INSTALL_DATA)" \
+       "INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
+       "INSTALL_SCRIPT=$(INSTALL_SCRIPT)" \
+       "LDFLAGS=$(LDFLAGS)" \
+       "LIBCFLAGS=$(LIBCFLAGS)" \
+       "LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \
+       "MAKE=$(MAKE)" \
+       "MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \
+       "PICFLAG=$(PICFLAG)" \
+       "PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \
+       "SHELL=$(SHELL)" \
+       "RUNTESTFLAGS=$(RUNTESTFLAGS)" \
+       "exec_prefix=$(exec_prefix)" \
+       "infodir=$(infodir)" \
+       "libdir=$(libdir)" \
+       "includedir=$(includedir)" \
+       "prefix=$(prefix)" \
+       "tooldir=$(tooldir)" \
+       "AR=$(AR)" \
+       "AS=$(AS)" \
+       "LD=$(LD)" \
+       "LIBCFLAGS=$(LIBCFLAGS)" \
+       "PICFLAG=$(PICFLAG)" \
+       "RANLIB=$(RANLIB)" \
+       "NM=$(NM)" \
+       "NM_FOR_BUILD=$(NM_FOR_BUILD)" \
+       "NM_FOR_TARGET=$(NM_FOR_TARGET)" \
+       "DESTDIR=$(DESTDIR)" \
+       "WERROR=$(WERROR)" 
 
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 CONFIG_HEADER = config.h
@@ -169,7 +206,7 @@ mkcheck.in testsuite_flags.in
 
 DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
 
-TAR = tar
+TAR = gtar
 GZIP_ENV = --best
 all: all-redirect
 .SUFFIXES:
index aa0dd99cfa9e25b4efc2a5051b68064f215f067b..777e94a5039a96692710ab30ddf2a4099a467761 100644 (file)
 // Define if you have the copysignf function.
 #undef _GLIBCPP_HAVE_COPYSIGNF
 
+// Define to use symbol versioning in the shared library.
+#undef _GLIBCPP_SYMVER
+
+// Define symbol versioning in assember directives. If symbol
+// versioning is beigng used, and the assembler supports this kind of
+// thing, then use it.
+// NB: _GLIBCPP_AT_AT is a hack to work around quoting issues in m4.
+#if _GLIBCPP_SYMVER
+  #define _GLIBCPP_ASM_SYMVER(cur, old, version) \
+   asm (".symver " #cur "," #old _GLIBCPP_AT_AT #version);
+#else
+  #define _GLIBCPP_ASM_SYMVER(cur, old, version)
+#endif
+
 // Define if mbstate_t exists in wchar.h.
 #undef HAVE_MBSTATE_T
 
index a7ab248aa1ccad1e58cb3f7f74342b6cfb1888ba..a8bfebdc47211631fc0b047e354347cb44357afb 100644 (file)
@@ -2201,6 +2201,7 @@ case $enable_symvers in
       ;;
   gnu)
       LINKER_MAP=config/linker-map.gnu
+      AC_DEFINE(_GLIBCPP_SYMVER)       
       ;;
 esac
 
index abb3ba9f9f298b379d8d98b37662efe40dbaa52d..2dd5fe2dbff2900b9e17cbcea3f181482ea5a9da 100644 (file)
@@ -2213,6 +2213,7 @@ case $enable_symvers in
       ;;
   gnu)
       LINKER_MAP=config/linker-map.gnu
+      AC_DEFINE(_GLIBCPP_SYMVER)       
       ;;
 esac
 
index fcc2c3e2ebf5d033b8cf3edfc5ef156f3de49def..de9f397390afaa247e5eea0dcff52583ec1f957b 100644 (file)
 // Define to use concept checking code from the boost libraries.
 #undef _GLIBCPP_CONCEPT_CHECKS
 
+// Define to use symbol versioning in the shared library.
+#undef _GLIBCPP_SYMVER
+
+// Define symbol versioning in assember directives. If symbol
+// versioning is beigng used, and the assembler supports this kind of
+// thing, then use it.
+// NB: _GLIBCPP_AT_AT is a hack to work around quoting issues in m4.
+#if _GLIBCPP_SYMVER
+  #define _GLIBCPP_ASM_SYMVER(cur, old, version) \
+   asm (".symver " #cur "," #old _GLIBCPP_AT_AT #version);
+#else
+  #define _GLIBCPP_ASM_SYMVER(cur, old, version)
+#endif
+
 // Define if mbstate_t exists in wchar.h.
 #undef HAVE_MBSTATE_T
 
index d4346b1c660eb5311961d3c411353336968d6de3..588ad57fdd867f3dcf032a6b3f13edadba18e2d9 100644 (file)
@@ -20,7 +20,6 @@
 ## Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
 ## USA.
 
-
 GLIBCPP_3.2 {
 
   global:
@@ -29,7 +28,17 @@ GLIBCPP_3.2 {
     # All but the last are terminated with a semicolon.
     extern "C++"
     {
-      std::[A-Za-z]*;
+      std::[A-Za-k]*;
+      std::length_error*;
+      std::logic_error*;
+      std::locale::[A-Za-z]*;
+      std::locale::_[A-Ra-z]*;
+      std::locale::_S_classic;
+      std::locale::_S_global;
+      std::locale::_S_num_categories;
+      std::locale::_S_normalize_category*;
+      std::locale::_[T-Za-z]*;
+      std::[A-Zm-z]*;
       std::__throw_*;
       std::__basic_file*;
       std::__num_base*;
@@ -42,6 +51,11 @@ GLIBCPP_3.2 {
     };
 
     # Names not in an 'extern' block are mangled names.
+
+    # std::locale destructors
+    _ZNSt6localeD*;
+        
+    # std::has_facet*
     _ZSt9has_facet*;
 
     # operator new(unsigned)
@@ -72,8 +86,8 @@ GLIBCPP_3.2 {
     # operator delete[](void*, std::nothrow_t const&)
     _ZdaPvRKSt9nothrow_t;
 
-    # vtable   
-    _ZTV*;  
+    # vtable
+    _ZTV*;
     _ZTT*;
 
     # typeinfo
@@ -95,7 +109,6 @@ GLIBCPP_3.2 {
     *;
 };
 
-
 # Symbols in the support library (libsupc++) have their own tag.
 CXXABI_1.2 {
 
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..fd45645a690cf59d0d63c662c8cfcdf431ee4e03 100644 (file)
 
 namespace std
 {
-  template<>
-    __timepunct<char>::~__timepunct()
-    {
-      if (_M_c_locale_timepunct != _S_c_locale)
-       _S_destroy_c_locale(_M_c_locale_timepunct); 
-    }
-
   template<>
     void
     __timepunct<char>::
@@ -121,13 +114,6 @@ 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); 
-    }
-
   template<>
     void
     __timepunct<wchar_t>::
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..7df10b8ab7162dff7e11eac3e02af203d46a4752 100644 (file)
 
 namespace std
 {
-  template<>
-    __timepunct<char>::~__timepunct()
-    {
-      if (_M_c_locale_timepunct != _S_c_locale)
-       _S_destroy_c_locale(_M_c_locale_timepunct); 
-    }
-
   template<>
     void
     __timepunct<char>::
@@ -67,11 +60,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";
@@ -192,13 +184,6 @@ 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); 
-    }
-
   template<>
     void
     __timepunct<wchar_t>::
@@ -220,11 +205,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 50d041e687a7e849c11b22ab4723eacc3927759b..51f3808247bb0c140bc421de10e5d6414f5760e7 100755 (executable)
@@ -22032,6 +22032,10 @@ case $enable_symvers in
       ;;
   gnu)
       LINKER_MAP=config/linker-map.gnu
+      cat >> confdefs.h <<\EOF
+#define _GLIBCPP_SYMVER 1
+EOF
+       
       ;;
 esac
 
@@ -22046,7 +22050,7 @@ else
   GLIBCPP_BUILD_VERSIONED_SHLIB_FALSE=
 fi
 echo $ac_n "checking versioning on shared library symbols""... $ac_c" 1>&6
-echo "configure:22050: checking versioning on shared library symbols" >&5
+echo "configure:22054: checking versioning on shared library symbols" >&5
 echo "$ac_t""$enable_symvers" 1>&6
 
 
@@ -22134,7 +22138,7 @@ glibcpp_prefixdir=${prefix}
 
 # Process the option --with-gxx-include-dir=<path to include-files directory>
 echo $ac_n "checking for --with-gxx-include-dir""... $ac_c" 1>&6
-echo "configure:22138: checking for --with-gxx-include-dir" >&5
+echo "configure:22142: checking for --with-gxx-include-dir" >&5
 # Check whether --with-gxx-include-dir or --without-gxx-include-dir was given.
 if test "${with_gxx_include_dir+set}" = set; then
   withval="$with_gxx_include_dir"
@@ -22158,7 +22162,7 @@ echo "$ac_t""$gxx_include_dir" 1>&6
 
 # Process the option "--enable-version-specific-runtime-libs"
 echo $ac_n "checking for --enable-version-specific-runtime-libs""... $ac_c" 1>&6
-echo "configure:22162: checking for --enable-version-specific-runtime-libs" >&5
+echo "configure:22166: checking for --enable-version-specific-runtime-libs" >&5
 # Check whether --enable-version-specific-runtime-libs or --disable-version-specific-runtime-libs was given.
 if test "${enable_version_specific_runtime_libs+set}" = set; then
   enableval="$enable_version_specific_runtime_libs"
@@ -22204,7 +22208,7 @@ if test x"$glibcpp_toolexecdir" = x"no"; then
 fi
 
 echo $ac_n "checking for install location""... $ac_c" 1>&6
-echo "configure:22208: checking for install location" >&5
+echo "configure:22212: checking for install location" >&5
 echo "$ac_t""$gxx_include_dir" 1>&6
 
 
index 999e82ed0bd72620bd9d452fe0eee0b2ba534dad..6816204df8f3043865154aba23492aa4dc4b07f3 100644 (file)
@@ -1,8 +1,12 @@
-<html>
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE html
+          PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
 <head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <meta name="AUTHOR" content="bkoz@redhat.com (Benjamin Kosnik)" />
-   <meta name="KEYWORDS" content="HOWTO, libstdc++, GCC, g++, libg++, STL" />
+   <meta name="KEYWORDS" content="HOWTO, libstdc++, locale name LC_ALL" />
    <meta name="DESCRIPTION" content="Notes on the locale implementation." />
    <title>Notes on the locale implementation.</title>
 <link rel="StyleSheet" href="../lib3styles.css" />
   Notes on the locale implementation.
   </h1>
 <em>
-prepared by Benjamin Kosnik (bkoz@redhat.com) on August 8, 2001
+prepared by Benjamin Kosnik (bkoz@redhat.com) on October 14, 2002
 </em>
 
 <h2>
-1. Abstract Describes the basic locale object, including nested
-classes id, facet, and the reference-counted implementation object,
-class _Impl.
+1. Abstract 
 </h2>
 <p>
+Describes the basic locale object, including nested
+classes id, facet, and the reference-counted implementation object,
+class _Impl.
 </p>
 
 <h2>
 2. What the standard says
 </h2>
-See Chapter 22 of the standard.
+Class locale is non-templatized and has two distinct types nested
+inside of it:
+
+<blockquote>
+<em>
+class facet
+22.1.1.1.2 Class locale::facet
+</em>
+</blockquote>
+
+<p>
+Facets actually implement locale functionality. For instance, a facet
+called numpunct is the data objects that can be used to query for the
+thousands separator is in the German locale.
+</p>
+
+Literally, a facet is strictly defined:
+<ul>
+  <li>containing the following public data member:
+  <p>
+  <code>static locale::id id;</code>
+  </p>
+  </li>
+
+  <li>derived from another facet:
+  <p>
+  <code> class gnu_codecvt: public std::ctype&lt;user-defined-type&gt;</code>
+  </p>
+  </li>
+</ul>
+
+<p>
+Of interest in this class are the memory management options explicitly
+specified as an argument to facet's constructor. Each constructor of a
+facet class takes a std::size_t __refs argument: if __refs == 0, the
+facet is deleted when the locale containing it is destroyed. If __refs
+== 1, the facet is not destroyed, even when it is no longer
+referenced.
+</p>
+
+<blockquote>
+<em>
+class id
+22.1.1.1.3 - Class locale::id
+</em>
+</blockquote>
+
+<p>
+Provides an index for looking up specific facets.
+<p>
 
 
 <h2>
-3. Problems with &quot;C&quot; locales : global locales, termination.
+3. Interacting with &quot;C&quot; locales.
 </h2>
 
 <p>
-The major problem is fitting an object-orientated and non-global locale
-design ontop of POSIX and other relevant stanards, which include the
-Single Unix (nee X/Open.)
+Some help on determining the underlying support for locales on a system. 
+Note, this is specific to linux (and glibc-2.3.x)
+</p>
 
-Because POSIX falls down so completely, portibility is an issue.
+<ul>
+   <li> <code>`locale -a`</code> displays available locales. 
+<blockquote>
+<pre>
+af_ZA
+ar_AE
+ar_AE.utf8
+ar_BH
+ar_BH.utf8
+ar_DZ
+ar_DZ.utf8
+ar_EG
+ar_EG.utf8
+ar_IN
+ar_IQ
+ar_IQ.utf8
+ar_JO
+ar_JO.utf8
+ar_KW
+ar_KW.utf8
+ar_LB
+ar_LB.utf8
+ar_LY
+ar_LY.utf8
+ar_MA
+ar_MA.utf8
+ar_OM
+ar_OM.utf8
+ar_QA
+ar_QA.utf8
+ar_SA
+ar_SA.utf8
+ar_SD
+ar_SD.utf8
+ar_SY
+ar_SY.utf8
+ar_TN
+ar_TN.utf8
+ar_YE
+ar_YE.utf8
+be_BY
+be_BY.utf8
+bg_BG
+bg_BG.utf8
+br_FR
+bs_BA
+C
+ca_ES
+ca_ES@euro
+ca_ES.utf8
+ca_ES.utf8@euro
+cs_CZ
+cs_CZ.utf8
+cy_GB
+da_DK
+da_DK.iso885915
+da_DK.utf8
+de_AT
+de_AT@euro
+de_AT.utf8
+de_AT.utf8@euro
+de_BE
+de_BE@euro
+de_BE.utf8
+de_BE.utf8@euro
+de_CH
+de_CH.utf8
+de_DE
+de_DE@euro
+de_DE.utf8
+de_DE.utf8@euro
+de_LU
+de_LU@euro
+de_LU.utf8
+de_LU.utf8@euro
+el_GR
+el_GR.utf8
+en_AU
+en_AU.utf8
+en_BW
+en_BW.utf8
+en_CA
+en_CA.utf8
+en_DK
+en_DK.utf8
+en_GB
+en_GB.iso885915
+en_GB.utf8
+en_HK
+en_HK.utf8
+en_IE
+en_IE@euro
+en_IE.utf8
+en_IE.utf8@euro
+en_IN
+en_NZ
+en_NZ.utf8
+en_PH
+en_PH.utf8
+en_SG
+en_SG.utf8
+en_US
+en_US.iso885915
+en_US.utf8
+en_ZA
+en_ZA.utf8
+en_ZW
+en_ZW.utf8
+es_AR
+es_AR.utf8
+es_BO
+es_BO.utf8
+es_CL
+es_CL.utf8
+es_CO
+es_CO.utf8
+es_CR
+es_CR.utf8
+es_DO
+es_DO.utf8
+es_EC
+es_EC.utf8
+es_ES
+es_ES@euro
+es_ES.utf8
+es_ES.utf8@euro
+es_GT
+es_GT.utf8
+es_HN
+es_HN.utf8
+es_MX
+es_MX.utf8
+es_NI
+es_NI.utf8
+es_PA
+es_PA.utf8
+es_PE
+es_PE.utf8
+es_PR
+es_PR.utf8
+es_PY
+es_PY.utf8
+es_SV
+es_SV.utf8
+es_US
+es_US.utf8
+es_UY
+es_UY.utf8
+es_VE
+es_VE.utf8
+et_EE
+et_EE.utf8
+eu_ES
+eu_ES@euro
+eu_ES.utf8
+eu_ES.utf8@euro
+fa_IR
+fi_FI
+fi_FI@euro
+fi_FI.utf8
+fi_FI.utf8@euro
+fo_FO
+fo_FO.utf8
+fr_BE
+fr_BE@euro
+fr_BE.utf8
+fr_BE.utf8@euro
+fr_CA
+fr_CA.utf8
+fr_CH
+fr_CH.utf8
+fr_FR
+fr_FR@euro
+fr_FR.utf8
+fr_FR.utf8@euro
+fr_LU
+fr_LU@euro
+fr_LU.utf8
+fr_LU.utf8@euro
+ga_IE
+ga_IE@euro
+ga_IE.utf8
+ga_IE.utf8@euro
+gl_ES
+gl_ES@euro
+gl_ES.utf8
+gl_ES.utf8@euro
+gv_GB
+gv_GB.utf8
+he_IL
+he_IL.utf8
+hi_IN
+hr_HR
+hr_HR.utf8
+hu_HU
+hu_HU.utf8
+id_ID
+id_ID.utf8
+is_IS
+is_IS.utf8
+it_CH
+it_CH.utf8
+it_IT
+it_IT@euro
+it_IT.utf8
+it_IT.utf8@euro
+iw_IL
+iw_IL.utf8
+ja_JP.eucjp
+ja_JP.utf8
+ka_GE
+kl_GL
+kl_GL.utf8
+ko_KR.euckr
+ko_KR.utf8
+kw_GB
+kw_GB.utf8
+lt_LT
+lt_LT.utf8
+lv_LV
+lv_LV.utf8
+mi_NZ
+mk_MK
+mk_MK.utf8
+mr_IN
+ms_MY
+ms_MY.utf8
+mt_MT
+mt_MT.utf8
+nl_BE
+nl_BE@euro
+nl_BE.utf8
+nl_BE.utf8@euro
+nl_NL
+nl_NL@euro
+nl_NL.utf8
+nl_NL.utf8@euro
+nn_NO
+nn_NO.utf8
+no_NO
+no_NO.utf8
+oc_FR
+pl_PL
+pl_PL.utf8
+POSIX
+pt_BR
+pt_BR.utf8
+pt_PT
+pt_PT@euro
+pt_PT.utf8
+pt_PT.utf8@euro
+ro_RO
+ro_RO.utf8
+ru_RU
+ru_RU.koi8r
+ru_RU.utf8
+ru_UA
+ru_UA.utf8
+se_NO
+sk_SK
+sk_SK.utf8
+sl_SI
+sl_SI.utf8
+sq_AL
+sq_AL.utf8
+sr_YU
+sr_YU@cyrillic
+sr_YU.utf8
+sr_YU.utf8@cyrillic
+sv_FI
+sv_FI@euro
+sv_FI.utf8
+sv_FI.utf8@euro
+sv_SE
+sv_SE.iso885915
+sv_SE.utf8
+ta_IN
+te_IN
+tg_TJ
+th_TH
+th_TH.utf8
+tl_PH
+tr_TR
+tr_TR.utf8
+uk_UA
+uk_UA.utf8
+ur_PK
+uz_UZ
+vi_VN
+vi_VN.tcvn
+wa_BE
+wa_BE@euro
+yi_US
+zh_CN
+zh_CN.gb18030
+zh_CN.gbk
+zh_CN.utf8
+zh_HK
+zh_HK.utf8
+zh_TW
+zh_TW.euctw
+zh_TW.utf8
+</pre>
+</blockquote>
+</li>
+   
+   <li> <code>`locale`</code> displays environmental variables
+   that impact how locale("") will be deduced.
+
+<blockquote>
+<pre>
+LANG=en_US
+LC_CTYPE="en_US"
+LC_NUMERIC="en_US"
+LC_TIME="en_US"
+LC_COLLATE="en_US"
+LC_MONETARY="en_US"
+LC_MESSAGES="en_US"
+LC_PAPER="en_US"
+LC_NAME="en_US"
+LC_ADDRESS="en_US"
+LC_TELEPHONE="en_US"
+LC_MEASUREMENT="en_US"
+LC_IDENTIFICATION="en_US"
+LC_ALL=
+</pre>
+</blockquote>
+</li>
+</ul>
+
+<p>
+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:
 </p>
+    <code>std::locale::global(std::locale(""));</code>
 
-<h2>
-4. Design
-</h2>
-Class locale in non-templatized and has three distinct types nested
-inside of it:
+<p>affects the C functions as if the following call was made:</p>
 
-class facet
-22.1.1.1.2 Class locale::facet
+    <code>std::setlocale(LC_ALL, "");</code>
 
-Facets actually implement locale functionality. For instance, a facet
-called numpunct is the data objects that can be used to query for the
-thousands separator is in the German locale.
+<p>
+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.
+</p>
 
-Literally, a facet is strictly defined:
- - containing 
-public:
-  static locale::id id;
 
-- or derived from another facet
+<h2>
+4. Design
+</h2>
 
-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.
 
+<p>
+The major design challenge is fitting an object-orientated and
+non-global locale design ontop of POSIX and other relevant stanards,
+which include the Single Unix (nee X/Open.)
+</p>
 
-class id
-Provides an index for looking up specific facets.
+<p>
+Because POSIX falls down so completely, portibility is an issue.
+</p>
 
 class _Impl
+The internal representation of the std::locale object.
+
 
 <h2>
 5.  Examples
 </h2>
 
-<pre>
-  typedef __locale_t locale;
-</pre>
-
 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>
@@ -92,8 +476,6 @@ More information can be found in the following testcases:
 </h2>
 
 <ul>
-   <li> locale -a displays available locales on linux </li>
-
    <li> locale initialization: at what point does _S_classic,
    _S_global get initialized? Can named locales assume this
    initialization has already taken place? </li>
index 770c3cf59740b9732f8ae04fa8e5caf3177adf42..73cb46c9c099dee1c276a9add90ac499538831f8 100644 (file)
@@ -1,12 +1,5 @@
 
-===========================
-
-See http://gcc.gnu.org/ml/libstdc++/2002-07/msg00054.html for why this
-document exists, why it's incomplete, and what needs to be done still.
-
-===========================
-
-2002-09-06 Benjamin Kosnik
+2002-10-14 Benjamin Kosnik
 
 Description of the libstdc++ ABI.
 
@@ -244,7 +237,7 @@ II. Library ABI changes
 The following will cause the library major version number to
 increase, say from "libstdc++.so.3.0.4" to "libstdc++.so.4.0.0".
 
-- any g++ compiler ABI changes
+- (anything) changing in the gcc/g++ compiler ABI
 
 - (anything) changing size of an exported symbol
 
@@ -256,7 +249,14 @@ increase, say from "libstdc++.so.3.0.4" to "libstdc++.so.4.0.0".
 
 - (anything) deleting an exported symbol
 
-Note: adding an exported symbol, if it's in a new linker map name, is ok.
+- (anything) changing the size, alignment, or layout of types
+  specified in the C++ standard. These may not necessarily be
+  instantiated or otherwise exported in the library binary, and
+  include all the required locale facets, as well as things like
+  std::basic_streambuf, et al.
+
+Note: adding an exported symbol, if it's in a new and dependent
+interface name, is ok.
 
 The following will cause the library revision version number to
 increase, say from "libstdc++.so.5.0.0" to "libstdc++.so.5.0.1".
@@ -331,17 +331,20 @@ addition, all exported names are demangled, and the exported objects
 are checked to make sure they are the same size as the same object in
 the baseline.
 
-In the future, more tests should be added. In particular, vtable
-information, offsets of data members in class objects, and other
-layout information should be checked.
+This dataset is insufficient, yet a start. Also needed is a
+comprehensive check for all user-visible types part of the standard
+library for sizeof() and alignof() changes. 
 
-It should be possible to use sizeof, alignof, and offset to compute
+Verifying compatible layouts of objects is not even attempted.  It
+should be possible to use sizeof, alignof, and offsetof to compute
 offsets for each structure and type in the standard library, saving to
-another datafile. Then, compute this for new binaries, and look for
-differences.
+another datafile. Then, compute this in a similar way for new
+binaries, and look for differences.
 
 Another approach might be to use the -fdump-class-hierarchy flag to
-get information.
+get information. However, currently this approach gives insufficient
+data for use in library testing, as class data members, their offsets,
+and other detailed data is not displayed with this flag.
 (See g++/7470 on how this was used to find bugs.)
 
 Perhaps there are other C++ ABI checkers. If so, please notify
index 20e2a0a366bd48a4a92f80d3d8d83e99d4ddd900..f91e6c7f2d71a2b5beaf6c8cf87b16fe2331fbcc 100644 (file)
       <p>
       If the 'gnu' locale model is being used, the following locales
       are used and tested in the libstdc++ testsuites: en_HK, en_US,
-      fr_FR, fr_FR@euro, de_DE, de_DE@euro, ja_JP.eucjp, and
-      it_IT. Failure to have the underlying "C" library locale
+      fr_FR, fr_FR@euro, de_DE, de_DE@euro, ja_JP.eucjp, es_MX, en_PH,
+      and it_IT. Failure to have the underlying "C" library locale
       information installed will mean that C++ named locales for the
       above regions will not work: because of this, the libstdc++
       testsuite will not pass the named locale tests. If this isn't an
index 840f1ee76f53c711f80bcea9b27e62a2cdf938c6..611038f64170c4b67913c3be3a661d19ee2033e3 100644 (file)
@@ -55,6 +55,9 @@
 // Use corrected code from the committee library group's issues list.
 #define _GLIBCPP_RESOLVE_LIB_DEFECTS 1
 
+// Hopefully temporary workaround to autoconf/m4 issue with quoting '@'.
+#define _GLIBCPP_AT_AT "@@"
+
 // In those parts of the standard C++ library that use a mutex instead
 // of a spin-lock, we now unconditionally use GCC's gthr.h mutex
 // abstraction layer.  All support to directly map to various
index f99562fac49eb41f6c98bb5d3129ddac79f60714..660bad3c11a939459c4290ee4cfc33756c32abc6 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); 
       }
 
@@ -956,7 +952,7 @@ namespace std
 
     protected:
       __c_locale                       _M_c_locale_timepunct;
-      const char*                      _M_name_timepunct;
+      char*                            _M_name_timepunct;
       const _CharT*                    _M_date_format;
       const _CharT*                    _M_date_era_format;
       const _CharT*                    _M_time_format;
@@ -1016,13 +1012,21 @@ namespace std
     public:
       explicit 
       __timepunct(size_t __refs = 0) 
-      : locale::facet(__refs), _M_name_timepunct("C")
-      { _M_initialize_timepunct(); }
+      : locale::facet(__refs)
+      { 
+       _M_name_timepunct = new char[2];
+       strcpy(_M_name_timepunct, "C");
+       _M_initialize_timepunct(); 
+      }
 
       explicit 
       __timepunct(__c_locale __cloc, const char* __s, size_t __refs = 0) 
-      : locale::facet(__refs), _M_name_timepunct(__s)
-      { _M_initialize_timepunct(__cloc); }
+      : locale::facet(__refs)
+      { 
+       _M_name_timepunct = new char[strlen(__s) + 1];
+       strcpy(_M_name_timepunct, __s);
+       _M_initialize_timepunct(__cloc); 
+      }
 
       void
       _M_put(_CharT* __s, size_t __maxlen, const _CharT* __format, 
@@ -1119,20 +1123,21 @@ namespace std
 
     protected:
       virtual 
-      ~__timepunct();
+      ~__timepunct()
+      { 
+       delete [] _M_name_timepunct;
+       _S_destroy_c_locale(_M_c_locale_timepunct); 
+      }
 
       // 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>
     locale::id __timepunct<_CharT>::id;
 
   // Specializations.
-  template<>
-    __timepunct<char>::~__timepunct();
-
   template<> 
     const char*
     __timepunct<char>::_S_timezones[14];
@@ -1146,9 +1151,6 @@ namespace std
     __timepunct<char>::_M_put(char*, size_t, const char*, const tm*) const;
 
 #ifdef _GLIBCPP_USE_WCHAR_T
-  template<>
-    __timepunct<wchar_t>::~__timepunct();
-
   template<> 
     const wchar_t*
     __timepunct<wchar_t>::_S_timezones[14];
@@ -1459,7 +1461,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);
     };
 
@@ -1628,7 +1630,7 @@ namespace std
       __c_locale                       _M_c_locale_messages;
 #if 1
       // Only needed if glibc < 2.3
-      const char*                      _M_name_messages;
+      char*                            _M_name_messages;
 #endif
 
     public:
@@ -1636,15 +1638,20 @@ namespace std
 
       explicit 
       messages(size_t __refs = 0) 
-      : locale::facet(__refs), _M_name_messages("C")
-      { _M_c_locale_messages = _S_c_locale; }
+      : locale::facet(__refs)
+      { 
+       _M_name_messages = new char[2];
+       strcpy(_M_name_messages, "C");
+       _M_c_locale_messages = _S_c_locale; 
+      }
 
       // Non-standard.
       explicit 
-      messages(__c_locale __cloc, const char* __name, size_t __refs = 0) 
+      messages(__c_locale __cloc, const char* __s, size_t __refs = 0) 
       : locale::facet(__refs)
       { 
-       _M_name_messages = __name;
+       _M_name_messages = new char[strlen(__s) + 1];
+       strcpy(_M_name_messages, __s);
        _M_c_locale_messages = _S_clone_c_locale(__cloc); 
       }
 
@@ -1668,8 +1675,8 @@ namespace std
       virtual 
       ~messages()
        { 
-        if (_M_c_locale_messages != _S_c_locale)
-          _S_destroy_c_locale(_M_c_locale_messages); 
+        delete [] _M_name_messages;
+        _S_destroy_c_locale(_M_c_locale_messages); 
        }
 
       virtual catalog 
@@ -1758,9 +1765,10 @@ namespace std
       messages_byname(const char* __s, size_t __refs = 0)
       : messages<_CharT>(__refs) 
       { 
-       _M_name_messages = __s;
-       if (_M_c_locale_messages != _S_c_locale)
-         _S_destroy_c_locale(_M_c_locale_messages);
+       delete [] _M_name_messages;
+       _M_name_messages = new char[strlen(__s) + 1];
+       strcpy(_M_name_messages, __s);
+       _S_destroy_c_locale(_M_c_locale_messages);
        _S_create_c_locale(_M_c_locale_messages, __s); 
       }
 
index 028c4126b85e1152b14a2e48830bba0a576bc313..d8d742b4c592db5812a3d84fe7e44a6d7153b97a 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 a2fb42d96919e54285055eb26537eb00fca8b052..1fe6b97bc6d02b01124519cf281457ffe2721176 100644 (file)
@@ -50,7 +50,7 @@ namespace std
 
   codecvt<char, char, mbstate_t>::
   ~codecvt()
-   { }
+  { }
   
   codecvt_base::result
   codecvt<char, 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..c6ff69c5e811b7ac74cf7bcae19a43a153fac469 100644 (file)
 // Because <iostream> declares the standard streams to be [io]stream
 // types instead of say [io]fstream types, it is also necessary to
 // allocate the actual file buffers in this file.
-namespace std 
+namespace __gnu_cxx
 {
-  // Standard "C" locale.
-  typedef char fake_locale[sizeof(locale)]
-  __attribute__ ((aligned(__alignof__(locale))));
-  fake_locale c_locale;
+  using namespace std;
+
+  typedef char fake_facet_name[sizeof(char*)]
+  __attribute__ ((aligned(__alignof__(char*))));
+  fake_facet_name facet_name[6 + _GLIBCPP_NUM_CATEGORIES];
 
   typedef char fake_locale_Impl[sizeof(locale::_Impl)]
   __attribute__ ((aligned(__alignof__(locale::_Impl))));
   fake_locale_Impl c_locale_impl;
-  
+
+
+  // NB: The asm directives renames these non-exported, namespace
+  // __gnu_cxx symbols into the mistakenly exported, namespace std
+  // symbols in GLIBCPP_3.2.
+  // The rename syntax is 
+  //   asm (".symver currentname,oldname@@GLIBCPP_3.2")
+  // At the same time, these new __gnu_cxx symbols are not exported.
+  // In the future, GLIBCXX_ABI > 5 should remove all uses of
+  // _GLIBCPP_ASM_SYMVER in this file.
+  typedef char fake_locale[sizeof(locale)]
+  __attribute__ ((aligned(__alignof__(locale))));
+  fake_locale c_locale;
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx8c_localeE, _ZSt8c_locale, GLIBCPP_3.2)
+
+  // GLIBCXX_ABI > 5 will not need this symbol at all.
+  // It's here just as a placeholder, as the size of this exported
+  // object changed. The new symbol is not exported.
+  const int o = sizeof(locale::_Impl) - sizeof(char*[_GLIBCPP_NUM_CATEGORIES]);
+  typedef char fake_locale_Impl_compat[o]
+  __attribute__ ((aligned(__alignof__(o))));
+  fake_locale_Impl_compat  c_locale_impl_compat;
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx20c_locale_impl_compatE, _ZSt13c_locale_impl, GLIBCPP_3.2)
+
   typedef char fake_facet_vec[sizeof(locale::facet*)]
   __attribute__ ((aligned(__alignof__(locale::facet*))));
   fake_facet_vec facet_vec[_GLIBCPP_NUM_FACETS];
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx9facet_vecE, _ZSt9facet_vec, GLIBCPP_3.2)
 
   typedef char fake_ctype_c[sizeof(std::ctype<char>)]
   __attribute__ ((aligned(__alignof__(std::ctype<char>))));
   fake_ctype_c ctype_c;
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx7ctype_cE, _ZSt7ctype_c, GLIBCPP_3.2)
 
   typedef char fake_collate_c[sizeof(std::collate<char>)]
   __attribute__ ((aligned(__alignof__(std::collate<char>))));
   fake_collate_c collate_c;
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx9collate_cE, _ZSt9collate_c, GLIBCPP_3.2)
 
   typedef char fake_numpunct_c[sizeof(numpunct<char>)]
   __attribute__ ((aligned(__alignof__(numpunct<char>))));
   fake_numpunct_c numpunct_c;
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx10numpunct_cE, _ZSt10numpunct_c, GLIBCPP_3.2)
 
   typedef char fake_num_get_c[sizeof(num_get<char>)]
   __attribute__ ((aligned(__alignof__(num_get<char>))));
   fake_num_get_c num_get_c;
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx9num_get_cE, _ZSt9num_get_c, GLIBCPP_3.2)
 
   typedef char fake_num_put_c[sizeof(num_put<char>)]
   __attribute__ ((aligned(__alignof__(num_put<char>))));
   fake_num_put_c num_put_c;
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx9num_put_cE, _ZSt9num_put_c, GLIBCPP_3.2)
 
   typedef char fake_codecvt_c[sizeof(codecvt<char, char, mbstate_t>)]
   __attribute__ ((aligned(__alignof__(codecvt<char, char, mbstate_t>))));
   fake_codecvt_c codecvt_c;
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx9codecvt_cE, _ZSt9codecvt_c, GLIBCPP_3.2)
 
   typedef char fake_moneypunct_c[sizeof(moneypunct<char, true>)]
   __attribute__ ((aligned(__alignof__(moneypunct<char, true>))));
   fake_moneypunct_c moneypunct_tc;
   fake_moneypunct_c moneypunct_fc;
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx13moneypunct_tcE,\
+        _ZSt13moneypunct_tc, GLIBCPP_3.2)
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx13moneypunct_fcE,\
+        _ZSt13moneypunct_fc, GLIBCPP_3.2)
 
   typedef char fake_money_get_c[sizeof(money_get<char>)]
   __attribute__ ((aligned(__alignof__(money_get<char>))));
   fake_money_get_c money_get_c;
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx11money_get_cE, _ZSt11money_get_c, GLIBCPP_3.2)
   
   typedef char fake_money_put_c[sizeof(money_put<char>)]
   __attribute__ ((aligned(__alignof__(money_put<char>))));
   fake_money_put_c money_put_c;
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx11money_put_cE, _ZSt11money_put_c, GLIBCPP_3.2)
 
   typedef char fake_timepunct_c[sizeof(__timepunct<char>)]
   __attribute__ ((aligned(__alignof__(__timepunct<char>))));
   fake_timepunct_c timepunct_c;
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx11timepunct_cE, _ZSt11timepunct_c, GLIBCPP_3.2)
 
   typedef char fake_time_get_c[sizeof(time_get<char>)]
   __attribute__ ((aligned(__alignof__(time_get<char>))));
   fake_time_get_c time_get_c;
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx10time_get_cE, _ZSt10time_get_c, GLIBCPP_3.2)
 
   typedef char fake_time_put_c[sizeof(time_put<char>)]
   __attribute__ ((aligned(__alignof__(time_put<char>))));
   fake_time_put_c time_put_c;
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx10time_put_cE, _ZSt10time_put_c, GLIBCPP_3.2)
 
   typedef char fake_messages_c[sizeof(messages<char>)]
   __attribute__ ((aligned(__alignof__(messages<char>))));
   fake_messages_c messages_c;
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx10messages_cE, _ZSt10messages_c, GLIBCPP_3.2)
 
 #ifdef  _GLIBCPP_USE_WCHAR_T
   typedef char fake_wtype_w[sizeof(std::ctype<wchar_t>)]
   __attribute__ ((aligned(__alignof__(std::ctype<wchar_t>))));
   fake_wtype_w ctype_w;
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx7ctype_wE, _ZSt7ctype_w, GLIBCPP_3.2)
 
   typedef char fake_wollate_w[sizeof(std::collate<wchar_t>)]
   __attribute__ ((aligned(__alignof__(std::collate<wchar_t>))));
   fake_wollate_w collate_w;
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx9collate_wE, _ZSt9collate_w, GLIBCPP_3.2)
 
   typedef char fake_numpunct_w[sizeof(numpunct<wchar_t>)]
   __attribute__ ((aligned(__alignof__(numpunct<wchar_t>))));
   fake_numpunct_w numpunct_w;
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx10numpunct_wE, _ZSt10numpunct_w, GLIBCPP_3.2)
 
   typedef char fake_num_get_w[sizeof(num_get<wchar_t>)]
   __attribute__ ((aligned(__alignof__(num_get<wchar_t>))));
   fake_num_get_w num_get_w;
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx9num_get_wE, _ZSt9num_get_w, GLIBCPP_3.2)
 
   typedef char fake_num_put_w[sizeof(num_put<wchar_t>)]
   __attribute__ ((aligned(__alignof__(num_put<wchar_t>))));
   fake_num_put_w num_put_w;
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx9num_put_wE, _ZSt9num_put_w, GLIBCPP_3.2)
 
   typedef char fake_wodecvt_w[sizeof(codecvt<wchar_t, char, mbstate_t>)]
   __attribute__ ((aligned(__alignof__(codecvt<wchar_t, char, mbstate_t>))));
   fake_wodecvt_w codecvt_w;
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx9codecvt_wE, _ZSt9codecvt_w, GLIBCPP_3.2)
 
   typedef char fake_moneypunct_w[sizeof(moneypunct<wchar_t, true>)]
   __attribute__ ((aligned(__alignof__(moneypunct<wchar_t, true>))));
   fake_moneypunct_w moneypunct_tw;
   fake_moneypunct_w moneypunct_fw;
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx13moneypunct_twE,\
+        _ZSt13moneypunct_tw, GLIBCPP_3.2)
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx13moneypunct_fwE,\
+        _ZSt13moneypunct_fw, GLIBCPP_3.2)
 
   typedef char fake_money_get_w[sizeof(money_get<wchar_t>)]
   __attribute__ ((aligned(__alignof__(money_get<wchar_t>))));
   fake_money_get_w money_get_w;
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx11money_get_wE, _ZSt11money_get_w, GLIBCPP_3.2)
   
   typedef char fake_money_put_w[sizeof(money_put<wchar_t>)]
   __attribute__ ((aligned(__alignof__(money_put<wchar_t>))));
   fake_money_put_w money_put_w;
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx11money_put_wE, _ZSt11money_put_w, GLIBCPP_3.2)
 
   typedef char fake_timepunct_w[sizeof(__timepunct<wchar_t>)]
   __attribute__ ((aligned(__alignof__(__timepunct<wchar_t>))));
   fake_timepunct_w timepunct_w;
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx11timepunct_wE, _ZSt11timepunct_w, GLIBCPP_3.2)
 
   typedef char fake_time_get_w[sizeof(time_get<wchar_t>)]
   __attribute__ ((aligned(__alignof__(time_get<wchar_t>))));
   fake_time_get_w time_get_w;
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx10time_get_wE, _ZSt10time_get_w, GLIBCPP_3.2)
 
   typedef char fake_time_put_w[sizeof(time_put<wchar_t>)]
   __attribute__ ((aligned(__alignof__(time_put<wchar_t>))));
   fake_time_put_w time_put_w;
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx10time_put_wE, _ZSt10time_put_w, GLIBCPP_3.2)
 
   typedef char fake_messages_w[sizeof(messages<wchar_t>)]
   __attribute__ ((aligned(__alignof__(messages<wchar_t>))));
   fake_messages_w messages_w;
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx10messages_wE, _ZSt10messages_w, GLIBCPP_3.2)
 #endif
 
-  // Standard stream objects.
-  typedef char fake_istream[sizeof(istream)]
-  __attribute__ ((aligned(__alignof__(istream))));
-  typedef char fake_ostream[sizeof(ostream)] 
-  __attribute__ ((aligned(__alignof__(ostream))));
-  fake_istream cin;
-  fake_ostream cout;
-  fake_ostream cerr;
-  fake_ostream clog;
-
-  typedef char fake_filebuf[sizeof(__gnu_cxx::stdio_filebuf<char>)]
-  __attribute__ ((aligned(__alignof__(__gnu_cxx::stdio_filebuf<char>))));
+  typedef char fake_filebuf[sizeof(stdio_filebuf<char>)]
+  __attribute__ ((aligned(__alignof__(stdio_filebuf<char>))));
   fake_filebuf buf_cout;
   fake_filebuf buf_cin;
   fake_filebuf buf_cerr;
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx8buf_coutE, _ZSt8buf_cout, GLIBCPP_3.2)
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx7buf_cinE, _ZSt7buf_cin, GLIBCPP_3.2)
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx8buf_cerrE, _ZSt8buf_cerr, GLIBCPP_3.2)
 
 #ifdef _GLIBCPP_USE_WCHAR_T
-  typedef char fake_wistream[sizeof(wistream)] 
-  __attribute__ ((aligned(__alignof__(wistream))));
-  typedef char fake_wostream[sizeof(wostream)] 
-  __attribute__ ((aligned(__alignof__(wostream))));
-  fake_wistream wcin;
-  fake_wostream wcout;
-  fake_wostream wcerr;
-  fake_wostream wclog;
-
-  typedef char fake_wfilebuf[sizeof(__gnu_cxx::stdio_filebuf<wchar_t>)]
-  __attribute__ ((aligned(__alignof__(__gnu_cxx::stdio_filebuf<wchar_t>))));
+  typedef char fake_wfilebuf[sizeof(stdio_filebuf<wchar_t>)]
+  __attribute__ ((aligned(__alignof__(stdio_filebuf<wchar_t>))));
   fake_wfilebuf buf_wcout;
   fake_wfilebuf buf_wcin;
   fake_wfilebuf buf_wcerr;
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx9buf_wcoutE, _ZSt9buf_wcout, GLIBCPP_3.2)
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx8buf_wcinE, _ZSt8buf_wcin, GLIBCPP_3.2)
+  _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx9buf_wcerrE, _ZSt9buf_wcerr, GLIBCPP_3.2)
 #endif
+} // namespace __gnu_cxx
 
-
+namespace std
+{
   // 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.
@@ -223,4 +269,25 @@ namespace std
   _GLIBCPP_mutex_address_init ()
   { __GTHREAD_MUTEX_INIT_FUNCTION (_GLIBCPP_mutex_address); }
 #endif
-}
+
+  // Standard stream objects.
+  typedef char fake_istream[sizeof(istream)]
+  __attribute__ ((aligned(__alignof__(istream))));
+  typedef char fake_ostream[sizeof(ostream)] 
+  __attribute__ ((aligned(__alignof__(ostream))));
+  fake_istream cin;
+  fake_ostream cout;
+  fake_ostream cerr;
+  fake_ostream clog;
+
+#ifdef _GLIBCPP_USE_WCHAR_T
+  typedef char fake_wistream[sizeof(wistream)] 
+  __attribute__ ((aligned(__alignof__(wistream))));
+  typedef char fake_wostream[sizeof(wostream)] 
+  __attribute__ ((aligned(__alignof__(wostream))));
+  fake_wistream wcin;
+  fake_wostream wcout;
+  fake_wostream wcerr;
+  fake_wostream wclog;
+#endif
+} // namespace std
index c1167f8c15cf6ee8f2cfe7ac7267bd59d4a754a1..7bfdc5b4bb4095cbb03e88f20e4b69527dce569c 100644 (file)
 #include <bits/atomicity.h>
 #include <ext/stdio_filebuf.h>
 
-namespace std 
+namespace __gnu_cxx
 {
   // Extern declarations for global objects in src/globals.cc.
+  extern stdio_filebuf<char> buf_cout;
+  extern stdio_filebuf<char> buf_cin;
+  extern stdio_filebuf<char> buf_cerr;
+
+#ifdef _GLIBCPP_USE_WCHAR_T
+  extern stdio_filebuf<wchar_t> buf_wcout;
+  extern stdio_filebuf<wchar_t> buf_wcin;
+  extern stdio_filebuf<wchar_t> buf_wcerr;
+#endif
+} // namespace __gnu_cxx
+
+namespace std 
+{
+  using namespace __gnu_cxx;
+  
   extern istream cin;
   extern ostream cout;
   extern ostream cerr;
   extern ostream clog;
 
-  using __gnu_cxx::stdio_filebuf;
-  extern stdio_filebuf<char> buf_cout;
-  extern stdio_filebuf<char> buf_cin;
-  extern stdio_filebuf<char> buf_cerr;
-
 #ifdef _GLIBCPP_USE_WCHAR_T
   extern wistream wcin;
   extern wostream wcout;
   extern wostream wcerr;
   extern wostream wclog;
-
-  extern stdio_filebuf<wchar_t> buf_wcout;
-  extern stdio_filebuf<wchar_t> buf_wcin;
-  extern stdio_filebuf<wchar_t> buf_wcerr;
 #endif
 
   // Definitions for static const data members of __ios_flags.
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..127197d0138f4d3494fc66162e6230735499bda4 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 
+namespace __gnu_cxx
 {
   // Defined in globals.cc.
-  extern locale                c_locale;
-  extern locale::_Impl                 c_locale_impl;
-  extern locale::facet**       facet_vec;
+  extern std::locale           c_locale;
+  extern std::locale::_Impl    c_locale_impl;
+} // namespace __gnu_cxx
+
+namespace std 
+{
+  using namespace __gnu_cxx;
 
   // Definitions for static const data members of locale.
   const locale::category       locale::none;
@@ -55,9 +55,14 @@ namespace std
   const locale::category       locale::messages;
   const locale::category       locale::all;
 
+  // In the future, GLIBCXX_ABI > 5 should remove all uses of
+  // _GLIBCPP_ASM_SYMVER in this file, and remove exports of any
+  // static data members of locale.
   locale::_Impl*               locale::_S_classic;
   locale::_Impl*               locale::_S_global; 
-  const size_t                         locale::_S_num_categories;
+  const size_t                         locale::_S_categories_size;
+  _GLIBCPP_ASM_SYMVER(_ZNSt6locale18_S_categories_sizeE, _ZNSt6locale17_S_num_categoriesE, GLIBCPP_3.2)
+  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,31 +151,12 @@ 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
   };
 
-  locale::~locale() throw()
-  { _M_impl->_M_remove_reference(); }
-
-  void
-  locale::_M_coalesce(const locale& __base, const locale& __add, 
-                     category __cat)
-  {
-    __cat = _S_normalize_category(__cat);  
-    _M_impl = new _Impl(*__base._M_impl, 1);  
-
-    try 
-      { _M_impl->_M_replace_categories(__add._M_impl, __cat); }
-    catch (...) 
-      { 
-       _M_impl->_M_remove_reference(); 
-       __throw_exception_again;
-      }
-  }
-
   locale::locale() throw()
   { 
     _S_initialize(); 
@@ -182,6 +168,7 @@ namespace std
 
   // This is used to initialize global and classic locales, and
   // assumes that the _Impl objects are constructed correctly.
+  // The lack of a reference increment is intentional.
   locale::locale(_Impl* __ip) throw() : _M_impl(__ip)
   { }
 
@@ -192,18 +179,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");
@@ -221,6 +300,9 @@ namespace std
   locale::locale(const locale& __base, const locale& __add, category __cat)
   { _M_coalesce(__base, __add, __cat); }
 
+  locale::~locale() throw()
+  { _M_impl->_M_remove_reference(); }
+
   bool
   locale::operator==(const locale& __rhs) const throw()
   {
@@ -261,20 +343,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;
@@ -291,12 +375,8 @@ namespace std
        try 
          {
            // 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);
+           // One reference for _S_classic, one for _S_global
+           _S_classic = new (&c_locale_impl) _Impl(0, 2, true);
            _S_global = _S_classic;         
            new (&c_locale) locale(_S_classic);
          }
@@ -313,6 +393,22 @@ namespace std
     return c_locale;
   }
 
+  void
+  locale::_M_coalesce(const locale& __base, const locale& __add, 
+                     category __cat)
+  {
+    __cat = _S_normalize_category(__cat);  
+    _M_impl = new _Impl(*__base._M_impl, 1);  
+
+    try 
+      { _M_impl->_M_replace_categories(__add._M_impl, __cat); }
+    catch (...) 
+      { 
+       _M_impl->_M_remove_reference(); 
+       __throw_exception_again;
+      }
+  }
+
   locale::category
   locale::_S_normalize_category(category __cat) 
   {
@@ -361,11 +457,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 +469,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 8fa911891705aad7dfab3ff7627c02f5731def3c..61aa952e6ad2e7277c242317588f41bb899fda92 100644 (file)
 #include <cstring>
 #include <locale>
 
-namespace std
+namespace __gnu_cxx
 {
+  using 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;
@@ -63,6 +68,11 @@ namespace std
   extern time_put<wchar_t>                     time_put_w;
   extern std::messages<wchar_t>                messages_w;
 #endif
+} // namespace __gnu_cxx
+
+namespace std
+{
+  using namespace __gnu_cxx;
 
   locale::_Impl::
   ~_Impl() throw()
@@ -71,6 +81,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 +109,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 +141,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>);
     _M_init_facet(new numpunct<char>(__cloc));
     _M_init_facet(new num_get<char>);
@@ -162,47 +210,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 +272,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 +282,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 +317,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 +335,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..8ffef6e34e1e1fb12f234c565901306d72817b10 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,183 @@ void test03()
 {
   bool test = true;
 #ifdef _GLIBCPP_HAVE_SETENV 
-  const char* oldLANG = getenv("LANG");
-  if (!setenv("LANG", "it_IT", 1))
+  const char* LC_ALL_orig = 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", LC_ALL_orig ? LC_ALL_orig : "", 1);
     }
 #endif
 }
 
+
+// More tests for locale("") == POSIX locale::name. 
+void test04()
+{
+  bool test = true;
+  using namespace std;
+
+#ifdef _GLIBCPP_HAVE_SETENV
+
+  const char* LANG_orig = getenv("LANG") ? strdup(getenv("LANG")) : "";
+  const char* LC_ALL_orig = getenv("LC_ALL") ? strdup(getenv("LC_ALL")) : "";
+  const char* LC_CTYPE_orig = 
+    getenv("LC_CTYPE") ? strdup(getenv("LC_CTYPE")) : "";
+  const char* LC_NUMERIC_orig = 
+    getenv("LC_NUMERIC") ? strdup(getenv("LC_NUMERIC")) : "";
+  const char* LC_COLLATE_orig =
+    getenv("LC_COLLATE") ? strdup(getenv("LC_COLLATE")) : "";
+  const char* LC_TIME_orig = 
+    getenv("LC_TIME") ? strdup(getenv("LC_TIME")) : "";
+  const char* LC_MONETARY_orig = 
+    getenv("LC_MONETARY") ? strdup(getenv("LC_MONETARY")) : "";
+  const char* LC_MESSAGES_orig = 
+    getenv("LC_MESSAGES") ? strdup(getenv("LC_MESSAGES")) : "";
+#if _GLIBCPP_NUM_CATEGORIES
+  const char* LC_PAPER_orig = 
+    getenv("LC_PAPER") ? strdup(getenv("LC_PAPER")) : "";
+  const char* LC_NAME_orig = 
+    getenv("LC_NAME") ? strdup(getenv("LC_NAME")) : "";
+  const char* LC_ADDRESS_orig = 
+    getenv("LC_ADDRESS") ? strdup(getenv("LC_ADDRESS")) : "";
+  const char* LC_TELEPHONE_orig = 
+    getenv("LC_TELEPHONE") ? strdup(getenv("LC_TELEPHONE")) : "";
+  const char* LC_MEASUREMENT_orig = 
+    getenv("LC_MEASUREMENT") ? strdup(getenv("LC_MEASUREMENT")) : "";
+  const char* LC_IDENTIFICATION_orig =
+    getenv("LC_IDENTIFICATION") ? strdup(getenv("LC_IDENTIFICATION")) : "";
+#endif
+
+  // Check that a "POSIX" LC_ALL is equivalent to "C".
+  if (!setenv("LC_ALL", "POSIX", 1))
+    {
+      locale loc("");
+      VERIFY( loc.name() == "C" );
+    }
+  setenv("LC_ALL", "", 1);
+
+  // Check that a "en_PH" LC_ALL is equivalent to "en_PH".
+  if (!setenv("LC_ALL", "en_PH", 1))
+    {
+      locale loc("");
+      VERIFY( loc.name() == "en_PH" );
+    }
+  setenv("LC_ALL", "", 1);
+
+  // Explicit check that LC_ALL sets regardless of LC_* and LANG.
+  if (!setenv("LANG", "es_MX", 1) && !setenv("LC_COLLATE", "de_DE", 1))
+    {
+      if (!setenv("LC_ALL", "en_PH", 1))
+       {
+         locale loc("");
+         VERIFY( loc.name() == "en_PH" );
+       }
+      setenv("LC_ALL", "", 1);
+      setenv("LANG", LANG_orig ? LANG_orig : "", 1);
+      setenv("LC_COLLATE", LC_COLLATE_orig ? LC_COLLATE_orig : "", 1);
+    }
+
+  // NB: LANG checks all LC_* macro settings. As such, all LC_* macros
+  // must be cleared for these tests, and then restored.
+  setenv("LC_ALL", "", 1);
+  setenv("LC_CTYPE", "", 1);
+  setenv("LC_NUMERIC", "", 1);
+  setenv("LC_COLLATE", "", 1);
+  setenv("LC_TIME", "", 1);
+  setenv("LC_MONETARY", "", 1);
+  setenv("LC_MESSAGES", "", 1);
+#if _GLIBCPP_NUM_CATEGORIES
+  setenv("LC_PAPER", "", 1);
+  setenv("LC_NAME", "", 1);
+  setenv("LC_ADDRESS", "", 1);
+  setenv("LC_TELEPHONE", "", 1);
+  setenv("LC_MEASUREMENT", "", 1);
+  setenv("LC_IDENTIFICATION", "", 1);
+#endif
+
+  // Check the default set by LANG.
+  if (!setenv("LANG", "fr_FR", 1))
+    {
+      locale loc("");
+      VERIFY( loc.name() == "fr_FR" );
+    }
+
+  // Check that a "POSIX" LANG is equivalent to "C".
+  if (!setenv("LANG", "POSIX", 1))
+    {
+      locale loc(""); 
+      VERIFY( loc.name() == "C" );
+    }
+
+  // Setting a category in the "C" default.
+  if (!setenv("LC_COLLATE", "de_DE", 1))
+    {
+      locale loc("");
+
+#if _GLIBCPP_NUM_CATEGORIES
+      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" );
+#else
+      VERIFY( loc.name() == "LC_CTYPE=C;LC_NUMERIC=C;LC_COLLATE=de_DE;"
+             "LC_TIME=C;LC_MONETARY=C;LC_MESSAGES=C" );
+#endif
+    }
+
+  // Changing the LANG default while LC_COLLATE is set.
+  if (!setenv("LANG", "fr_FR", 1))
+    {
+      locale loc("");
+#if _GLIBCPP_NUM_CATEGORIES
+      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" );
+#else
+      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" );
+#endif
+    }
+  
+  // Changing another (C only) category.
+#if _GLIBCPP_NUM_CATEGORIES
+  if (!setenv("LC_IDENTIFICATION", "it_IT", 1))
+    {
+      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" );
+    }
+#endif
+
+  // Restore the environment.
+  setenv("LANG", LANG_orig ? LANG_orig : "", 1);
+  setenv("LC_ALL", LC_ALL_orig ? LC_ALL_orig : "", 1);
+  setenv("LC_CTYPE", LC_CTYPE_orig ? LC_CTYPE_orig : "", 1);
+  setenv("LC_NUMERIC", LC_NUMERIC_orig ? LC_NUMERIC_orig : "", 1);
+  setenv("LC_COLLATE", LC_COLLATE_orig ? LC_COLLATE_orig : "", 1);
+  setenv("LC_TIME", LC_TIME_orig ? LC_TIME_orig : "", 1);
+  setenv("LC_MONETARY", LC_MONETARY_orig ? LC_MONETARY_orig : "", 1);
+  setenv("LC_MESSAGES", LC_MESSAGES_orig ? LC_MESSAGES_orig : "", 1);
+#if _GLIBCPP_NUM_CATEGORIES
+  setenv("LC_PAPER", LC_PAPER_orig ? LC_PAPER_orig : "", 1);
+  setenv("LC_NAME", LC_NAME_orig ? LC_NAME_orig : "", 1);
+  setenv("LC_ADDRESS", LC_ADDRESS_orig ? LC_ADDRESS_orig : "", 1);
+  setenv("LC_TELEPHONE", LC_TELEPHONE_orig ? LC_TELEPHONE_orig : "", 1);
+  setenv("LC_MEASUREMENT", LC_MEASUREMENT_orig ? LC_MEASUREMENT_orig : "", 1);
+  setenv("LC_IDENTIFICATION", 
+         LC_IDENTIFICATION_orig ? LC_IDENTIFICATION_orig : "", 1);
+#endif
+
+#endif
+}
+
 int main()
 {
   test00();
@@ -335,6 +502,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..9811dd9a8067dfea65742de8a0b86bc44b3e3eb0 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,6 +22,7 @@
 
 #include <cwchar> // for mbstate_t
 #include <locale>
+#include <iostream>
 #include <testsuite_hooks.h>
 
 typedef std::codecvt<char, char, std::mbstate_t> ccodecvt;
@@ -30,14 +31,15 @@ class gnu_codecvt: public ccodecvt { };
 void test01()
 {
   using namespace std;
-
   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 loc01 = locale::classic();
+
+  // Construct a locale object with the specialized facet.
+  locale loc02(locale::classic(), new gnu_codecvt);
   VERIFY ( loc01 != loc02 );
   VERIFY ( !(loc01 == loc02) );
 
@@ -50,15 +52,143 @@ void test01()
   // global
   locale loc03;
   VERIFY ( loc03 == loc01);
-  locale loc04 = locale::global(loc02);
+  locale global_orig = locale::global(loc02);
   locale loc05;
   VERIFY (loc05 != loc03);
   VERIFY (loc05 == loc02);
+
+  // Reset global settings.
+  locale::global(global_orig);
+}
+
+// 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 char* orig = setlocale(LC_ALL, NULL);
+  const char* testph = setlocale(LC_ALL, ph.c_str());
+  const char* testmx = setlocale(LC_ALL, mx.c_str());
+  setlocale(LC_ALL, orig);
+
+  // If the underlying locale doesn't support these names, setlocale
+  // won't be reset. Therefore, disable unless we know these specific
+  // named locales work.
+  if (testph && testmx)
+    {
+      const locale loc_ph(ph.c_str());
+      const locale loc_mx(mx.c_str());
+      
+      // Use setlocale between two calls to locale("")
+      const locale loc_env_1("");
+      setlocale(LC_ALL, ph.c_str());
+      const locale loc_env_2("");
+      VERIFY( loc_env_1 == loc_env_2 );
+      
+      // Change global locale.
+      locale global_orig = locale::global(loc_mx);
+      const char* lc_all_mx = setlocale(LC_ALL, NULL);
+      if (lc_all_mx)
+       {
+         cout << "lc_all_mx is " << lc_all_mx << endl;
+         VERIFY( mx == lc_all_mx );
+       }
+      
+      // Restore global settings.
+      locale::global(global_orig);
+    }
+}
+
+// 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;
+
+// Verify lifetimes of global objects.
+void test03()
+{
+  using namespace std;
+  bool test = true;
+
+  string name;
+  locale global_orig;
+  // 1: Destroyed when out of scope.
+  {
+    {
+      {
+       VERIFY( counter == 0 );
+       {
+         locale loc01(locale::classic(), new facet_type);
+         VERIFY( counter == 1 );
+         global_orig = locale::global(loc01);
+         name = loc01.name();
+       }
+       VERIFY( counter == 1 );
+       locale loc02 = locale();
+       // Weak, but it's something...
+       VERIFY( loc02.name() == name );
+      }
+      VERIFY( counter == 1 );
+      // NB: loc03 should be a copy of the previous global locale.
+      locale loc03 = locale::global(global_orig);
+      VERIFY( counter == 1 );
+      VERIFY( loc03.name() == name );
+    }
+    VERIFY( counter == 0 );
+    locale loc04 = locale();
+    VERIFY( loc04 == global_orig );
+  }
+
+  // 2: Not destroyed when out of scope, deliberately leaked.
+  {
+    {
+      {
+       VERIFY( counter == 0 );
+       {
+         locale loc01(locale::classic(), new facet_type(1));
+         VERIFY( counter == 1 );
+         global_orig = locale::global(loc01);
+         name = loc01.name();
+       }
+       VERIFY( counter == 1 );
+       locale loc02 = locale();
+       // Weak, but it's something...
+       VERIFY( loc02.name() == name );
+      }
+      VERIFY( counter == 1 );
+      // NB: loc03 should be a copy of the previous global locale.
+      locale loc03 = locale::global(global_orig);
+      VERIFY( counter == 1 );
+      VERIFY( loc03.name() == name );
+    }
+    VERIFY( counter == 1 );
+    locale loc04 = locale();
+    VERIFY( loc04 == global_orig );
+  }
+  VERIFY( counter == 1 );
+
+  // Restore global settings.
+  locale::global(global_orig);
 }
 
 int main ()
 {
   test01();
+  test02();
 
+  test03();
   return 0;
 }
index 1e407811437a3cf479f2f2e40d0ba046d4b53e53..21ca619ca83f278e4823ceeaffe614d514455652 100644 (file)
@@ -46,17 +46,35 @@ struct symbol_info
   enum category { none, function, object, error };
   category     type;
   std::string  name;
-  std::string  name_demangled;
-  std::string  version;
+  std::string  demangled_name;
   int          size;
+  std::string  version_name;
 
   symbol_info() : type(none), size(0) { }
 
   symbol_info(const symbol_info& other) 
-  : type(other.type), name(other.name), name_demangled(other.name_demangled), 
-  version(other.version), size(other.size) { }
+  : type(other.type), name(other.name), demangled_name(other.demangled_name), 
+   size(other.size), version_name(other.version_name) { }
 };
 
+namespace __gnu_cxx
+{
+  using namespace std;
+
+  template<> 
+    struct hash<string>
+    {
+      size_t operator()(const string& s) const 
+      { 
+       const collate<char>& c = use_facet<collate<char> >(locale::classic());
+       return c.hash(s.c_str(), s.c_str() + s.size());
+      }
+    }; 
+}
+
+typedef std::deque<std::string>                                symbol_names;
+typedef __gnu_cxx::hash_map<std::string, symbol_info>  symbol_infos;
+
 bool 
 check_compatible(const symbol_info& lhs, const symbol_info& rhs, 
                 bool verbose = false)
@@ -93,8 +111,7 @@ check_compatible(const symbol_info& lhs, const symbol_info& rhs,
        }
     }
 
-  // Expect something more sophisticated eventually.
-  if (lhs.version != rhs.version)
+  if (lhs.version_name != rhs.version_name)
     {
       ret = false;
       if (verbose)
@@ -106,19 +123,6 @@ check_compatible(const symbol_info& lhs, const symbol_info& rhs,
   return ret;
 }
 
-template<typename _CharT, typename _Traits>
-  std::basic_ostream<_CharT, _Traits>&
-  operator<<(std::basic_ostream<_CharT, _Traits>& os, symbol_info& si)
-  {
-    using namespace std;
-    os << si.type << endl;
-    os << si.name << endl;
-    os << si.name_demangled << endl;
-    os << si.version << endl;
-    os << si.size << endl;
-    return os;
-  }
 const char*
 demangle(const std::string& mangled)
 {
@@ -187,7 +191,7 @@ line_to_symbol_info(std::string& input, symbol_info& output)
          istringstream iss(size);
          int x;
          iss >> x;
-         if (iss.good())
+         if (!iss.fail())
            output.size = x;
          input.erase(input.begin(), input.begin() + n + 1);
        }
@@ -203,7 +207,7 @@ line_to_symbol_info(std::string& input, symbol_info& output)
       input.erase(input.begin(), input.begin() + n + 1);
 
       // Set version name.
-      output.version = input;
+      output.version_name = input;
     }
   else
     {
@@ -213,12 +217,9 @@ line_to_symbol_info(std::string& input, symbol_info& output)
     }
 
   // Set the demangled name.
-  output.name_demangled = demangle(output.name);
+  output.demangled_name = demangle(output.name);
 }
 
-typedef std::deque<std::string>                                symbol_names;
-typedef __gnu_cxx::hash_map<const char*, symbol_info>  symbol_infos;
-
 void
 create_symbol_data(const char* file, symbol_infos& symbols, 
                   symbol_names& names)
@@ -238,7 +239,7 @@ create_symbol_data(const char* file, symbol_infos& symbols,
        {
          symbol_info symbol;
          line_to_symbol_info(line, symbol);
-         symbols[symbol.name.c_str()] = symbol;
+         symbols[symbol.name] = symbol;
          names.push_back(symbol.name);
          line = empty;
        }
@@ -256,7 +257,7 @@ report_symbol_info(const symbol_info& symbol, std::size_t n)
 
   // Add any other information to display here.
   cout << tab << "demangled symbol"<< endl;
-  cout << tab << symbol.name_demangled << endl;
+  cout << tab << symbol.demangled_name << endl;
 
   cout << endl;
 }
@@ -279,10 +280,10 @@ main(int argc, char** argv)
       exit(1);
     }
 
+
+  // Quick sanity/setup check for arguments.
   const char* test_file = argv[2];
   const char* baseline_file = argv[3];
-
-  // Quick sanity/setup check
   if (access(test_file, R_OK) != 0)
     {
       cerr << "Cannot read symbols file " << test_file
@@ -303,7 +304,7 @@ main(int argc, char** argv)
   create_symbol_data(baseline_file, baseline_symbols, baseline_names);
   create_symbol_data(test_file, test_symbols, test_names);
 
-  // More sanity checking.
+  //  Sanity check results.
   const symbol_names::size_type baseline_size = baseline_names.size();
   const symbol_names::size_type test_size = test_names.size();
   if (!baseline_size || !test_size)
@@ -315,53 +316,71 @@ main(int argc, char** argv)
   // Sort out names.
   // Assuming baseline_names, test_names are both unique w/ no duplicates.
   //
-  // The pairs of names in shared_names are needed to do lookups on
-  // the hash tables of common symbols to do compares.
-  //
   // The names added to missing_names are baseline_names not found in
   // test_names 
   // -> symbols that have been deleted.
   //
-  // The names left in test_names are names not in baseline_names
+  // The names added to added_names are test_names are names not in
+  // baseline_names
   // -> symbols that have been added.
-  typedef pair<string, string> string_pair;
-  vector<string_pair> shared_names;
+  symbol_names shared_names;
   symbol_names missing_names;
+  symbol_names added_names = test_names;
   for (size_t i = 0; i < baseline_size; ++i)
     {
-      symbol_names::iterator end = test_names.end();
-      symbol_names::iterator it = find(test_names.begin(), end, 
-                                      baseline_names[i]);
+      string what(baseline_names[i]);
+      symbol_names::iterator end = added_names.end();
+      symbol_names::iterator it = find(added_names.begin(), end, what);
       if (it != end)
        {
          // Found.
-         shared_names.push_back(string_pair(baseline_names[i], *it));
-         test_names.erase(it);
+         shared_names.push_back(what);
+         added_names.erase(it);
        }
       else
-       missing_names.push_back(baseline_names[i]);
+       missing_names.push_back(what);
     }
 
-  // Check common names for detailed compatibility.
-  const vector<string_pair>::size_type shared_size = shared_names.size();
+  // Check shared names for compatibility.
   typedef pair<symbol_info, symbol_info> symbol_pair;
   vector<symbol_pair> incompatible;
-  for (size_t i = 0; i < shared_size; ++i)
+  for (size_t i = 0; i < shared_names.size(); ++i)
     {
-      symbol_info base = baseline_symbols[shared_names[i].first.c_str()];
-      symbol_info test = test_symbols[shared_names[i].second.c_str()];
+      symbol_info base = baseline_symbols[shared_names[i]];
+      symbol_info test = test_symbols[shared_names[i]];
       if (!check_compatible(base, test))
        incompatible.push_back(symbol_pair(base, test));
     }
 
+  // Check added names for compatibility.
+  for (size_t i = 0; i < added_names.size(); ++i)
+    {
+      vector<string> compatible_versions;
+      compatible_versions.push_back("GLIBCPP_3.2.1");
+
+      symbol_info test = test_symbols[added_names[i]];
+      vector<string>::iterator end = compatible_versions.end();
+
+      // Check version names for compatibility...
+      vector<string>::iterator it1 = find(compatible_versions.begin(), end, 
+                                         test.version_name);
+
+      // Check for weak label.
+      vector<string>::iterator it2 = find(compatible_versions.begin(), end, 
+                                         test.name);
+
+      if (it1 == end && it2 == end)
+       incompatible.push_back(symbol_pair(test, test));
+    }
+
   // Report results.
-  cout << test_names.size() << " added symbols " << endl;
-  for (size_t j = 0; j < test_names.size() ; ++j)
-    report_symbol_info(test_symbols[test_names[j].c_str()], j + 1);
+  cout << added_names.size() << " added symbols " << endl;
+  for (size_t j = 0; j < added_names.size() ; ++j)
+    report_symbol_info(test_symbols[added_names[j]], j + 1);
 
   cout << missing_names.size() << " missing symbols " << endl;
   for (size_t j = 0; j < missing_names.size() ; ++j)
-    report_symbol_info(baseline_symbols[missing_names[j].c_str()], j + 1);
+    report_symbol_info(baseline_symbols[missing_names[j]], j + 1);
 
   cout << incompatible.size() << " incompatible symbols " << endl;
   for (size_t j = 0; j < incompatible.size() ; ++j)