Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-3-0]: src Pull up following revision(s) (requested by tnozaki in ...
details: https://anonhg.NetBSD.org/src/rev/2354f4d63396
branches: netbsd-3-0
changeset: 579210:2354f4d63396
user: riz <riz%NetBSD.org@localhost>
date: Fri Apr 28 21:59:57 2006 +0000
description:
Pull up following revision(s) (requested by tnozaki in ticket #1272):
lib/libc/locale/wcstod.c: revision 1.4-1.8
regress/lib/libc/locale/wcstod/wcstod_test.c: revision 1.1
regress/lib/libc/locale/wcstod/Makefile: revision 1.1
replaced by FreeBSD version wcstod(3) for make it work
with L"inf", L"nan", and hex conversion.
suggested by joerg AT netbsd DOT org, thanks.
diffstat:
lib/libc/locale/wcstod.c | 152 ++++-----
regress/lib/libc/locale/wcstod/Makefile | 11 +
regress/lib/libc/locale/wcstod/wcstod_test.c | 412 +++++++++++++++++++++++++++
3 files changed, 495 insertions(+), 80 deletions(-)
diffs (truncated from 623 to 300 lines):
diff -r 3d464759c4a0 -r 2354f4d63396 lib/libc/locale/wcstod.c
--- a/lib/libc/locale/wcstod.c Tue Apr 25 23:52:02 2006 +0000
+++ b/lib/libc/locale/wcstod.c Fri Apr 28 21:59:57 2006 +0000
@@ -1,7 +1,7 @@
-/* $NetBSD: wcstod.c,v 1.4 2001/10/28 12:08:43 yamt Exp $ */
+/* $NetBSD: wcstod.c,v 1.4.12.1 2006/04/28 21:59:57 riz Exp $ */
/*-
- * Copyright (c)1999, 2000, 2001 Citrus Project,
+ * Copyright (c) 2002 Tim J. Robbins
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -25,10 +25,15 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Citrus: xpg4dl/FreeBSD/lib/libc/locale/wcstod.c,v 1.2 2001/09/27 16:23:57 yamt Exp $
+ * Original version ID:
+ * FreeBSD: /repoman/r/ncvs/src/lib/libc/locale/wcstod.c,v 1.4 2004/04/07 09:47:56 tjr Exp
*/
#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcstod.c,v 1.4.12.1 2006/04/28 21:59:57 riz Exp $");
+#endif /* LIBC_SCCS and not lint */
+
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
@@ -36,97 +41,84 @@
#include <wchar.h>
#include <wctype.h>
-#define _L(x) __CONCAT(L,x)
-#define _LC(x) __CONCAT(L,x)
-
+/*
+ * Convert a string to a double-precision number.
+ *
+ * This is the wide-character counterpart of strtod(). So that we do not
+ * have to duplicate the code of strtod() here, we convert the supplied
+ * wide character string to multibyte and call strtod() on the result.
+ * This assumes that the multibyte encoding is compatible with ASCII
+ * for at least the digits, radix character and letters.
+ */
double
-wcstod(const wchar_t *nptr, wchar_t **endptr)
+wcstod(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr)
{
- const wchar_t *src;
- size_t size;
- const wchar_t *start;
-
- _DIAGASSERT(nptr);
-
- /*
- * we do only check length of string
- * and give it over strtod.
- */
- src = nptr;
+ const wchar_t *src, *start;
+ double val;
+ char *buf, *end;
+ size_t bufsiz, len;
- /* skip space first */
- while (iswspace(*src)) {
- src++;
- }
+ _DIAGASSERT(nptr != NULL);
+ /* endptr may be null */
- /* get length of string */
- start = src;
- if (wcschr(_L("+-"), *src))
- src++;
- size = wcsspn(src, _L("0123456789"));
- src += size;
- if (*src == _LC('.')) {/* XXX use localeconv */
- src++;
- size = wcsspn(src, _L("0123456789"));
- src += size;
- }
- if (wcschr(_L("Ee"), *src)) {
- src++;
- if (wcschr(_L("+-"), *src))
- src++;
- size = wcsspn(src, _L("0123456789"));
- src += size;
- }
- size = src - start;
+ src = nptr;
+ while (iswspace((wint_t)*src) != 0)
+ ++src;
+ if (*src == L'\0')
+ goto no_convert;
/*
- * convert to a char-string and pass it to strtod.
+ * Convert the supplied numeric wide char. string to multibyte.
*
- * since all chars used to represent a double-constant
- * are in the portable character set, we can assume
- * that they are 1-byte chars.
+ * 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.
*/
- if (size)
- {
- mbstate_t st;
- char *buf;
- char *end;
- const wchar_t *s;
- size_t size_converted;
- double result;
-
- buf = malloc(size + 1);
- if (!buf) {
- /* error */
- errno = ENOMEM; /* XXX */
- return 0;
- }
-
- s = start;
- memset(&st, 0, sizeof(st));
- size_converted = wcsrtombs(buf, &s, size, &st);
- if (size != size_converted) {
- /* XXX should not happen */
- free(buf);
- errno = EILSEQ;
- return 0;
- }
+ start = src;
+ len = wcstombs(NULL, src, 0);
+ if (len == (size_t)-1)
+ /* errno = EILSEQ */
+ goto no_convert;
+
+ _DIAGASSERT(len > 0);
- buf[size] = 0;
- result = strtod(buf, &end);
+ bufsiz = len;
+ buf = (void *)malloc(bufsiz + 1);
+ if (buf == NULL)
+ /* errno = ENOMEM */
+ goto no_convert;
- free(buf);
+ len = wcstombs(buf, src, bufsiz + 1);
- if (endptr)
- /* LINTED bad interface */
- *endptr = (wchar_t*)start + (end - buf);
+ _DIAGASSERT(len == bufsiz);
+ _DIAGASSERT(buf[len] == '\0');
- return result;
+ /* Let strtod() do most of the work for us. */
+ val = strtod(buf, &end);
+ if (buf == end) {
+ free(buf);
+ goto no_convert;
}
- if (endptr)
- /* LINTED bad interface */
- *endptr = (wchar_t*)start;
+ /*
+ * 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 = __UNCONST(start + (size_t)(end - buf));
+ free(buf);
+
+ return val;
+
+no_convert:
+ if (endptr != NULL)
+ *endptr = __UNCONST(nptr);
return 0;
}
diff -r 3d464759c4a0 -r 2354f4d63396 regress/lib/libc/locale/wcstod/Makefile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/regress/lib/libc/locale/wcstod/Makefile Fri Apr 28 21:59:57 2006 +0000
@@ -0,0 +1,11 @@
+# $NetBSD: Makefile,v 1.1.4.2 2006/04/28 21:59:58 riz Exp $
+
+NOMAN= #defined
+
+PROG= wcstod_test
+WARNS?= 4
+
+regress: ${PROG}
+ ./${PROG}
+
+.include <bsd.prog.mk>
diff -r 3d464759c4a0 -r 2354f4d63396 regress/lib/libc/locale/wcstod/wcstod_test.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/regress/lib/libc/locale/wcstod/wcstod_test.c Fri Apr 28 21:59:57 2006 +0000
@@ -0,0 +1,412 @@
+/* $NetBSD: wcstod_test.c,v 1.1.4.2 2006/04/28 21:59:58 riz Exp $ */
+
+/*-
+ * Copyright (c)2005 Citrus Project,
+ * 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 <assert.h>
+#include <errno.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+typedef struct {
+ const wchar_t *wcs;
+ size_t exp_len;
+ double exp_val;
+ int exp_errno;
+} unitcase_t;
+
+#define ALT_HUGE_VAL -1
+#define ALT_MINUS_HUGE_VAL -2
+#define ALT_NAN -3
+
+static const unitcase_t unitcases[] = {
+
+{ L"IN", 0, 0, 0 },
+{ L"+IN", 0, 0, 0 },
+{ L"-IN", 0, 0, 0 },
+{ L"INX", 0, 0, 0 },
+{ L"+INX", 0, 0, 0 },
+{ L"-INX", 0, 0, 0 },
+{ L"INF", 3, ALT_HUGE_VAL, 0 },
+{ L"+INF", 4, ALT_HUGE_VAL, 0 },
+{ L"-INF", 4, ALT_MINUS_HUGE_VAL, 0 },
+{ L"INFX", 3, ALT_HUGE_VAL, 0 },
+{ L"+INFX", 4, ALT_HUGE_VAL, 0 },
+{ L"-INFX", 4, ALT_MINUS_HUGE_VAL, 0 },
+{ L" IN", 0, 0, 0 },
+{ L" +IN", 0, 0, 0 },
+{ L" -IN", 0, 0, 0 },
+{ L" INX", 0, 0, 0 },
+{ L" +INX", 0, 0, 0 },
+{ L" -INX", 0, 0, 0 },
+{ L"+ INF", 0, 0, 0 },
+{ L"- INF", 0, 0, 0 },
+{ L" INF", 8, ALT_HUGE_VAL, 0 },
+{ L" +INF", 9, ALT_HUGE_VAL, 0 },
+{ L" -INF", 9, ALT_MINUS_HUGE_VAL, 0 },
+{ L" INFX", 8, ALT_HUGE_VAL, 0 },
+{ L" +INFX", 9, ALT_HUGE_VAL, 0 },
+{ L" -INFX", 9, ALT_MINUS_HUGE_VAL, 0 },
+{ L" INFINIT", 8, ALT_HUGE_VAL, 0 },
+{ L" +INFINIT", 9, ALT_HUGE_VAL, 0 },
+{ L" -INFINIT", 9, ALT_MINUS_HUGE_VAL, 0 },
+{ L" INFINITY", 13, ALT_HUGE_VAL, 0 },
+{ L" +INFINITY", 14, ALT_HUGE_VAL, 0 },
+{ L" -INFINITY", 14, ALT_MINUS_HUGE_VAL, 0 },
+{ L" INFINITYX", 13, ALT_HUGE_VAL, 0 },
+{ L" +INFINITYX", 14, ALT_HUGE_VAL, 0 },
+{ L" -INFINITYX", 14, ALT_MINUS_HUGE_VAL, 0 },
+
+/* NAN */
+{ L"NA", 0, 0, 0 },
+{ L"+NA", 0, 0, 0 },
+{ L"-NA", 0, 0, 0 },
+{ L"NAX", 0, 0, 0 },
Home |
Main Index |
Thread Index |
Old Index