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