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