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