1 /* $NetBSD: wcstoul.c,v 1.1 2001/09/27 16:30:37 yamt Exp $ */ 2 /* $Citrus: xpg4dl/FreeBSD/lib/libc/locale/wcstoul.c,v 1.2 2001/09/21 16:11:41 yamt Exp $ */ 3 4 /* 5 * Copyright (c) 1990, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 #include <sys/cdefs.h> 38 #if defined(LIBC_SCCS) && !defined(lint) 39 #if 0 40 static char sccsid[] = "@(#)strtoul.c 8.1 (Berkeley) 6/4/93"; 41 #else 42 __RCSID("$NetBSD: wcstoul.c,v 1.1 2001/09/27 16:30:37 yamt Exp $"); 43 #endif 44 #endif /* LIBC_SCCS and not lint */ 45 46 #include <assert.h> 47 #include <ctype.h> 48 #include <errno.h> 49 #include <limits.h> 50 #include <stdlib.h> 51 #include <wchar.h> 52 #include <wctype.h> 53 54 #include "__wctoint.h" 55 56 /* 57 * Convert a wide-char string to an unsigned long integer. 58 */ 59 unsigned long 60 wcstoul(nptr, endptr, base) 61 const wchar_t *nptr; 62 wchar_t **endptr; 63 int base; 64 { 65 const wchar_t *s; 66 unsigned long acc, cutoff; 67 wint_t wc; 68 int i; 69 int neg, any, cutlim; 70 71 _DIAGASSERT(nptr != NULL); 72 /* endptr may be NULL */ 73 74 /* check base value */ 75 if (base && (base < 2 || base > 36)) { 76 errno = EINVAL; 77 return 0; 78 } 79 80 /* 81 * See strtol for comments as to the logic used. 82 */ 83 s = nptr; 84 do { 85 wc = (wchar_t) *s++; 86 } while (iswspace(wc)); 87 if (wc == L'-') { 88 neg = 1; 89 wc = *s++; 90 } else { 91 neg = 0; 92 if (wc == L'+') 93 wc = *s++; 94 } 95 if ((base == 0 || base == 16) && 96 wc == L'0' && (*s == L'x' || *s == L'X')) { 97 wc = s[1]; 98 s += 2; 99 base = 16; 100 } 101 if (base == 0) 102 base = wc == L'0' ? 8 : 10; 103 104 cutoff = ULONG_MAX / (unsigned long)base; 105 cutlim = (int)(ULONG_MAX % (unsigned long)base); 106 for (acc = 0, any = 0;; wc = (wchar_t) *s++) { 107 i = __wctoint(wc); 108 if (i == (wint_t)-1) 109 break; 110 if (i >= base) 111 break; 112 if (any < 0) 113 continue; 114 if (acc > cutoff || (acc == cutoff && i > cutlim)) { 115 any = -1; 116 acc = ULONG_MAX; 117 errno = ERANGE; 118 } else { 119 any = 1; 120 acc *= (unsigned long)base; 121 acc += i; 122 } 123 } 124 if (neg && any > 0) 125 acc = -acc; 126 if (endptr != 0) 127 /* LINTED interface specification */ 128 *endptr = (wchar_t *)(any ? s - 1 : nptr); 129 return (acc); 130 } 131