1157016Sdes/* $OpenBSD: strtoll.c,v 1.6 2005/11/10 10:00:17 espie Exp $ */ 2149749Sdes/*- 3149749Sdes * Copyright (c) 1992 The Regents of the University of California. 4149749Sdes * All rights reserved. 5149749Sdes * 6149749Sdes * Redistribution and use in source and binary forms, with or without 7149749Sdes * modification, are permitted provided that the following conditions 8149749Sdes * are met: 9149749Sdes * 1. Redistributions of source code must retain the above copyright 10149749Sdes * notice, this list of conditions and the following disclaimer. 11149749Sdes * 2. Redistributions in binary form must reproduce the above copyright 12149749Sdes * notice, this list of conditions and the following disclaimer in the 13149749Sdes * documentation and/or other materials provided with the distribution. 14149749Sdes * 3. Neither the name of the University nor the names of its contributors 15149749Sdes * may be used to endorse or promote products derived from this software 16149749Sdes * without specific prior written permission. 17149749Sdes * 18149749Sdes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19149749Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20149749Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21149749Sdes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22149749Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23149749Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24149749Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25149749Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26149749Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27149749Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28149749Sdes * SUCH DAMAGE. 29149749Sdes */ 30149749Sdes 31157016Sdes/* OPENBSD ORIGINAL: lib/libc/stdlib/strtoll.c */ 32157016Sdes 33149749Sdes#include "includes.h" 34149749Sdes#ifndef HAVE_STRTOLL 35149749Sdes 36149749Sdes#include <sys/types.h> 37149749Sdes 38149749Sdes#include <ctype.h> 39149749Sdes#include <errno.h> 40149749Sdes#include <limits.h> 41149749Sdes#include <stdlib.h> 42149749Sdes 43149749Sdes/* 44149749Sdes * Convert a string to a long long. 45149749Sdes * 46149749Sdes * Ignores `locale' stuff. Assumes that the upper and lower case 47149749Sdes * alphabets and digits are each contiguous. 48149749Sdes */ 49149749Sdeslong long 50149749Sdesstrtoll(const char *nptr, char **endptr, int base) 51149749Sdes{ 52149749Sdes const char *s; 53149749Sdes long long acc, cutoff; 54149749Sdes int c; 55149749Sdes int neg, any, cutlim; 56149749Sdes 57149749Sdes /* 58149749Sdes * Skip white space and pick up leading +/- sign if any. 59149749Sdes * If base is 0, allow 0x for hex and 0 for octal, else 60149749Sdes * assume decimal; if base is already 16, allow 0x. 61149749Sdes */ 62149749Sdes s = nptr; 63149749Sdes do { 64149749Sdes c = (unsigned char) *s++; 65149749Sdes } while (isspace(c)); 66149749Sdes if (c == '-') { 67149749Sdes neg = 1; 68149749Sdes c = *s++; 69149749Sdes } else { 70149749Sdes neg = 0; 71149749Sdes if (c == '+') 72149749Sdes c = *s++; 73149749Sdes } 74149749Sdes if ((base == 0 || base == 16) && 75149749Sdes c == '0' && (*s == 'x' || *s == 'X')) { 76149749Sdes c = s[1]; 77149749Sdes s += 2; 78149749Sdes base = 16; 79149749Sdes } 80149749Sdes if (base == 0) 81149749Sdes base = c == '0' ? 8 : 10; 82149749Sdes 83149749Sdes /* 84149749Sdes * Compute the cutoff value between legal numbers and illegal 85149749Sdes * numbers. That is the largest legal value, divided by the 86149749Sdes * base. An input number that is greater than this value, if 87149749Sdes * followed by a legal input character, is too big. One that 88149749Sdes * is equal to this value may be valid or not; the limit 89149749Sdes * between valid and invalid numbers is then based on the last 90149749Sdes * digit. For instance, if the range for long longs is 91149749Sdes * [-9223372036854775808..9223372036854775807] and the input base 92149749Sdes * is 10, cutoff will be set to 922337203685477580 and cutlim to 93149749Sdes * either 7 (neg==0) or 8 (neg==1), meaning that if we have 94149749Sdes * accumulated a value > 922337203685477580, or equal but the 95149749Sdes * next digit is > 7 (or 8), the number is too big, and we will 96149749Sdes * return a range error. 97149749Sdes * 98149749Sdes * Set any if any `digits' consumed; make it negative to indicate 99149749Sdes * overflow. 100149749Sdes */ 101149749Sdes cutoff = neg ? LLONG_MIN : LLONG_MAX; 102149749Sdes cutlim = cutoff % base; 103149749Sdes cutoff /= base; 104149749Sdes if (neg) { 105149749Sdes if (cutlim > 0) { 106149749Sdes cutlim -= base; 107149749Sdes cutoff += 1; 108149749Sdes } 109149749Sdes cutlim = -cutlim; 110149749Sdes } 111149749Sdes for (acc = 0, any = 0;; c = (unsigned char) *s++) { 112149749Sdes if (isdigit(c)) 113149749Sdes c -= '0'; 114149749Sdes else if (isalpha(c)) 115149749Sdes c -= isupper(c) ? 'A' - 10 : 'a' - 10; 116149749Sdes else 117149749Sdes break; 118149749Sdes if (c >= base) 119149749Sdes break; 120149749Sdes if (any < 0) 121149749Sdes continue; 122149749Sdes if (neg) { 123149749Sdes if (acc < cutoff || (acc == cutoff && c > cutlim)) { 124149749Sdes any = -1; 125149749Sdes acc = LLONG_MIN; 126149749Sdes errno = ERANGE; 127149749Sdes } else { 128149749Sdes any = 1; 129149749Sdes acc *= base; 130149749Sdes acc -= c; 131149749Sdes } 132149749Sdes } else { 133149749Sdes if (acc > cutoff || (acc == cutoff && c > cutlim)) { 134149749Sdes any = -1; 135149749Sdes acc = LLONG_MAX; 136149749Sdes errno = ERANGE; 137149749Sdes } else { 138149749Sdes any = 1; 139149749Sdes acc *= base; 140149749Sdes acc += c; 141149749Sdes } 142149749Sdes } 143149749Sdes } 144149749Sdes if (endptr != 0) 145149749Sdes *endptr = (char *) (any ? s - 1 : nptr); 146149749Sdes return (acc); 147149749Sdes} 148149749Sdes#endif /* HAVE_STRTOLL */ 149