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