+2003-10-02 Benjamin Kosnik <bkoz@redhat.com>
+
+ * config/linker-map.gnu: Export _S_get_c_locale instead of
+ _S_c_locale object.
+
+2003-10-02 Petur Runolfsson <peturr02@ru.is>
+
+ * config/locale/generic/c_locale.cc
+ (category_names, locale::_S_categories): Const qualify.
+ * config/locale/gnu/c_locale.cc: Same.
+ * config/locale/generic/time_members.h (__timepunct::__timepunct):
+ Copy string contents before assigning to _M_name_timepunct,
+ qualify strcpy and strlen with std::.
+ * config/locale/gnu/time_members.h: Same.
+ * config/locale/gnu/messages_members.h (messages::messages):
+ Copy string contents before assigning to _M_name_messages,
+ qualify strcpy and strlen with std::.
+ * config/os/gnu-linux/ctype_noninline.h
+ (ctype<char>::classic_table()): Don't call locale::classic().
+ * include/bits/locale_classes.h
+ (locale::_S_categories): Const qualify.
+ (locale::_S_once, locale::_S_initialize_once,
+ locale::facet::_S_once, locale::facet::_S_initialize_once,
+ locale::facet::_S_get_c_locale): Declare.
+ (locale::_S_initialize): Don't define.
+ (locale::facet::_S_c_locale): Make private.
+ (locale::facet::_S_c_name): Same, const qualify.
+ (locale::_Impl::_Impl(facet**, size_t, bool)): Drop unused
+ parameters, add throw() specifier.
+ * include/bits/locale_facets.h (__timepunct::_M_name_timepunct,
+ messages::_M_name_messages): Const qualify.
+ * src/locale.cc
+ (locale::_S_once, locale::facet::_S_once): Define.
+ (locale::classic): Move initialization code...
+ (locale::_S_initialize_once): ...here.
+ (locale::_S_initialize): Call _S_initialize_once through
+ __gthread_once.
+ (locale::facet::_S_initialize_once): Initialize _S_c_locale.
+ (locale::facet::_S_get_c_locale): Call _S_initialize_once through
+ __gthread_once before returning _S_c_locale.
+ * src/localename.cc (locale::_Impl::_Impl(facet**, size_t, bool)):
+ Drop unused parameters, add throw() specifier, don't initialize
+ locale::facet::_S_c_locale and _S_c_name.
+
+ * config/locale/generic/messages_members.h:
+ Replace _S_c_locale with _S_get_c_locale().
+ * config/locale/gnu/c_locale.cc: Same.
+ * config/locale/gnu/messages_members.h: Same.
+ * config/locale/gnu/numeric_members.cc: Same.
+ * config/locale/gnu/time_members.cc: Same.
+ * config/os/gnu-linux/ctype_noninline.h: Same.
+ * include/bits/locale_facets.h: Same.
+ * include/bits/locale_facets.tcc: Same.
+ * src/codecvt.cc: Same.
+ * src/ctype.cc: Same.
+
2003-10-02 Carlo Wood <carlo@alinoe.com>
* include/bits/demangle.h (demangle<Allocator>::symbol(char const*)):
std::logic_error*;
std::locale::[A-Za-e]*;
std::locale::facet::[A-Za-z]*;
- std::locale::facet::_S_c_locale;
+ std::locale::facet::_S_get_c_locale*;
std::locale::facet::_S_clone_c_locale*;
std::locale::facet::_S_create_c_locale*;
std::locale::facet::_S_destroy_c_locale*;
namespace __gnu_cxx
{
- const char* category_names[6 + _GLIBCXX_NUM_CATEGORIES] =
+ const char* const category_names[6 + _GLIBCXX_NUM_CATEGORIES] =
{
"LC_CTYPE",
"LC_NUMERIC",
namespace std
{
- const char** locale::_S_categories = __gnu_cxx::category_names;
+ const char* const* const locale::_S_categories = __gnu_cxx::category_names;
} // namespace std
template<typename _CharT>
messages<_CharT>::messages(size_t __refs)
: facet(__refs)
- { _M_c_locale_messages = _S_c_locale; }
+ { _M_c_locale_messages = _S_get_c_locale(); }
template<typename _CharT>
messages<_CharT>::messages(__c_locale, const char*, size_t __refs)
: facet(__refs)
- { _M_c_locale_messages = _S_c_locale; }
+ { _M_c_locale_messages = _S_get_c_locale(); }
template<typename _CharT>
typename messages<_CharT>::catalog
size_t __refs)
: facet(__refs), _M_data(NULL)
{
- _M_name_timepunct = new char[strlen(__s) + 1];
- strcpy(_M_name_timepunct, __s);
+ char* __tmp = new char[std::strlen(__s) + 1];
+ std::strcpy(__tmp, __s);
+ _M_name_timepunct = __tmp;
_M_initialize_timepunct(__cloc);
}
void
locale::facet::_S_destroy_c_locale(__c_locale& __cloc)
{
- if (_S_c_locale != __cloc)
+ if (_S_get_c_locale() != __cloc)
__freelocale(__cloc);
}
namespace __gnu_cxx
{
- const char* category_names[6 + _GLIBCXX_NUM_CATEGORIES] =
+ const char* const category_names[6 + _GLIBCXX_NUM_CATEGORIES] =
{
"LC_CTYPE",
"LC_NUMERIC",
namespace std
{
- const char** locale::_S_categories = __gnu_cxx::category_names;
+ const char* const* const locale::_S_categories = __gnu_cxx::category_names;
} // namespace std
#if !(__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2))
_M_name_messages = _S_c_name;
#endif
- _M_c_locale_messages = _S_c_locale;
+ _M_c_locale_messages = _S_get_c_locale();
}
template<typename _CharT>
: facet(__refs)
{
#if !(__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2))
- _M_name_messages = new char[strlen(__s) + 1];
- strcpy(_M_name_messages, __s);
+ char* __tmp = new char[std::strlen(__s) + 1];
+ std::strcpy(__tmp, __s);
+ _M_name_messages = __tmp;
#endif
_M_c_locale_messages = _S_clone_c_locale(__cloc);
}
#if !(__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2))
if (this->_S_c_name != this->_M_name_messages)
delete [] this->_M_name_messages;
- this->_M_name_messages = new char[strlen(__s) + 1];
- strcpy(this->_M_name_messages, __s);
+ char* __tmp = new char[std::strlen(__s) + 1];
+ std::strcpy(__tmp, __s);
+ this->_M_name_messages = __tmp;
#endif
_S_destroy_c_locale(this->_M_c_locale_messages);
_S_create_c_locale(this->_M_c_locale_messages, __s);
_M_data->_M_thousands_sep = L',';
#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
- __c_locale __old = __uselocale(_S_c_locale);
+ __c_locale __old = __uselocale(_S_get_c_locale());
#endif
// Use ctype::widen code without the facet...
unsigned char uc;
if (!__cloc)
{
// "C" locale
- _M_c_locale_timepunct = _S_c_locale;
+ _M_c_locale_timepunct = _S_get_c_locale();
_M_data->_M_date_format = "%m/%d/%y";
_M_data->_M_date_era_format = "%m/%d/%y";
if (!__cloc)
{
// "C" locale
- _M_c_locale_timepunct = _S_c_locale;
+ _M_c_locale_timepunct = _S_get_c_locale();
_M_data->_M_date_format = L"%m/%d/%y";
_M_data->_M_date_era_format = L"%m/%d/%y";
: facet(__refs), _M_data(NULL)
{
#if !(__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2))
- _M_name_timepunct = new char[strlen(__s) + 1];
- strcpy(_M_name_timepunct, __s);
+ char* __tmp = new char[std::strlen(__s) + 1];
+ std::strcpy(__tmp, __s);
+ _M_name_timepunct = __tmp;
#endif
_M_initialize_timepunct(__cloc);
}
#if _GLIBCXX_C_LOCALE_GNU
const ctype_base::mask*
ctype<char>::classic_table() throw()
- {
- locale::classic();
- return _S_c_locale->__ctype_b;
- }
+ { return _S_get_c_locale()->__ctype_b; }
#else
const ctype_base::mask*
ctype<char>::classic_table() throw()
#endif
setlocale(LC_CTYPE, __old);
free(__old);
- _M_c_locale_ctype = _S_c_locale;
+ _M_c_locale_ctype = _S_get_c_locale();
}
#endif
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_get_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;
#endif
setlocale(LC_CTYPE, __old);
free(__old);
- _M_c_locale_ctype = _S_c_locale;
+ _M_c_locale_ctype = _S_get_c_locale();
}
#endif
codecvt_byname(const char* __s, size_t __refs = 0)
: codecvt<_InternT, _ExternT, _StateT>(__refs)
{
- if (this->_M_c_locale_codecvt != this->_S_c_locale)
- _S_destroy_c_locale(this->_M_c_locale_codecvt);
+ _S_destroy_c_locale(this->_M_c_locale_codecvt);
_S_create_c_locale(this->_M_c_locale_codecvt, __s);
}
#include <cstring> // For strcmp.
#include <string>
#include <bits/atomicity.h>
+#include <bits/gthr.h>
namespace std
{
_Impl* _M_impl;
// The "C" reference locale
- static _Impl* _S_classic;
+ static _Impl* _S_classic;
// Current global locale
static _Impl* _S_global;
// 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;
+ static const char* const* const _S_categories;
// Number of standard categories. For C++, these categories are
// collate, ctype, monetary, numeric, time, and messages. These
// and LC_IDENTIFICATION.
static const size_t _S_categories_size = 6 + _GLIBCXX_NUM_CATEGORIES;
+#ifdef __GTHREADS
+ static __gthread_once_t _S_once;
+#endif
+
explicit
locale(_Impl*) throw();
- static inline void
- _S_initialize()
- {
- if (!_S_classic)
- classic();
- }
+ static void
+ _S_initialize();
+
+ static void
+ _S_initialize_once();
static category
_S_normalize_category(category);
mutable _Atomic_word _M_references;
- protected:
// Contains data from the underlying "C" library for the classic locale.
- static __c_locale _S_c_locale;
+ static __c_locale _S_c_locale;
// String literal for the name of the classic locale.
- static char _S_c_name[2];
-
+ static const char _S_c_name[2];
+
+#ifdef __GTHREADS
+ static __gthread_once_t _S_once;
+#endif
+
+ static void
+ _S_initialize_once();
+
+ protected:
explicit
facet(size_t __refs = 0) throw() : _M_references(__refs ? 1 : 0)
{ }
static void
_S_destroy_c_locale(__c_locale& __cloc);
+ // Returns data from the underlying "C" library for the classic locale.
+ static __c_locale
+ _S_get_c_locale();
+
private:
inline void
_M_add_reference() const throw()
_Impl(const _Impl&, size_t);
_Impl(const char*, size_t);
- _Impl(facet**, size_t, bool);
+ _Impl(size_t) throw();
~_Impl() throw();
explicit
collate(size_t __refs = 0)
: facet(__refs)
- { _M_c_locale_collate = _S_c_locale; }
+ { _M_c_locale_collate = _S_get_c_locale(); }
explicit
collate(__c_locale __cloc, size_t __refs = 0)
protected:
__cache_type* _M_data;
__c_locale _M_c_locale_timepunct;
- char* _M_name_timepunct;
+ const char* _M_name_timepunct;
public:
static locale::id id;
// Underlying "C" library locale information saved from
// initialization, needed by messages_byname as well.
__c_locale _M_c_locale_messages;
- char* _M_name_messages;
+ const char* _M_name_messages;
public:
static locale::id id;
unsigned long __ul;
std::__convert_to_v(__xtrc.c_str(), __ul, __err,
- _S_c_locale, __base);
+ _S_get_c_locale(), __base);
if (!(__err & ios_base::failbit) && __ul <= 1)
__v = __ul;
else
string __xtrc;
int __base;
__beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
- std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base);
+ std::__convert_to_v(__xtrc.c_str(), __v, __err,
+ _S_get_c_locale(), __base);
return __beg;
}
int __base;
__beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
unsigned long __ul;
- std::__convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base);
+ std::__convert_to_v(__xtrc.c_str(), __ul, __err,
+ _S_get_c_locale(), __base);
if (!(__err & ios_base::failbit)
&& __ul <= numeric_limits<unsigned short>::max())
__v = static_cast<unsigned short>(__ul);
int __base;
__beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
unsigned long __ul;
- std::__convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base);
+ std::__convert_to_v(__xtrc.c_str(), __ul, __err,
+ _S_get_c_locale(), __base);
if (!(__err & ios_base::failbit)
&& __ul <= numeric_limits<unsigned int>::max())
__v = static_cast<unsigned int>(__ul);
string __xtrc;
int __base;
__beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
- std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base);
+ std::__convert_to_v(__xtrc.c_str(), __v, __err,
+ _S_get_c_locale(), __base);
return __beg;
}
string __xtrc;
int __base;
__beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
- std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base);
+ std::__convert_to_v(__xtrc.c_str(), __v, __err,
+ _S_get_c_locale(), __base);
return __beg;
}
string __xtrc;
int __base;
__beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
- std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base);
+ std::__convert_to_v(__xtrc.c_str(), __v, __err,
+ _S_get_c_locale(), __base);
return __beg;
}
#endif
string __xtrc;
__xtrc.reserve(32);
__beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
- std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale);
+ std::__convert_to_v(__xtrc.c_str(), __v, __err,
+ _S_get_c_locale());
return __beg;
}
string __xtrc;
__xtrc.reserve(32);
__beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
- std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale);
+ std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
return __beg;
}
string __xtrc;
__xtrc.reserve(32);
__beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
- std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale);
+ std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
return __beg;
}
__io.flags(__fmt);
unsigned long __ul;
- std::__convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base);
+ std::__convert_to_v(__xtrc.c_str(), __ul, __err,
+ _S_get_c_locale(), __base);
if (!(__err & ios_base::failbit))
__v = reinterpret_cast<void*>(__ul);
else
_S_format_float(__io, __fbuf, __mod);
__len = std::__convert_from_v(__cs, __cs_size, __fbuf, __v,
- _S_c_locale, __prec);
+ _S_get_c_locale(), __prec);
// If the buffer was not large enough, try again with the correct size.
if (__len >= __cs_size)
__cs_size = __len + 1;
__cs = static_cast<char*>(__builtin_alloca(__cs_size));
__len = std::__convert_from_v(__cs, __cs_size, __fbuf, __v,
- _S_c_locale, __prec);
+ _S_get_c_locale(), __prec);
}
#else
// Consider the possibility of long ios_base::fixed outputs
_S_format_float(__io, __fbuf, __mod);
__len = std::__convert_from_v(__cs, 0, __fbuf, __v,
- _S_c_locale, __prec);
+ _S_get_c_locale(), __prec);
#endif
// [22.2.2.2.2] Stage 2, convert to char_type, using correct
const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
const _CharT* __wcs = __str.c_str();
__ctype.narrow(__wcs, __wcs + __str.size() + 1, char(), __cs);
- std::__convert_to_v(__cs, __units, __err, _S_c_locale);
+ std::__convert_to_v(__cs, __units, __err, _S_get_c_locale());
return __beg;
}
int __cs_size = 64;
char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
int __len = std::__convert_from_v(__cs, __cs_size, "%.01Lf", __units,
- _S_c_locale);
+ _S_get_c_locale());
// If the buffer was not large enough, try again with the correct size.
if (__len >= __cs_size)
{
__cs_size = __len + 1;
__cs = static_cast<char*>(__builtin_alloca(__cs_size));
__len = std::__convert_from_v(__cs, __cs_size, "%.01Lf", __units,
- _S_c_locale);
+ _S_get_c_locale());
}
#else
// max_exponent10 + 1 for the integer part, + 4 for sign, decimal point,
const int __cs_size = numeric_limits<long double>::max_exponent10 + 5;
char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
int __len = std::__convert_from_v(__cs, 0, "%.01Lf", __units,
- _S_c_locale);
+ _S_get_c_locale());
#endif
_CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
* __cs_size));
if (__i == 2 || __i == 4)
{
long __l;
- std::__convert_to_v(__digits.c_str(), __l, __err, _S_c_locale);
+ std::__convert_to_v(__digits.c_str(), __l, __err,
+ _S_get_c_locale());
if (!(__err & ios_base::failbit) && __l <= INT_MAX)
{
__l = __i == 2 ? __l : __l - 1900;
codecvt<char, char, mbstate_t>::
codecvt(size_t __refs)
: __codecvt_abstract_base<char, char, mbstate_t>(__refs)
- { _M_c_locale_codecvt = _S_c_locale; }
+ { _M_c_locale_codecvt = _S_get_c_locale(); }
codecvt<char, char, mbstate_t>::
codecvt(__c_locale __cloc, size_t __refs)
codecvt<wchar_t, char, mbstate_t>::
codecvt(size_t __refs)
: __codecvt_abstract_base<wchar_t, char, mbstate_t>(__refs)
- { _M_c_locale_codecvt = _S_c_locale; }
+ { _M_c_locale_codecvt = _S_get_c_locale(); }
codecvt<wchar_t, char, mbstate_t>::
codecvt(__c_locale __cloc, size_t __refs)
#ifdef _GLIBCXX_USE_WCHAR_T
ctype<wchar_t>::ctype(size_t __refs)
: __ctype_abstract_base<wchar_t>(__refs)
- { _M_c_locale_ctype = _S_c_locale; }
+ { _M_c_locale_ctype = _S_get_c_locale(); }
ctype<wchar_t>::ctype(__c_locale __cloc, size_t __refs)
: __ctype_abstract_base<wchar_t>(__refs)
// static data members of locale.
// These are no longer exported.
- locale::_Impl* locale::_S_classic;
+ locale::_Impl* locale::_S_classic;
locale::_Impl* locale::_S_global;
const size_t locale::_S_categories_size;
+#ifdef __GTHREADS
+ __gthread_once_t locale::_S_once = __GTHREAD_ONCE_INIT;
+#endif
+
// Definitions for static const data members of locale::id
_Atomic_word locale::id::_S_highwater; // init'd to 0 by linker
locale
locale::global(const locale& __other)
{
- // XXX MT
_S_initialize();
+
+ // XXX MT
_Impl* __old = _S_global;
__other._M_impl->_M_add_reference();
_S_global = __other._M_impl;
const locale&
locale::classic()
{
- // Locking protocol: singleton-called-before-threading-starts
- if (!_S_classic)
- {
- try
- {
- // 26 Standard facets, 2 references.
- // 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);
- }
- catch(...)
- {
- // Just call destructor, so that locale_impl_c's memory is
- // not deallocated via a call to delete.
- if (_S_classic)
- _S_classic->~_Impl();
- _S_classic = _S_global = 0;
- __throw_exception_again;
- }
- }
+ _S_initialize();
return c_locale;
}
+ void
+ locale::_S_initialize_once()
+ {
+ // 2 references.
+ // One reference for _S_classic, one for _S_global
+ _S_classic = new (&c_locale_impl) _Impl(2);
+ _S_global = _S_classic;
+ new (&c_locale) locale(_S_classic);
+ }
+
+ void
+ locale::_S_initialize()
+ {
+#ifdef __GTHREADS
+ __gthread_once(&_S_once, _S_initialize_once);
+#else
+ if (!_S_classic)
+ _S_initialize_once();
+#endif
+ }
+
void
locale::_M_coalesce(const locale& __base, const locale& __add,
category __cat)
return __ret;
}
- __c_locale
- locale::facet::_S_c_locale;
-
- char locale::facet::_S_c_name[2];
+ __c_locale locale::facet::_S_c_locale;
+
+ const char locale::facet::_S_c_name[2] = "C";
+
+#ifdef __GTHREADS
+ __gthread_once_t locale::facet::_S_once = __GTHREAD_ONCE_INIT;
+#endif
locale::facet::
~facet() { }
+ void
+ locale::facet::_S_initialize_once()
+ {
+ // Initialize the underlying locale model.
+ _S_create_c_locale(_S_c_locale, _S_c_name);
+ }
+
+ __c_locale
+ locale::facet::_S_get_c_locale()
+ {
+#ifdef __GHTREADS
+ __gthread_once(&_S_once, _S_initialize_once);
+#else
+ if (!_S_c_locale)
+ _S_initialize_once();
+#endif
+ return _S_c_locale;
+ }
+
// Definitions for static const data members of time_base.
template<>
const char*
// Construct "C" _Impl.
locale::_Impl::
- _Impl(facet**, size_t __refs, bool)
+ _Impl(size_t __refs) throw()
: _M_references(__refs), _M_facets_size(_GLIBCXX_NUM_FACETS)
{
- // Initialize the underlying locale model.
- locale::facet::_S_c_name[0] = 'C';
- locale::facet::_S_c_name[1] = '\0';
- locale::facet::_S_create_c_locale(locale::facet::_S_c_locale,
- locale::facet::_S_c_name);
-
_M_facets = new (&facet_vec) const facet*[_M_facets_size];
_M_caches = new (&cache_vec) const facet*[_M_facets_size];
for (size_t __i = 0; __i < _M_facets_size; ++__i)