1// Wrapper for underlying C-language localization -*- C++ -*-
2
3// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006
4// Free Software Foundation, Inc.
5//
6// This file is part of the GNU ISO C++ Library.  This library is free
7// software; you can redistribute it and/or modify it under the
8// terms of the GNU General Public License as published by the
9// Free Software Foundation; either version 2, or (at your option)
10// any later version.
11
12// This library is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15// GNU General Public License for more details.
16
17// You should have received a copy of the GNU General Public License along
18// with this library; see the file COPYING.  If not, write to the Free
19// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20// USA.
21
22// As a special exception, you may use this file as part of a free software
23// library without restriction.  Specifically, if other files instantiate
24// templates or use macros or inline functions from this file, or you compile
25// this file and link it with other files to produce an executable, this
26// file does not by itself cause the resulting executable to be covered by
27// the GNU General Public License.  This exception does not however
28// invalidate any other reasons why the executable file might be covered by
29// the GNU General Public License.
30
31//
32// ISO C++ 14882: 22.8  Standard locale categories.
33//
34
35// Written by Benjamin Kosnik <bkoz@redhat.com>
36
37#include <cerrno>  // For errno
38#include <cmath>  // For isinf, finite, finitef, fabs
39#include <cstdlib>  // For strof, strtold
40#include <locale>
41
42#ifdef _GLIBCXX_HAVE_IEEEFP_H
43#include <ieeefp.h>
44#endif
45
46_GLIBCXX_BEGIN_NAMESPACE(std)
47
48  // Specializations for all types used in num_get.
49  template<>
50    void
51    __convert_to_v(const char* __s, float& __v, ios_base::iostate& __err,
52		   const __c_locale&)
53    {
54      // Assumes __s formatted for "C" locale.
55      errno = 0;
56      char* __old = strdup(setlocale(LC_ALL, NULL));
57      setlocale(LC_ALL, "C");
58      char* __sanity;
59#if defined(_GLIBCXX_HAVE_STRTOF)
60      float __f = strtof(__s, &__sanity);
61#else
62      double __d = strtod(__s, &__sanity);
63      float __f = static_cast<float>(__d);
64#ifdef _GLIBCXX_HAVE_FINITEF
65      if (!finitef (__f))
66	errno = ERANGE;
67#elif defined (_GLIBCXX_HAVE_FINITE)
68      if (!finite (static_cast<double> (__f)))
69	errno = ERANGE;
70#elif defined (_GLIBCXX_HAVE_ISINF)
71      if (isinf (static_cast<double> (__f)))
72	errno = ERANGE;
73#else
74      if (fabs(__d) > numeric_limits<float>::max())
75	errno = ERANGE;
76#endif
77#endif
78      if (__sanity != __s && errno != ERANGE)
79	__v = __f;
80      else
81	__err |= ios_base::failbit;
82      setlocale(LC_ALL, __old);
83      free(__old);
84    }
85
86  template<>
87    void
88    __convert_to_v(const char* __s, double& __v, ios_base::iostate& __err,
89		   const __c_locale&)
90    {
91      // Assumes __s formatted for "C" locale.
92      errno = 0;
93      char* __old = strdup(setlocale(LC_ALL, NULL));
94      setlocale(LC_ALL, "C");
95      char* __sanity;
96      double __d = strtod(__s, &__sanity);
97      if (__sanity != __s && errno != ERANGE)
98	__v = __d;
99      else
100	__err |= ios_base::failbit;
101      setlocale(LC_ALL, __old);
102      free(__old);
103    }
104
105  template<>
106    void
107    __convert_to_v(const char* __s, long double& __v,
108		   ios_base::iostate& __err, const __c_locale&)
109    {
110      // Assumes __s formatted for "C" locale.
111      errno = 0;
112      char* __old = strdup(setlocale(LC_ALL, NULL));
113      setlocale(LC_ALL, "C");
114#if defined(_GLIBCXX_HAVE_STRTOLD)
115      char* __sanity;
116      long double __ld = strtold(__s, &__sanity);
117      if (__sanity != __s && errno != ERANGE)
118	__v = __ld;
119#else
120      typedef char_traits<char>::int_type int_type;
121      long double __ld;
122      int __p = sscanf(__s, "%Lf", &__ld);
123      if (__p && static_cast<int_type>(__p) != char_traits<char>::eof()
124	  && errno != ERANGE)
125	__v = __ld;
126#endif
127      else
128	__err |= ios_base::failbit;
129      setlocale(LC_ALL, __old);
130      free(__old);
131    }
132
133  void
134  locale::facet::_S_create_c_locale(__c_locale& __cloc, const char* __s,
135				    __c_locale)
136  {
137    // Currently, the generic model only supports the "C" locale.
138    // See http://gcc.gnu.org/ml/libstdc++/2003-02/msg00345.html
139    __cloc = NULL;
140    if (strcmp(__s, "C"))
141      __throw_runtime_error(__N("locale::facet::_S_create_c_locale "
142			    "name not valid"));
143  }
144
145  void
146  locale::facet::_S_destroy_c_locale(__c_locale& __cloc)
147  { __cloc = NULL; }
148
149  __c_locale
150  locale::facet::_S_clone_c_locale(__c_locale&)
151  { return __c_locale(); }
152
153_GLIBCXX_END_NAMESPACE
154
155_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
156
157  const char* const category_names[6 + _GLIBCXX_NUM_CATEGORIES] =
158    {
159      "LC_CTYPE",
160      "LC_NUMERIC",
161      "LC_TIME",
162      "LC_COLLATE",
163      "LC_MONETARY",
164      "LC_MESSAGES"
165    };
166
167_GLIBCXX_END_NAMESPACE
168
169_GLIBCXX_BEGIN_NAMESPACE(std)
170
171  const char* const* const locale::_S_categories = __gnu_cxx::category_names;
172
173_GLIBCXX_END_NAMESPACE
174
175// XXX GLIBCXX_ABI Deprecated
176#ifdef _GLIBCXX_LONG_DOUBLE_COMPAT
177#define _GLIBCXX_LDBL_COMPAT(dbl, ldbl) \
178  extern "C" void ldbl (void) __attribute__ ((alias (#dbl)))
179_GLIBCXX_LDBL_COMPAT(_ZSt14__convert_to_vIdEvPKcRT_RSt12_Ios_IostateRKPi, _ZSt14__convert_to_vIeEvPKcRT_RSt12_Ios_IostateRKPi);
180#endif // _GLIBCXX_LONG_DOUBLE_COMPAT
181