source: trunk/libs/newlib/src/newlib/libc/stdlib/wcstod.c @ 471

Last change on this file since 471 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 9.1 KB
Line 
1/*
2FUNCTION
3        <<wcstod>>, <<wcstof>>, <<wcstold>>, <<wcstod_l>>, <<wcstof_l>>, <<wcstold_l>>---wide char string to double or float
4
5INDEX
6        wcstod
7
8INDEX
9        wcstof
10
11INDEX
12        wcstold
13
14INDEX
15        wcstod_l
16
17INDEX
18        wcstof_l
19
20INDEX
21        wcstold_l
22
23INDEX
24        _wcstod_r
25
26INDEX
27        _wcstof_r
28
29SYNOPSIS
30        #include <stdlib.h>
31        double wcstod(const wchar_t *__restrict <[str]>,
32                      wchar_t **__restrict <[tail]>);
33        float wcstof(const wchar_t *__restrict <[str]>,
34                     wchar_t **__restrict <[tail]>);
35        long double wcstold(const wchar_t *__restrict <[str]>,
36                            wchar_t **__restrict <[tail]>);
37
38        #include <stdlib.h>
39        double wcstod_l(const wchar_t *__restrict <[str]>,
40                        wchar_t **__restrict <[tail]>, locale_t <[locale]>);
41        float wcstof_l(const wchar_t *__restrict <[str]>,
42                       wchar_t **__restrict <[tail]>, locale_t <[locale]>);
43        long double wcstold_l(const wchar_t *__restrict <[str]>,
44                              wchar_t **__restrict <[tail]>,
45                              locale_t <[locale]>);
46
47        double _wcstod_r(void *<[reent]>,
48                         const wchar_t *<[str]>, wchar_t **<[tail]>);
49        float _wcstof_r(void *<[reent]>,
50                         const wchar_t *<[str]>, wchar_t **<[tail]>);
51
52DESCRIPTION
53        <<wcstod>>, <<wcstof>>, <<wcstold>> parse the wide-character string
54        <[str]>, producing a substring which can be converted to a double,
55        float, or long double value.  The substring converted is the longest
56        initial subsequence of <[str]>, beginning with the first non-whitespace
57        character, that has one of these formats:
58        .[+|-]<[digits]>[.[<[digits]>]][(e|E)[+|-]<[digits]>]
59        .[+|-].<[digits]>[(e|E)[+|-]<[digits]>]
60        .[+|-](i|I)(n|N)(f|F)[(i|I)(n|N)(i|I)(t|T)(y|Y)]
61        .[+|-](n|N)(a|A)(n|N)[<(>[<[hexdigits]>]<)>]
62        .[+|-]0(x|X)<[hexdigits]>[.[<[hexdigits]>]][(p|P)[+|-]<[digits]>]
63        .[+|-]0(x|X).<[hexdigits]>[(p|P)[+|-]<[digits]>]
64        The substring contains no characters if <[str]> is empty, consists
65        entirely of whitespace, or if the first non-whitespace
66        character is something other than <<+>>, <<->>, <<.>>, or a
67        digit, and cannot be parsed as infinity or NaN. If the platform
68        does not support NaN, then NaN is treated as an empty substring.
69        If the substring is empty, no conversion is done, and
70        the value of <[str]> is stored in <<*<[tail]>>>.  Otherwise,
71        the substring is converted, and a pointer to the final string
72        (which will contain at least the terminating null character of
73        <[str]>) is stored in <<*<[tail]>>>.  If you want no
74        assignment to <<*<[tail]>>>, pass a null pointer as <[tail]>.
75
76        This implementation returns the nearest machine number to the
77        input decimal string.  Ties are broken by using the IEEE
78        round-even rule.  However, <<wcstof>> is currently subject to
79        double rounding errors.
80
81        <<wcstod_l>>, <<wcstof_l>>, <<wcstold_l>> are like <<wcstod>>,
82        <<wcstof>>, <<wcstold>> but perform the conversion based on the
83        locale specified by the locale object locale.  If <[locale]> is
84        LC_GLOBAL_LOCALE or not a valid locale object, the behaviour is
85        undefined.
86
87        The alternate functions <<_wcstod_r>> and <<_wcstof_r>> are
88        reentrant versions of <<wcstod>> and <<wcstof>>, respectively.
89        The extra argument <[reent]> is a pointer to a reentrancy structure.
90
91RETURNS
92        Return the converted substring value, if any.  If
93        no conversion could be performed, 0 is returned.  If the
94        correct value is out of the range of representable values,
95        plus or minus <<HUGE_VAL>> is returned, and <<ERANGE>> is
96        stored in errno. If the correct value would cause underflow, 0
97        is returned and <<ERANGE>> is stored in errno.
98
99PORTABILITY
100<<wcstod>> is ANSI.
101<<wcstof>>, <<wcstold>> are C99.
102<<wcstod_l>>, <<wcstof_l>>, <<wcstold_l>> are GNU extensions.
103
104Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
105<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
106*/
107
108/*-
109 * Copyright (c) 2002 Tim J. Robbins
110 * All rights reserved.
111 *
112 * Redistribution and use in source and binary forms, with or without
113 * modification, are permitted provided that the following conditions
114 * are met:
115 * 1. Redistributions of source code must retain the above copyright
116 *    notice, this list of conditions and the following disclaimer.
117 * 2. Redistributions in binary form must reproduce the above copyright
118 *    notice, this list of conditions and the following disclaimer in the
119 *    documentation and/or other materials provided with the distribution.
120 *
121 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
122 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
123 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
124 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
125 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
126 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
127 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
128 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
129 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
130 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
131 * SUCH DAMAGE.
132 */
133
134#include <_ansi.h>
135#include <errno.h>
136#include <stdlib.h>
137#include <string.h>
138#include <wchar.h>
139#include <wctype.h>
140#include <locale.h>
141#include <math.h>
142#include "mprec.h"
143
144double
145_wcstod_l (struct _reent *ptr, const wchar_t *nptr, wchar_t **endptr,
146           locale_t loc)
147{
148        static const mbstate_t initial;
149        mbstate_t mbs;
150        double val;
151        char *buf, *end;
152        const wchar_t *wcp;
153        size_t len;
154
155        while (iswspace_l(*nptr, loc))
156                nptr++;
157
158        /*
159         * Convert the supplied numeric wide char. string to multibyte.
160         *
161         * We could attempt to find the end of the numeric portion of the
162         * wide char. string to avoid converting unneeded characters but
163         * choose not to bother; optimising the uncommon case where
164         * the input string contains a lot of text after the number
165         * duplicates a lot of strtod()'s functionality and slows down the
166         * most common cases.
167         */
168        wcp = nptr;
169        mbs = initial;
170        if ((len = _wcsnrtombs_l(ptr, NULL, &wcp, (size_t) -1, 0, &mbs, loc))
171            == (size_t) -1) {
172                if (endptr != NULL)
173                        *endptr = (wchar_t *)nptr;
174                return (0.0);
175        }
176        if ((buf = _malloc_r(ptr, len + 1)) == NULL)
177                return (0.0);
178        mbs = initial;
179        _wcsnrtombs_l(ptr, buf, &wcp, (size_t) -1, len + 1, &mbs, loc);
180
181        /* Let strtod() do most of the work for us. */
182        val = _strtod_l(ptr, buf, &end, loc);
183
184        /*
185         * We only know where the number ended in the _multibyte_
186         * representation of the string. If the caller wants to know
187         * where it ended, count multibyte characters to find the
188         * corresponding position in the wide char string.
189         */
190        if (endptr != NULL) {
191                /* The only valid multibyte char in a float converted by
192                   strtod/wcstod is the radix char.  What we do here is,
193                   figure out if the radix char was in the valid leading
194                   float sequence in the incoming string.  If so, the
195                   multibyte float string is strlen(radix char) - 1 bytes
196                   longer than the incoming wide char string has characters.
197                   To fix endptr, reposition end as if the radix char was
198                   just one byte long.  The resulting difference (end - buf)
199                   is then equivalent to the number of valid wide characters
200                   in the input string. */
201                len = strlen (__localeconv_l (loc)->decimal_point);
202                if (len > 1) {
203                        char *d = strstr (buf,
204                                          __localeconv_l (loc)->decimal_point);
205                        if (d && d < end)
206                                end -= len - 1;
207                }
208                *endptr = (wchar_t *)nptr + (end - buf);
209        }
210
211        _free_r(ptr, buf);
212
213        return (val);
214}
215
216double
217_wcstod_r (struct _reent *ptr,
218        const wchar_t *nptr,
219        wchar_t **endptr)
220{
221  return _wcstod_l (ptr, nptr, endptr, __get_current_locale ());
222}
223
224float
225_wcstof_r (struct _reent *ptr,
226        const wchar_t *nptr,
227        wchar_t **endptr)
228{
229  double retval = _wcstod_l (ptr, nptr, endptr, __get_current_locale ());
230  if (isnan (retval))
231    return nanf (NULL);
232  return (float)retval;
233}
234
235#ifndef _REENT_ONLY
236
237double
238wcstod_l (const wchar_t *__restrict nptr, wchar_t **__restrict endptr,
239          locale_t loc)
240{
241  return _wcstod_l (_REENT, nptr, endptr, loc);
242}
243
244double
245wcstod (const wchar_t *__restrict nptr, wchar_t **__restrict endptr)
246{
247  return _wcstod_l (_REENT, nptr, endptr, __get_current_locale ());
248}
249
250float
251wcstof_l (const wchar_t *__restrict nptr, wchar_t **__restrict endptr,
252          locale_t loc)
253{
254  double val = _wcstod_l (_REENT, nptr, endptr, loc);
255  if (isnan (val))
256    return nanf (NULL);
257  float retval = (float) val;
258#ifndef NO_ERRNO
259  if (isinf (retval) && !isinf (val))
260    _REENT->_errno = ERANGE;
261#endif
262  return retval;
263}
264
265float
266wcstof (const wchar_t *__restrict nptr,
267        wchar_t **__restrict endptr)
268{
269  double val = _wcstod_l (_REENT, nptr, endptr, __get_current_locale ());
270  if (isnan (val))
271    return nanf (NULL);
272  float retval = (float) val;
273#ifndef NO_ERRNO
274  if (isinf (retval) && !isinf (val))
275    _REENT->_errno = ERANGE;
276#endif
277
278  return retval;
279}
280
281#endif
Note: See TracBrowser for help on using the repository browser.