115c1c147SMadhukar Pappireddy /*- 215c1c147SMadhukar Pappireddy * SPDX-License-Identifier: BSD-3-Clause 315c1c147SMadhukar Pappireddy * 415c1c147SMadhukar Pappireddy * Copyright (c) 1990, 1993 515c1c147SMadhukar Pappireddy * The Regents of the University of California. All rights reserved. 615c1c147SMadhukar Pappireddy * 715c1c147SMadhukar Pappireddy * Copyright (c) 2011 The FreeBSD Foundation 815c1c147SMadhukar Pappireddy * All rights reserved. 915c1c147SMadhukar Pappireddy * Portions of this software were developed by David Chisnall 1015c1c147SMadhukar Pappireddy * under sponsorship from the FreeBSD Foundation. 1115c1c147SMadhukar Pappireddy * 1215c1c147SMadhukar Pappireddy * Redistribution and use in source and binary forms, with or without 1315c1c147SMadhukar Pappireddy * modification, are permitted provided that the following conditions 1415c1c147SMadhukar Pappireddy * are met: 1515c1c147SMadhukar Pappireddy * 1. Redistributions of source code must retain the above copyright 1615c1c147SMadhukar Pappireddy * notice, this list of conditions and the following disclaimer. 1715c1c147SMadhukar Pappireddy * 2. Redistributions in binary form must reproduce the above copyright 1815c1c147SMadhukar Pappireddy * notice, this list of conditions and the following disclaimer in the 1915c1c147SMadhukar Pappireddy * documentation and/or other materials provided with the distribution. 2015c1c147SMadhukar Pappireddy * 3. Neither the name of the University nor the names of its contributors 2115c1c147SMadhukar Pappireddy * may be used to endorse or promote products derived from this software 2215c1c147SMadhukar Pappireddy * without specific prior written permission. 2315c1c147SMadhukar Pappireddy * 2415c1c147SMadhukar Pappireddy * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2515c1c147SMadhukar Pappireddy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2615c1c147SMadhukar Pappireddy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2715c1c147SMadhukar Pappireddy * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2815c1c147SMadhukar Pappireddy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2915c1c147SMadhukar Pappireddy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3015c1c147SMadhukar Pappireddy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3115c1c147SMadhukar Pappireddy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3215c1c147SMadhukar Pappireddy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3315c1c147SMadhukar Pappireddy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3415c1c147SMadhukar Pappireddy * SUCH DAMAGE. 3515c1c147SMadhukar Pappireddy */ 3615c1c147SMadhukar Pappireddy 3715c1c147SMadhukar Pappireddy #include <errno.h> 3815c1c147SMadhukar Pappireddy #include <limits.h> 3915c1c147SMadhukar Pappireddy #include <stddef.h> 4015c1c147SMadhukar Pappireddy #include <stdlib.h> 4115c1c147SMadhukar Pappireddy 4215c1c147SMadhukar Pappireddy /* 4315c1c147SMadhukar Pappireddy * Convert a string to an unsigned long integer. 4415c1c147SMadhukar Pappireddy * 4515c1c147SMadhukar Pappireddy * Assumes that the upper and lower case 4615c1c147SMadhukar Pappireddy * alphabets and digits are each contiguous. 4715c1c147SMadhukar Pappireddy */ 4815c1c147SMadhukar Pappireddy unsigned long strtoul(const char *nptr, char **endptr, int base) 4915c1c147SMadhukar Pappireddy { 5015c1c147SMadhukar Pappireddy const char *s; 5115c1c147SMadhukar Pappireddy unsigned long acc; 5215c1c147SMadhukar Pappireddy char c; 5315c1c147SMadhukar Pappireddy unsigned long cutoff; 5415c1c147SMadhukar Pappireddy int neg, any, cutlim; 55*4d7238bbSGovindraj Raja unsigned long long extended; 5615c1c147SMadhukar Pappireddy 5715c1c147SMadhukar Pappireddy /* 5815c1c147SMadhukar Pappireddy * See strtol for comments as to the logic used. 5915c1c147SMadhukar Pappireddy */ 6015c1c147SMadhukar Pappireddy s = nptr; 6115c1c147SMadhukar Pappireddy do { 6215c1c147SMadhukar Pappireddy c = *s++; 6315c1c147SMadhukar Pappireddy } while (isspace((unsigned char)c)); 6415c1c147SMadhukar Pappireddy if (c == '-') { 6515c1c147SMadhukar Pappireddy neg = 1; 6615c1c147SMadhukar Pappireddy c = *s++; 6715c1c147SMadhukar Pappireddy } else { 6815c1c147SMadhukar Pappireddy neg = 0; 6915c1c147SMadhukar Pappireddy if (c == '+') 7015c1c147SMadhukar Pappireddy c = *s++; 7115c1c147SMadhukar Pappireddy } 7215c1c147SMadhukar Pappireddy if ((base == 0 || base == 16) && 7315c1c147SMadhukar Pappireddy c == '0' && (*s == 'x' || *s == 'X') && 7415c1c147SMadhukar Pappireddy ((s[1] >= '0' && s[1] <= '9') || 7515c1c147SMadhukar Pappireddy (s[1] >= 'A' && s[1] <= 'F') || 7615c1c147SMadhukar Pappireddy (s[1] >= 'a' && s[1] <= 'f'))) { 7715c1c147SMadhukar Pappireddy c = s[1]; 7815c1c147SMadhukar Pappireddy s += 2; 7915c1c147SMadhukar Pappireddy base = 16; 8015c1c147SMadhukar Pappireddy } 8115c1c147SMadhukar Pappireddy if (base == 0) 8215c1c147SMadhukar Pappireddy base = c == '0' ? 8 : 10; 8315c1c147SMadhukar Pappireddy acc = any = 0; 8415c1c147SMadhukar Pappireddy 8515c1c147SMadhukar Pappireddy cutoff = ULONG_MAX / base; 8615c1c147SMadhukar Pappireddy cutlim = ULONG_MAX % base; 8715c1c147SMadhukar Pappireddy for ( ; ; c = *s++) { 8815c1c147SMadhukar Pappireddy if (c >= '0' && c <= '9') 8915c1c147SMadhukar Pappireddy c -= '0'; 9015c1c147SMadhukar Pappireddy else if (c >= 'A' && c <= 'Z') 9115c1c147SMadhukar Pappireddy c -= 'A' - 10; 9215c1c147SMadhukar Pappireddy else if (c >= 'a' && c <= 'z') 9315c1c147SMadhukar Pappireddy c -= 'a' - 10; 9415c1c147SMadhukar Pappireddy else 9515c1c147SMadhukar Pappireddy break; 9615c1c147SMadhukar Pappireddy if (c >= base) 9715c1c147SMadhukar Pappireddy break; 9815c1c147SMadhukar Pappireddy if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) 9915c1c147SMadhukar Pappireddy any = -1; 10015c1c147SMadhukar Pappireddy else { 101*4d7238bbSGovindraj Raja extended = (unsigned long long)acc * (unsigned)base; 102*4d7238bbSGovindraj Raja extended += (unsigned)c; 103*4d7238bbSGovindraj Raja 104*4d7238bbSGovindraj Raja if (extended > (unsigned long long)ULONG_MAX) { 105*4d7238bbSGovindraj Raja any = -1; 106*4d7238bbSGovindraj Raja } else { 107*4d7238bbSGovindraj Raja acc = (unsigned long)extended; 10815c1c147SMadhukar Pappireddy any = 1; 109*4d7238bbSGovindraj Raja } 11015c1c147SMadhukar Pappireddy } 11115c1c147SMadhukar Pappireddy } 11215c1c147SMadhukar Pappireddy if (any < 0) { 11315c1c147SMadhukar Pappireddy acc = ULONG_MAX; 11415c1c147SMadhukar Pappireddy } else if (neg) 11515c1c147SMadhukar Pappireddy acc = -acc; 11615c1c147SMadhukar Pappireddy if (endptr != NULL) 11715c1c147SMadhukar Pappireddy *endptr = (char *)(any ? s - 1 : nptr); 11815c1c147SMadhukar Pappireddy return (acc); 11915c1c147SMadhukar Pappireddy } 120