15fd17624STim J. Robbins /*- 2*8a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 3*8a16b7a1SPedro F. Giffuni * 45fd17624STim J. Robbins * Copyright (c) 1990, 1993 55fd17624STim J. Robbins * The Regents of the University of California. All rights reserved. 65fd17624STim J. Robbins * 73c87aa1dSDavid Chisnall * Copyright (c) 2011 The FreeBSD Foundation 83c87aa1dSDavid Chisnall * All rights reserved. 93c87aa1dSDavid Chisnall * Portions of this software were developed by David Chisnall 103c87aa1dSDavid Chisnall * under sponsorship from the FreeBSD Foundation. 113c87aa1dSDavid Chisnall * 125fd17624STim J. Robbins * Redistribution and use in source and binary forms, with or without 135fd17624STim J. Robbins * modification, are permitted provided that the following conditions 145fd17624STim J. Robbins * are met: 155fd17624STim J. Robbins * 1. Redistributions of source code must retain the above copyright 165fd17624STim J. Robbins * notice, this list of conditions and the following disclaimer. 175fd17624STim J. Robbins * 2. Redistributions in binary form must reproduce the above copyright 185fd17624STim J. Robbins * notice, this list of conditions and the following disclaimer in the 195fd17624STim J. Robbins * documentation and/or other materials provided with the distribution. 20fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 215fd17624STim J. Robbins * may be used to endorse or promote products derived from this software 225fd17624STim J. Robbins * without specific prior written permission. 235fd17624STim J. Robbins * 245fd17624STim J. Robbins * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 255fd17624STim J. Robbins * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 265fd17624STim J. Robbins * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 275fd17624STim J. Robbins * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 285fd17624STim J. Robbins * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 295fd17624STim J. Robbins * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 305fd17624STim J. Robbins * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 315fd17624STim J. Robbins * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 325fd17624STim J. Robbins * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 335fd17624STim J. Robbins * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 345fd17624STim J. Robbins * SUCH DAMAGE. 355fd17624STim J. Robbins */ 365fd17624STim J. Robbins 375fd17624STim J. Robbins #include <sys/cdefs.h> 385fd17624STim J. Robbins __FBSDID("$FreeBSD$"); 395fd17624STim J. Robbins 405fd17624STim J. Robbins #include <ctype.h> 415fd17624STim J. Robbins #include <errno.h> 425fd17624STim J. Robbins #include <limits.h> 435fd17624STim J. Robbins #include <wchar.h> 445fd17624STim J. Robbins #include <wctype.h> 453c87aa1dSDavid Chisnall #include "xlocale_private.h" 465fd17624STim J. Robbins 475fd17624STim J. Robbins /* 485fd17624STim J. Robbins * Convert a string to a long integer. 495fd17624STim J. Robbins */ 505fd17624STim J. Robbins long 513c87aa1dSDavid Chisnall wcstol_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int 523c87aa1dSDavid Chisnall base, locale_t locale) 535fd17624STim J. Robbins { 545fd17624STim J. Robbins const wchar_t *s; 555fd17624STim J. Robbins unsigned long acc; 565fd17624STim J. Robbins wchar_t c; 575fd17624STim J. Robbins unsigned long cutoff; 585fd17624STim J. Robbins int neg, any, cutlim; 593c87aa1dSDavid Chisnall FIX_LOCALE(locale); 605fd17624STim J. Robbins 615fd17624STim J. Robbins /* 625fd17624STim J. Robbins * See strtol for comments as to the logic used. 635fd17624STim J. Robbins */ 645fd17624STim J. Robbins s = nptr; 655fd17624STim J. Robbins do { 665fd17624STim J. Robbins c = *s++; 673c87aa1dSDavid Chisnall } while (iswspace_l(c, locale)); 685fd17624STim J. Robbins if (c == '-') { 695fd17624STim J. Robbins neg = 1; 705fd17624STim J. Robbins c = *s++; 715fd17624STim J. Robbins } else { 725fd17624STim J. Robbins neg = 0; 735fd17624STim J. Robbins if (c == L'+') 745fd17624STim J. Robbins c = *s++; 755fd17624STim J. Robbins } 765fd17624STim J. Robbins if ((base == 0 || base == 16) && 775fd17624STim J. Robbins c == L'0' && (*s == L'x' || *s == L'X')) { 785fd17624STim J. Robbins c = s[1]; 795fd17624STim J. Robbins s += 2; 805fd17624STim J. Robbins base = 16; 815fd17624STim J. Robbins } 825fd17624STim J. Robbins if (base == 0) 835fd17624STim J. Robbins base = c == L'0' ? 8 : 10; 845fd17624STim J. Robbins acc = any = 0; 855fd17624STim J. Robbins if (base < 2 || base > 36) 865fd17624STim J. Robbins goto noconv; 875fd17624STim J. Robbins 885fd17624STim J. Robbins cutoff = neg ? (unsigned long)-(LONG_MIN + LONG_MAX) + LONG_MAX 895fd17624STim J. Robbins : LONG_MAX; 905fd17624STim J. Robbins cutlim = cutoff % base; 915fd17624STim J. Robbins cutoff /= base; 925fd17624STim J. Robbins for ( ; ; c = *s++) { 935fd17624STim J. Robbins #ifdef notyet 943c87aa1dSDavid Chisnall if (iswdigit_l(c, locale)) 953c87aa1dSDavid Chisnall c = digittoint_l(c, locale); 965fd17624STim J. Robbins else 975fd17624STim J. Robbins #endif 985fd17624STim J. Robbins if (c >= L'0' && c <= L'9') 995fd17624STim J. Robbins c -= L'0'; 1005fd17624STim J. Robbins else if (c >= L'A' && c <= L'Z') 1015fd17624STim J. Robbins c -= L'A' - 10; 1025fd17624STim J. Robbins else if (c >= L'a' && c <= L'z') 1035fd17624STim J. Robbins c -= L'a' - 10; 1045fd17624STim J. Robbins else 1055fd17624STim J. Robbins break; 1065fd17624STim J. Robbins if (c >= base) 1075fd17624STim J. Robbins break; 1085fd17624STim J. Robbins if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) 1095fd17624STim J. Robbins any = -1; 1105fd17624STim J. Robbins else { 1115fd17624STim J. Robbins any = 1; 1125fd17624STim J. Robbins acc *= base; 1135fd17624STim J. Robbins acc += c; 1145fd17624STim J. Robbins } 1155fd17624STim J. Robbins } 1165fd17624STim J. Robbins if (any < 0) { 1175fd17624STim J. Robbins acc = neg ? LONG_MIN : LONG_MAX; 1185fd17624STim J. Robbins errno = ERANGE; 1195fd17624STim J. Robbins } else if (!any) { 1205fd17624STim J. Robbins noconv: 1215fd17624STim J. Robbins errno = EINVAL; 1225fd17624STim J. Robbins } else if (neg) 1235fd17624STim J. Robbins acc = -acc; 1245fd17624STim J. Robbins if (endptr != NULL) 1255fd17624STim J. Robbins *endptr = (wchar_t *)(any ? s - 1 : nptr); 1265fd17624STim J. Robbins return (acc); 1275fd17624STim J. Robbins } 1283c87aa1dSDavid Chisnall long 1293c87aa1dSDavid Chisnall wcstol(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base) 1303c87aa1dSDavid Chisnall { 1313c87aa1dSDavid Chisnall return wcstol_l(nptr, endptr, base, __get_locale()); 1323c87aa1dSDavid Chisnall } 133