From 77ea728b96e00e063b2243487a35e5c395639bfc Mon Sep 17 00:00:00 2001 From: Jeff Johnston Date: Thu, 12 Feb 2009 23:10:01 +0000 Subject: [PATCH] 2009-02-12 Corinna Vinschen * libc/include/wchar.h (_wcstod_r): Declare. (_wcstof_r): Declare. (wcstod): Declare. (wcstof): Declare. * libc/stdlib/Makefile.am (GENERAL_SOURCES): Add wcstod.c. (CHEWOUT_FILES): Add wcstod.def. * libc/stdlib/Makefile.in: Regenerate. * libc/stdlib/stdlib.tex: Add wcstod. * libc/stdlib/wcstod.c: New file. --- newlib/ChangeLog | 12 ++ newlib/libc/include/wchar.h | 4 + newlib/libc/stdlib/Makefile.am | 3 +- newlib/libc/stdlib/Makefile.in | 20 +++- newlib/libc/stdlib/stdlib.tex | 4 + newlib/libc/stdlib/wcstod.c | 209 +++++++++++++++++++++++++++++++++ 6 files changed, 245 insertions(+), 7 deletions(-) create mode 100644 newlib/libc/stdlib/wcstod.c diff --git a/newlib/ChangeLog b/newlib/ChangeLog index d1199f7ba..3a2b48c11 100644 --- a/newlib/ChangeLog +++ b/newlib/ChangeLog @@ -1,3 +1,15 @@ +2009-02-12 Corinna Vinschen + + * libc/include/wchar.h (_wcstod_r): Declare. + (_wcstof_r): Declare. + (wcstod): Declare. + (wcstof): Declare. + * libc/stdlib/Makefile.am (GENERAL_SOURCES): Add wcstod.c. + (CHEWOUT_FILES): Add wcstod.def. + * libc/stdlib/Makefile.in: Regenerate. + * libc/stdlib/stdlib.tex: Add wcstod. + * libc/stdlib/wcstod.c: New file. + 2009-02-05 Neal H. Walfield * libc/machine/x86_64/memcpy.S (memcpy): Don't use the red zone. diff --git a/newlib/libc/include/wchar.h b/newlib/libc/include/wchar.h index 815c3c19f..31e768700 100644 --- a/newlib/libc/include/wchar.h +++ b/newlib/libc/include/wchar.h @@ -74,6 +74,10 @@ wchar_t *_EXFUN(wcsrchr, (const wchar_t *, wchar_t)); size_t _EXFUN(wcsspn, (const wchar_t *, const wchar_t *)); wchar_t *_EXFUN(wcsstr, (const wchar_t *, const wchar_t *)); wchar_t *_EXFUN(wcstok, (wchar_t *, const wchar_t *, wchar_t **)); +double _EXFUN(wcstod, (const wchar_t *, wchar_t **)); +double _EXFUN(_wcstod_r, (struct _reent *, const wchar_t *, wchar_t **)); +float _EXFUN(wcstof, (const wchar_t *, wchar_t **)); +float _EXFUN(_wcstof_r, (struct _reent *, const wchar_t *, wchar_t **)); int _EXFUN(wcswidth, (const wchar_t *, size_t)); size_t _EXFUN(wcsxfrm, (wchar_t *, const wchar_t *, size_t)); int _EXFUN(wcwidth, (const wchar_t)); diff --git a/newlib/libc/stdlib/Makefile.am b/newlib/libc/stdlib/Makefile.am index e63ea0334..9a9c013d7 100644 --- a/newlib/libc/stdlib/Makefile.am +++ b/newlib/libc/stdlib/Makefile.am @@ -51,6 +51,7 @@ GENERAL_SOURCES = \ strtod.c \ strtol.c \ strtoul.c \ + wcstod.c \ wcstol.c \ wcstoul.c \ wcstombs.c \ @@ -238,12 +239,12 @@ CHEWOUT_FILES= \ strtoll.def \ strtoul.def \ strtoull.def \ + wcstod.def \ wcstol.def \ wcstoll.def \ wcstoul.def \ wcstoull.def \ system.def \ - wcstol.def \ wcstombs.def \ wctomb.def diff --git a/newlib/libc/stdlib/Makefile.in b/newlib/libc/stdlib/Makefile.in index be947cbcf..2dfbfed8f 100644 --- a/newlib/libc/stdlib/Makefile.in +++ b/newlib/libc/stdlib/Makefile.in @@ -89,9 +89,10 @@ am__objects_1 = lib_a-__adjust.$(OBJEXT) lib_a-__atexit.$(OBJEXT) \ lib_a-rand_r.$(OBJEXT) lib_a-realloc.$(OBJEXT) \ lib_a-reallocf.$(OBJEXT) lib_a-strtod.$(OBJEXT) \ lib_a-strtol.$(OBJEXT) lib_a-strtoul.$(OBJEXT) \ - lib_a-wcstol.$(OBJEXT) lib_a-wcstoul.$(OBJEXT) \ - lib_a-wcstombs.$(OBJEXT) lib_a-wcstombs_r.$(OBJEXT) \ - lib_a-wctomb.$(OBJEXT) lib_a-wctomb_r.$(OBJEXT) + lib_a-wcstod.$(OBJEXT) lib_a-wcstol.$(OBJEXT) \ + lib_a-wcstoul.$(OBJEXT) lib_a-wcstombs.$(OBJEXT) \ + lib_a-wcstombs_r.$(OBJEXT) lib_a-wctomb.$(OBJEXT) \ + lib_a-wctomb_r.$(OBJEXT) am__objects_2 = lib_a-cxa_atexit.$(OBJEXT) \ lib_a-cxa_finalize.$(OBJEXT) lib_a-drand48.$(OBJEXT) \ lib_a-ecvtbuf.$(OBJEXT) lib_a-efgcvt.$(OBJEXT) \ @@ -136,8 +137,8 @@ am__objects_7 = __adjust.lo __atexit.lo __call_atexit.lo __exp10.lo \ ldiv.lo ldtoa.lo malloc.lo mblen.lo mblen_r.lo mbstowcs.lo \ mbstowcs_r.lo mbtowc.lo mbtowc_r.lo mlock.lo mprec.lo \ mstats.lo rand.lo rand_r.lo realloc.lo reallocf.lo strtod.lo \ - strtol.lo strtoul.lo wcstol.lo wcstoul.lo wcstombs.lo \ - wcstombs_r.lo wctomb.lo wctomb_r.lo + strtol.lo strtoul.lo wcstod.lo wcstol.lo wcstoul.lo \ + wcstombs.lo wcstombs_r.lo wctomb.lo wctomb_r.lo am__objects_8 = cxa_atexit.lo cxa_finalize.lo drand48.lo ecvtbuf.lo \ efgcvt.lo erand48.lo jrand48.lo lcong48.lo lrand48.lo \ mrand48.lo msize.lo mtrim.lo nrand48.lo rand48.lo seed48.lo \ @@ -392,6 +393,7 @@ GENERAL_SOURCES = \ strtod.c \ strtol.c \ strtoul.c \ + wcstod.c \ wcstol.c \ wcstoul.c \ wcstombs.c \ @@ -526,12 +528,12 @@ CHEWOUT_FILES = \ strtoll.def \ strtoul.def \ strtoull.def \ + wcstod.def \ wcstol.def \ wcstoll.def \ wcstoul.def \ wcstoull.def \ system.def \ - wcstol.def \ wcstombs.def \ wctomb.def @@ -882,6 +884,12 @@ lib_a-strtoul.o: strtoul.c lib_a-strtoul.obj: strtoul.c $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strtoul.obj `if test -f 'strtoul.c'; then $(CYGPATH_W) 'strtoul.c'; else $(CYGPATH_W) '$(srcdir)/strtoul.c'; fi` +lib_a-wcstod.o: wcstod.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-wcstod.o `test -f 'wcstod.c' || echo '$(srcdir)/'`wcstod.c + +lib_a-wcstod.obj: wcstod.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-wcstod.obj `if test -f 'wcstod.c'; then $(CYGPATH_W) 'wcstod.c'; else $(CYGPATH_W) '$(srcdir)/wcstod.c'; fi` + lib_a-wcstol.o: wcstol.c $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-wcstol.o `test -f 'wcstol.c' || echo '$(srcdir)/'`wcstol.c diff --git a/newlib/libc/stdlib/stdlib.tex b/newlib/libc/stdlib/stdlib.tex index acb4894a5..d91b3f8d3 100644 --- a/newlib/libc/stdlib/stdlib.tex +++ b/newlib/libc/stdlib/stdlib.tex @@ -40,6 +40,7 @@ The corresponding declarations are in the header file @file{stdlib.h}. * strtoll:: String to long long * strtoul:: String to unsigned long * strtoull:: String to unsigned long long +* wcstod:: Wide string to double or float * wcstol:: Wide string to long * wcstoll:: Wide string to long long * wcstoul:: Wide string to unsigned long @@ -151,6 +152,9 @@ The corresponding declarations are in the header file @file{stdlib.h}. @page @include stdlib/strtoull.def +@page +@include stdlib/wcstod.def + @page @include stdlib/wcstol.def diff --git a/newlib/libc/stdlib/wcstod.c b/newlib/libc/stdlib/wcstod.c new file mode 100644 index 000000000..403415705 --- /dev/null +++ b/newlib/libc/stdlib/wcstod.c @@ -0,0 +1,209 @@ +/* +FUNCTION + <>, <>---wide char string to double or float + +INDEX + wcstod +INDEX + _wcstod_r +INDEX + wcstof +INDEX + _wcstof_r + +ANSI_SYNOPSIS + #include + double wcstod(const wchar_t *<[str]>, wchar_t **<[tail]>); + float wcstof(const wchar_t *<[str]>, wchar_t **<[tail]>); + + double _wcstod_r(void *<[reent]>, + const wchar_t *<[str]>, wchar_t **<[tail]>); + float _wcstof_r(void *<[reent]>, + const wchar_t *<[str]>, wchar_t **<[tail]>); + +TRAD_SYNOPSIS + #include + double wcstod(<[str]>,<[tail]>) + wchar_t *<[str]>; + wchar_t **<[tail]>; + + float wcstof(<[str]>,<[tail]>) + wchar_t *<[str]>; + wchar_t **<[tail]>; + + double _wcstod_r(<[reent]>,<[str]>,<[tail]>) + wchar_t *<[reent]>; + wchar_t *<[str]>; + wchar_t **<[tail]>; + + float _wcstof_r(<[reent]>,<[str]>,<[tail]>) + wchar_t *<[reent]>; + wchar_t *<[str]>; + wchar_t **<[tail]>; + +DESCRIPTION + The function <> parses the wide character string <[str]>, + producing a substring which can be converted to a double + value. The substring converted is the longest initial + subsequence of <[str]>, beginning with the first + non-whitespace character, that has one of these formats: + .[+|-]<[digits]>[.[<[digits]>]][(e|E)[+|-]<[digits]>] + .[+|-].<[digits]>[(e|E)[+|-]<[digits]>] + .[+|-](i|I)(n|N)(f|F)[(i|I)(n|N)(i|I)(t|T)(y|Y)] + .[+|-](n|N)(a|A)(n|N)[<(>[<[hexdigits]>]<)>] + .[+|-]0(x|X)<[hexdigits]>[.[<[hexdigits]>]][(p|P)[+|-]<[digits]>] + .[+|-]0(x|X).<[hexdigits]>[(p|P)[+|-]<[digits]>] + The substring contains no characters if <[str]> is empty, consists + entirely of whitespace, or if the first non-whitespace + character is something other than <<+>>, <<->>, <<.>>, or a + digit, and cannot be parsed as infinity or NaN. If the platform + does not support NaN, then NaN is treated as an empty substring. + If the substring is empty, no conversion is done, and + the value of <[str]> is stored in <<*<[tail]>>>. Otherwise, + the substring is converted, and a pointer to the final string + (which will contain at least the terminating null character of + <[str]>) is stored in <<*<[tail]>>>. If you want no + assignment to <<*<[tail]>>>, pass a null pointer as <[tail]>. + <> is identical to <> except for its return type. + + This implementation returns the nearest machine number to the + input decimal string. Ties are broken by using the IEEE + round-even rule. However, <> is currently subject to + double rounding errors. + + The alternate functions <<_wcstod_r>> and <<_wcstof_r>:> are + reentrant versions of <> and <>, respectively. + The extra argument <[reent]> is a pointer to a reentrancy structure. + +RETURNS + Return the converted substring value, if any. If + no conversion could be performed, 0 is returned. If the + correct value is out of the range of representable values, + plus or minus <> is returned, and <> is + stored in errno. If the correct value would cause underflow, 0 + is returned and <> is stored in errno. + +Supporting OS subroutines required: <>, <>, <>, +<>, <>, <>, <>. +*/ + +/*- + * Copyright (c) 2002 Tim J. Robbins + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <_ansi.h> +#include +#include +#include + +double +_DEFUN (_wcstod_r, (ptr, nptr, endptr), + struct _reent *ptr _AND + _CONST wchar_t *nptr _AND + wchar_t **endptr) +{ + static const mbstate_t initial; + mbstate_t mbs; + double val; + char *buf, *end; + const wchar_t *wcp; + size_t len; + + while (iswspace(*nptr)) + nptr++; + + /* + * Convert the supplied numeric wide char. string to multibyte. + * + * We could attempt to find the end of the numeric portion of the + * wide char. string to avoid converting unneeded characters but + * choose not to bother; optimising the uncommon case where + * the input string contains a lot of text after the number + * duplicates a lot of strtod()'s functionality and slows down the + * most common cases. + */ + wcp = nptr; + mbs = initial; + if ((len = _wcsrtombs_r(ptr, NULL, &wcp, 0, &mbs)) == (size_t)-1) { + if (endptr != NULL) + *endptr = (wchar_t *)nptr; + return (0.0); + } + if ((buf = _malloc_r(ptr, len + 1)) == NULL) + return (0.0); + mbs = initial; + _wcsrtombs_r(ptr, buf, &wcp, len + 1, &mbs); + + /* Let strtod() do most of the work for us. */ + val = _strtod_r(ptr, buf, &end); + + /* + * We only know where the number ended in the _multibyte_ + * representation of the string. If the caller wants to know + * where it ended, count multibyte characters to find the + * corresponding position in the wide char string. + */ + if (endptr != NULL) + /* XXX Assume each wide char is one byte. */ + *endptr = (wchar_t *)nptr + (end - buf); + + _free_r(ptr, buf); + + return (val); +} + +float +_DEFUN (_wcstof_r, (ptr, nptr, endptr), + struct _reent *ptr _AND + _CONST wchar_t *nptr _AND + wchar_t **endptr) +{ + double retval = _wcstod_r (ptr, nptr, endptr); + if (isnan (retval)) + return nanf (NULL); + return (float)retval; +} + +#ifndef NO_REENT + +double +_DEFUN (wcstod, (nptr, endptr), + _CONST wchar_t *nptr _AND wchar_t **endptr) +{ + return _wcstod_r (_REENT, nptr, endptr); +} + +float +_DEFUN (wcstof, (nptr, endptr), + _CONST wchar_t *nptr _AND + wchar_t **endptr) +{ + double retval = _wcstod_r (_REENT, nptr, endptr); + if (isnan (retval)) + return nanf (NULL); + return (float)retval; +} + +#endif