197403Sobrien// Wrapper for underlying C-language localization -*- C++ -*-
297403Sobrien
3169691Skan// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006
4169691Skan// Free Software Foundation, Inc.
597403Sobrien//
697403Sobrien// This file is part of the GNU ISO C++ Library.  This library is free
797403Sobrien// software; you can redistribute it and/or modify it under the
897403Sobrien// terms of the GNU General Public License as published by the
997403Sobrien// Free Software Foundation; either version 2, or (at your option)
1097403Sobrien// any later version.
1197403Sobrien
1297403Sobrien// This library is distributed in the hope that it will be useful,
1397403Sobrien// but WITHOUT ANY WARRANTY; without even the implied warranty of
1497403Sobrien// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1597403Sobrien// GNU General Public License for more details.
1697403Sobrien
1797403Sobrien// You should have received a copy of the GNU General Public License along
1897403Sobrien// with this library; see the file COPYING.  If not, write to the Free
19169691Skan// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
2097403Sobrien// USA.
2197403Sobrien
2297403Sobrien// As a special exception, you may use this file as part of a free software
2397403Sobrien// library without restriction.  Specifically, if other files instantiate
2497403Sobrien// templates or use macros or inline functions from this file, or you compile
2597403Sobrien// this file and link it with other files to produce an executable, this
2697403Sobrien// file does not by itself cause the resulting executable to be covered by
2797403Sobrien// the GNU General Public License.  This exception does not however
2897403Sobrien// invalidate any other reasons why the executable file might be covered by
2997403Sobrien// the GNU General Public License.
3097403Sobrien
3197403Sobrien//
3297403Sobrien// ISO C++ 14882: 22.8  Standard locale categories.
3397403Sobrien//
3497403Sobrien
3597403Sobrien// Written by Benjamin Kosnik <bkoz@redhat.com>
3697403Sobrien
37132720Skan#include <cerrno>  // For errno
3897403Sobrien#include <locale>
3997403Sobrien#include <stdexcept>
4097403Sobrien#include <langinfo.h>
41117397Skan#include <bits/c++locale_internal.h>
4297403Sobrien
43169691Skan_GLIBCXX_BEGIN_NAMESPACE(std)
44169691Skan
4597403Sobrien  template<>
4697403Sobrien    void
4797403Sobrien    __convert_to_v(const char* __s, float& __v, ios_base::iostate& __err,
48132720Skan		   const __c_locale& __cloc)
4997403Sobrien    {
50169691Skan      char* __sanity;
51169691Skan      errno = 0;
52169691Skan      float __f = __strtof_l(__s, &__sanity, __cloc);
53169691Skan      if (__sanity != __s && errno != ERANGE)
54169691Skan	__v = __f;
55169691Skan      else
56169691Skan	__err |= ios_base::failbit;
5797403Sobrien    }
5897403Sobrien
5997403Sobrien  template<>
6097403Sobrien    void
6197403Sobrien    __convert_to_v(const char* __s, double& __v, ios_base::iostate& __err,
62132720Skan		   const __c_locale& __cloc)
6397403Sobrien    {
64169691Skan      char* __sanity;
65169691Skan      errno = 0;
66169691Skan      double __d = __strtod_l(__s, &__sanity, __cloc);
67169691Skan      if (__sanity != __s && errno != ERANGE)
68169691Skan	__v = __d;
69169691Skan      else
70169691Skan	__err |= ios_base::failbit;
7197403Sobrien    }
7297403Sobrien
7397403Sobrien  template<>
7497403Sobrien    void
7597403Sobrien    __convert_to_v(const char* __s, long double& __v, ios_base::iostate& __err,
76132720Skan		   const __c_locale& __cloc)
7797403Sobrien    {
78169691Skan      char* __sanity;
79169691Skan      errno = 0;
80169691Skan#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
81169691Skan      // Prefer strtold_l, as __strtold_l isn't prototyped in more recent
82169691Skan      // glibc versions.
83169691Skan      long double __ld = strtold_l(__s, &__sanity, __cloc);
84169691Skan#else
85169691Skan      long double __ld = __strtold_l(__s, &__sanity, __cloc);
86169691Skan#endif
87169691Skan      if (__sanity != __s && errno != ERANGE)
88169691Skan	__v = __ld;
89169691Skan      else
90169691Skan	__err |= ios_base::failbit;
9197403Sobrien    }
9297403Sobrien
9397403Sobrien  void
9497403Sobrien  locale::facet::_S_create_c_locale(__c_locale& __cloc, const char* __s,
9597403Sobrien				    __c_locale __old)
9697403Sobrien  {
9797403Sobrien    __cloc = __newlocale(1 << LC_ALL, __s, __old);
9897403Sobrien    if (!__cloc)
9997403Sobrien      {
10097403Sobrien	// This named locale is not supported by the underlying OS.
101132720Skan	__throw_runtime_error(__N("locale::facet::_S_create_c_locale "
102132720Skan			      "name not valid"));
10397403Sobrien      }
10497403Sobrien  }
10597403Sobrien
10697403Sobrien  void
10797403Sobrien  locale::facet::_S_destroy_c_locale(__c_locale& __cloc)
108107606Sobrien  {
109169691Skan    if (__cloc && _S_get_c_locale() != __cloc)
110107606Sobrien      __freelocale(__cloc);
111107606Sobrien  }
11297403Sobrien
11397403Sobrien  __c_locale
11497403Sobrien  locale::facet::_S_clone_c_locale(__c_locale& __cloc)
11597403Sobrien  { return __duplocale(__cloc); }
116107606Sobrien
117169691Skan_GLIBCXX_END_NAMESPACE
118169691Skan
119169691Skan_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
120169691Skan
121132720Skan  const char* const category_names[6 + _GLIBCXX_NUM_CATEGORIES] =
122107606Sobrien    {
123107606Sobrien      "LC_CTYPE",
124117397Skan      "LC_NUMERIC",
125117397Skan      "LC_TIME",
126107606Sobrien      "LC_COLLATE",
127107606Sobrien      "LC_MONETARY",
128107606Sobrien      "LC_MESSAGES",
129107606Sobrien      "LC_PAPER",
130107606Sobrien      "LC_NAME",
131107606Sobrien      "LC_ADDRESS",
132107606Sobrien      "LC_TELEPHONE",
133107606Sobrien      "LC_MEASUREMENT",
134107606Sobrien      "LC_IDENTIFICATION"
135107606Sobrien    };
136132720Skan
137169691Skan_GLIBCXX_END_NAMESPACE
138169691Skan
139169691Skan_GLIBCXX_BEGIN_NAMESPACE(std)
140169691Skan
141132720Skan  const char* const* const locale::_S_categories = __gnu_cxx::category_names;
142169691Skan
143169691Skan_GLIBCXX_END_NAMESPACE
144169691Skan
145169691Skan// XXX GLIBCXX_ABI Deprecated
146169691Skan#ifdef _GLIBCXX_LONG_DOUBLE_COMPAT
147169691Skan#define _GLIBCXX_LDBL_COMPAT(dbl, ldbl) \
148169691Skan  extern "C" void ldbl (void) __attribute__ ((alias (#dbl)))
149169691Skan_GLIBCXX_LDBL_COMPAT(_ZSt14__convert_to_vIdEvPKcRT_RSt12_Ios_IostateRKP15__locale_struct, _ZSt14__convert_to_vIeEvPKcRT_RSt12_Ios_IostateRKP15__locale_struct);
150169691Skan#endif // _GLIBCXX_LONG_DOUBLE_COMPAT
151