1f9f848faSopenharmony_ci/*- 2f9f848faSopenharmony_ci * SPDX-License-Identifier: BSD-3-Clause 3f9f848faSopenharmony_ci * 4f9f848faSopenharmony_ci * Copyright (c) 1992, 1993 5f9f848faSopenharmony_ci * The Regents of the University of California. All rights reserved. 6f9f848faSopenharmony_ci * 7f9f848faSopenharmony_ci * Copyright (c) 2011 The FreeBSD Foundation 8f9f848faSopenharmony_ci * 9f9f848faSopenharmony_ci * Portions of this software were developed by David Chisnall 10f9f848faSopenharmony_ci * under sponsorship from the FreeBSD Foundation. 11f9f848faSopenharmony_ci * 12f9f848faSopenharmony_ci * Redistribution and use in source and binary forms, with or without 13f9f848faSopenharmony_ci * modification, are permitted provided that the following conditions 14f9f848faSopenharmony_ci * are met: 15f9f848faSopenharmony_ci * 1. Redistributions of source code must retain the above copyright 16f9f848faSopenharmony_ci * notice, this list of conditions and the following disclaimer. 17f9f848faSopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright 18f9f848faSopenharmony_ci * notice, this list of conditions and the following disclaimer in the 19f9f848faSopenharmony_ci * documentation and/or other materials provided with the distribution. 20f9f848faSopenharmony_ci * 3. Neither the name of the University nor the names of its contributors 21f9f848faSopenharmony_ci * may be used to endorse or promote products derived from this software 22f9f848faSopenharmony_ci * without specific prior written permission. 23f9f848faSopenharmony_ci * 24f9f848faSopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25f9f848faSopenharmony_ci * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26f9f848faSopenharmony_ci * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27f9f848faSopenharmony_ci * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28f9f848faSopenharmony_ci * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29f9f848faSopenharmony_ci * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30f9f848faSopenharmony_ci * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31f9f848faSopenharmony_ci * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32f9f848faSopenharmony_ci * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33f9f848faSopenharmony_ci * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34f9f848faSopenharmony_ci * SUCH DAMAGE. 35f9f848faSopenharmony_ci */ 36f9f848faSopenharmony_ci 37f9f848faSopenharmony_ci#if defined(LIBC_SCCS) && !defined(lint) 38f9f848faSopenharmony_cistatic char sccsid[] = "from @(#)strtol.c 8.1 (Berkeley) 6/4/93"; 39f9f848faSopenharmony_ci#endif /* LIBC_SCCS and not lint */ 40f9f848faSopenharmony_ci// #include <sys/cdefs.h> 41f9f848faSopenharmony_ci// __FBSDID("$FreeBSD$"); 42f9f848faSopenharmony_ci 43f9f848faSopenharmony_ci#include <ctype.h> 44f9f848faSopenharmony_ci#include <errno.h> 45f9f848faSopenharmony_ci#include <stdlib.h> 46f9f848faSopenharmony_ci#include <inttypes.h> 47f9f848faSopenharmony_ci// #include "xlocale_private.h" 48f9f848faSopenharmony_ci 49f9f848faSopenharmony_ci/* 50f9f848faSopenharmony_ci * Convert a string to an intmax_t integer. 51f9f848faSopenharmony_ci * 52f9f848faSopenharmony_ci * Assumes that the upper and lower case 53f9f848faSopenharmony_ci * alphabets and digits are each contiguous. 54f9f848faSopenharmony_ci */ 55f9f848faSopenharmony_ciintmax_t 56f9f848faSopenharmony_cistrtoimax_l(const char * __restrict nptr, char ** __restrict endptr, int base) 57f9f848faSopenharmony_ci{ 58f9f848faSopenharmony_ci const char *s; 59f9f848faSopenharmony_ci uintmax_t acc; 60f9f848faSopenharmony_ci char c; 61f9f848faSopenharmony_ci uintmax_t cutoff; 62f9f848faSopenharmony_ci int neg, any, cutlim; 63f9f848faSopenharmony_ci // FIX_LOCALE(locale); 64f9f848faSopenharmony_ci 65f9f848faSopenharmony_ci /* 66f9f848faSopenharmony_ci * Skip white space and pick up leading +/- sign if any. 67f9f848faSopenharmony_ci * If base is 0, allow 0x for hex and 0 for octal, else 68f9f848faSopenharmony_ci * assume decimal; if base is already 16, allow 0x. 69f9f848faSopenharmony_ci */ 70f9f848faSopenharmony_ci s = nptr; 71f9f848faSopenharmony_ci do { 72f9f848faSopenharmony_ci c = *s++; 73f9f848faSopenharmony_ci } while (isspace((unsigned char)c)); 74f9f848faSopenharmony_ci if (c == '-') { 75f9f848faSopenharmony_ci neg = 1; 76f9f848faSopenharmony_ci c = *s++; 77f9f848faSopenharmony_ci } else { 78f9f848faSopenharmony_ci neg = 0; 79f9f848faSopenharmony_ci if (c == '+') { 80f9f848faSopenharmony_ci c = *s++; 81f9f848faSopenharmony_ci } 82f9f848faSopenharmony_ci } 83f9f848faSopenharmony_ci if ((base == 0 || base == 16) && 84f9f848faSopenharmony_ci c == '0' && (*s == 'x' || *s == 'X') && 85f9f848faSopenharmony_ci ((s[1] >= '0' && s[1] <= '9') || 86f9f848faSopenharmony_ci (s[1] >= 'A' && s[1] <= 'F') || 87f9f848faSopenharmony_ci (s[1] >= 'a' && s[1] <= 'f'))) { 88f9f848faSopenharmony_ci c = s[1]; 89f9f848faSopenharmony_ci s += 2; 90f9f848faSopenharmony_ci base = 16; 91f9f848faSopenharmony_ci } 92f9f848faSopenharmony_ci if (base == 0) { 93f9f848faSopenharmony_ci base = c == '0' ? 8 : 10; 94f9f848faSopenharmony_ci } 95f9f848faSopenharmony_ci acc = any = 0; 96f9f848faSopenharmony_ci if (base < 2 || base > 36) { 97f9f848faSopenharmony_ci goto noconv; 98f9f848faSopenharmony_ci } 99f9f848faSopenharmony_ci 100f9f848faSopenharmony_ci /* 101f9f848faSopenharmony_ci * Compute the cutoff value between legal numbers and illegal 102f9f848faSopenharmony_ci * numbers. That is the largest legal value, divided by the 103f9f848faSopenharmony_ci * base. An input number that is greater than this value, if 104f9f848faSopenharmony_ci * followed by a legal input character, is too big. One that 105f9f848faSopenharmony_ci * is equal to this value may be valid or not; the limit 106f9f848faSopenharmony_ci * between valid and invalid numbers is then based on the last 107f9f848faSopenharmony_ci * digit. For instance, if the range for intmax_t is 108f9f848faSopenharmony_ci * [-9223372036854775808..9223372036854775807] and the input base 109f9f848faSopenharmony_ci * is 10, cutoff will be set to 922337203685477580 and cutlim to 110f9f848faSopenharmony_ci * either 7 (neg==0) or 8 (neg==1), meaning that if we have 111f9f848faSopenharmony_ci * accumulated a value > 922337203685477580, or equal but the 112f9f848faSopenharmony_ci * next digit is > 7 (or 8), the number is too big, and we will 113f9f848faSopenharmony_ci * return a range error. 114f9f848faSopenharmony_ci * 115f9f848faSopenharmony_ci * Set 'any' if any `digits' consumed; make it negative to indicate 116f9f848faSopenharmony_ci * overflow. 117f9f848faSopenharmony_ci */ 118f9f848faSopenharmony_ci cutoff = neg ? (uintmax_t)-(INTMAX_MIN + INTMAX_MAX) + INTMAX_MAX 119f9f848faSopenharmony_ci : INTMAX_MAX; 120f9f848faSopenharmony_ci cutlim = cutoff % base; 121f9f848faSopenharmony_ci cutoff /= base; 122f9f848faSopenharmony_ci for (;; c = *s++) { 123f9f848faSopenharmony_ci if (c >= '0' && c <= '9') { 124f9f848faSopenharmony_ci c -= '0'; 125f9f848faSopenharmony_ci } else if (c >= 'A' && c <= 'Z') { 126f9f848faSopenharmony_ci c -= 'A' - 10; 127f9f848faSopenharmony_ci } else if (c >= 'a' && c <= 'z') { 128f9f848faSopenharmony_ci c -= 'a' - 10; 129f9f848faSopenharmony_ci } else { 130f9f848faSopenharmony_ci break; 131f9f848faSopenharmony_ci } 132f9f848faSopenharmony_ci if (c >= base) { 133f9f848faSopenharmony_ci break; 134f9f848faSopenharmony_ci } 135f9f848faSopenharmony_ci if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) { 136f9f848faSopenharmony_ci any = -1; 137f9f848faSopenharmony_ci } else { 138f9f848faSopenharmony_ci any = 1; 139f9f848faSopenharmony_ci acc *= base; 140f9f848faSopenharmony_ci acc += c; 141f9f848faSopenharmony_ci } 142f9f848faSopenharmony_ci } 143f9f848faSopenharmony_ci if (any < 0) { 144f9f848faSopenharmony_ci acc = neg ? INTMAX_MIN : INTMAX_MAX; 145f9f848faSopenharmony_ci errno = ERANGE; 146f9f848faSopenharmony_ci } else if (!any) { 147f9f848faSopenharmony_cinoconv: 148f9f848faSopenharmony_ci errno = EINVAL; 149f9f848faSopenharmony_ci } else if (neg) { 150f9f848faSopenharmony_ci acc = -acc; 151f9f848faSopenharmony_ci } 152f9f848faSopenharmony_ci if (endptr != NULL) { 153f9f848faSopenharmony_ci *endptr = (char *)(any ? s - 1 : nptr); 154f9f848faSopenharmony_ci } 155f9f848faSopenharmony_ci return (acc); 156f9f848faSopenharmony_ci} 157f9f848faSopenharmony_ciintmax_t 158f9f848faSopenharmony_cistrtoimax(const char * __restrict nptr, char ** __restrict endptr, int base) 159f9f848faSopenharmony_ci{ 160f9f848faSopenharmony_ci return strtoimax_l(nptr, endptr, base); 161f9f848faSopenharmony_ci} 162