1 /* $NetBSD: wcstod.c,v 1.3 2001/10/02 01:20:03 erh Exp $ */ 2 3 /*- 4 * Copyright (c)1999, 2000, 2001 Citrus Project, 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $Citrus: xpg4dl/FreeBSD/lib/libc/locale/wcstod.c,v 1.2 2001/09/27 16:23:57 yamt Exp $ 29 */ 30 31 #include <sys/cdefs.h> 32 #include <assert.h> 33 #include <errno.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <wchar.h> 37 #include <wctype.h> 38 39 /* XXX our lint can't handle wide char constant */ 40 #if defined(lint) 41 #define _L(x) ((const wchar_t *)0) 42 #define _LC(x) ((wchar_t)0) 43 #else 44 #define _L(x) __CONCAT(L,x) 45 #define _LC(x) __CONCAT(L,x) 46 #endif 47 48 double 49 wcstod(const wchar_t *nptr, wchar_t **endptr) 50 { 51 const wchar_t *src; 52 size_t size; 53 const wchar_t *start; 54 55 _DIAGASSERT(nptr); 56 57 /* 58 * we do only check length of string 59 * and give it over strtod. 60 */ 61 src = nptr; 62 63 /* skip space first */ 64 while (iswspace(*src)) { 65 src++; 66 } 67 68 /* get length of string */ 69 start = src; 70 if (wcschr(_L("+-"), *src)) 71 src++; 72 size = wcsspn(src, _L("0123456789")); 73 src += size; 74 if (*src == _LC('.')) {/* XXX use localeconv */ 75 src++; 76 size = wcsspn(src, _L("0123456789")); 77 src += size; 78 } 79 if (wcschr(_L("Ee"), *src)) { 80 src++; 81 if (wcschr(_L("+-"), *src)) 82 src++; 83 size = wcsspn(src, _L("0123456789")); 84 src += size; 85 } 86 size = src - start; 87 88 /* 89 * convert to a char-string and pass it to strtod. 90 * 91 * since all chars used to represent a double-constant 92 * are in the portable character set, we can assume 93 * that they are 1-byte chars. 94 */ 95 if (size) 96 { 97 mbstate_t st; 98 char *buf; 99 char *end; 100 const wchar_t *s; 101 size_t size_converted; 102 double result; 103 104 buf = malloc(size + 1); 105 if (!buf) { 106 /* error */ 107 errno = ENOMEM; /* XXX */ 108 return 0; 109 } 110 111 s = start; 112 memset(&st, 0, sizeof(st)); 113 size_converted = wcsrtombs(buf, &s, size, &st); 114 if (size != size_converted) { 115 /* XXX should not happen */ 116 free(buf); 117 errno = EILSEQ; 118 return 0; 119 } 120 121 buf[size] = 0; 122 result = strtod(buf, &end); 123 124 free(buf); 125 126 if (endptr) 127 /* LINTED bad interface */ 128 *endptr = (wchar_t*)start + (end - buf); 129 130 return result; 131 } 132 133 if (endptr) 134 /* LINTED bad interface */ 135 *endptr = (wchar_t*)start; 136 137 return 0; 138 } 139