+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.
-# 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
# 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
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
-TAR = tar
+TAR = gtar
GZIP_ENV = --best
all: all-redirect
.SUFFIXES:
// 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
;;
gnu)
LINKER_MAP=config/linker-map.gnu
+ AC_DEFINE(_GLIBCPP_SYMVER)
;;
esac
;;
gnu)
LINKER_MAP=config/linker-map.gnu
+ AC_DEFINE(_GLIBCPP_SYMVER)
;;
esac
// 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
## Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
## USA.
-
GLIBCPP_3.2 {
global:
# 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*;
};
# Names not in an 'extern' block are mangled names.
+
+ # std::locale destructors
+ _ZNSt6localeD*;
+
+ # std::has_facet*
_ZSt9has_facet*;
# operator new(unsigned)
# operator delete[](void*, std::nothrow_t const&)
_ZdaPvRKSt9nothrow_t;
- # vtable
- _ZTV*;
+ # vtable
+ _ZTV*;
_ZTT*;
# typeinfo
*;
};
-
# Symbols in the support library (libsupc++) have their own tag.
CXXABI_1.2 {
__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
#include <clocale>
+#define _GLIBCPP_NUM_CATEGORIES 0
+
namespace std
{
typedef int* __c_locale;
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>::
}
#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>::
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
#define _GLIBCPP_C_LOCALE_GNU 1
+#define _GLIBCPP_NUM_CATEGORIES 6
+
#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
namespace __gnu_cxx
{
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;
moneypunct<char, true>::_M_initialize_moneypunct(__c_locale __cloc,
const char*)
{
- if (__cloc == _S_c_locale)
+ if (!__cloc)
{
// "C" locale
_M_decimal_point = '.';
moneypunct<char, false>::_M_initialize_moneypunct(__c_locale __cloc,
const char*)
{
- if (__cloc == _S_c_locale)
+ if (!__cloc)
{
// "C" locale
_M_decimal_point = '.';
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'.';
_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;
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'.';
_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)
{
void
numpunct<char>::_M_initialize_numpunct(__c_locale __cloc)
{
- if (__cloc == _S_c_locale)
+ if (!__cloc)
{
// "C" locale
_M_decimal_point = '.';
void
numpunct<wchar_t>::_M_initialize_numpunct(__c_locale __cloc)
{
- if (__cloc == _S_c_locale)
+ if (!__cloc)
{
// "C" locale
_M_decimal_point = L'.';
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>::
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";
}
#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>::
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";
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
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;
;;
gnu)
LINKER_MAP=config/linker-map.gnu
+ cat >> confdefs.h <<\EOF
+#define _GLIBCPP_SYMVER 1
+EOF
+
;;
esac
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
# 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"
# 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"
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
-<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<user-defined-type></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 "C" locales : global locales, termination.
+3. Interacting with "C" 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>
</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>
-===========================
-
-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.
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
- (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".
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
<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
// 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
// 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>
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,
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);
}
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;
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,
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];
__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];
// 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);
};
__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:
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);
}
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
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);
}
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();
// 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();
_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[];
_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;
}
{
_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
codecvt<char, char, mbstate_t>::
~codecvt()
- { }
+ { }
codecvt_base::result
codecvt<char, char, mbstate_t>::
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();
}
{ _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
// 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.
_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
#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.
#include <clocale>
#include <cstring>
#include <cassert>
-#include <limits>
-#include <exception>
#include <locale>
-#include <istream>
-#include <ostream>
namespace std
{
#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;
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
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();
// 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)
{ }
_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");
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()
{
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;
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);
}
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)
{
~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::
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; }
#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;
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()
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.
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.
}
// 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>);
// 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
_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)
// 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;
+ }
}
}
}
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;
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;
}
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)
{
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();
test02();
test03();
+ test04();
return 0;
}
// 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
#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
}
}
+// 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;
}
// 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
#include <cwchar> // for mbstate_t
#include <locale>
+#include <iostream>
#include <testsuite_hooks.h>
typedef std::codecvt<char, char, std::mbstate_t> 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) );
// 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;
}
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)
}
}
- // Expect something more sophisticated eventually.
- if (lhs.version != rhs.version)
+ if (lhs.version_name != rhs.version_name)
{
ret = false;
if (verbose)
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)
{
istringstream iss(size);
int x;
iss >> x;
- if (iss.good())
+ if (!iss.fail())
output.size = x;
input.erase(input.begin(), input.begin() + n + 1);
}
input.erase(input.begin(), input.begin() + n + 1);
// Set version name.
- output.version = input;
+ output.version_name = input;
}
else
{
}
// 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)
{
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;
}
// 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;
}
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
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)
// 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)