• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*  $NetBSD: strtoumax.c,v 1.1 2006/04/22 15:33:33 thorpej Exp $  */
2 
3 /*
4  * Copyright (c) 1990, 1993
5  *  The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 #include  <LibConfig.h>
32 #include <sys/EfiCdefs.h>
33 
34 #if !defined(_KERNEL) && !defined(_STANDALONE)
35 #if defined(LIBC_SCCS) && !defined(lint)
36 #if 0
37 static char sccsid[] = "from: @(#)strtoul.c 8.1 (Berkeley) 6/4/93";
38 #else
39 __RCSID("$NetBSD: strtoumax.c,v 1.1 2006/04/22 15:33:33 thorpej Exp $");
40 #endif
41 #endif /* LIBC_SCCS and not lint */
42 
43 #include "namespace.h"
44 
45 #include <assert.h>
46 #include <ctype.h>
47 #include <errno.h>
48 #include <inttypes.h>
49 #include <stddef.h>
50 
51 #include <Library/BaseLib.h>
52 
53 #ifdef __weak_alias
__weak_alias(strtoumax,_strtoumax)54 __weak_alias(strtoumax, _strtoumax)
55 #endif
56 
57 #else /* !_KERNEL && !_STANDALONE */
58 #include <sys/param.h>
59 #include <lib/libkern/libkern.h>
60 #endif /* !_KERNEL && !_STANDALONE */
61 
62 /*
63  * Convert a string to an uintmax_t.
64  *
65  * Ignores `locale' stuff.  Assumes that the upper and lower case
66  * alphabets and digits are each contiguous.
67  */
68 uintmax_t
69 strtoumax(const char *nptr, char **endptr, int base)
70 {
71   const char *s;
72   uintmax_t acc, cutoff;
73   int c;
74   int neg, any, cutlim;
75 
76   _DIAGASSERT(nptr != NULL);
77   /* endptr may be NULL */
78 
79   /*
80    * See strtol for comments as to the logic used.
81    */
82   s = nptr;
83   do {
84     c = (unsigned char) *s++;
85   } while (isspace(c));
86   if (c == '-') {
87     neg = 1;
88     c = *s++;
89   } else {
90     neg = 0;
91     if (c == '+')
92       c = *s++;
93   }
94   if ((base == 0 || base == 16) &&
95       c == '0' && (*s == 'x' || *s == 'X')) {
96     c = s[1];
97     s += 2;
98     base = 16;
99   }
100   if (base == 0)
101     base = c == '0' ? 8 : 10;
102 
103   cutoff = DivU64x32 ((UINT64) UINTMAX_MAX, (UINT32) base);
104   cutlim = (int) ModU64x32 ((UINT64) UINTMAX_MAX, (UINT32) base);
105   for (acc = 0, any = 0;; c = (unsigned char) *s++) {
106     if (isdigit(c))
107       c -= '0';
108     else if (isalpha(c)) {
109 #if defined(_KERNEL) || defined(_STANDALONE)
110       c = toupper(c) - 'A' + 10;
111 #else
112       c -= isupper(c) ? 'A' - 10 : 'a' - 10;
113 #endif
114     } else
115       break;
116     if (c >= base)
117       break;
118     if (any < 0)
119       continue;
120     if (acc > cutoff || (acc == cutoff && c > cutlim)) {
121 #if defined(_KERNEL) || defined(_STANDALONE)
122       if (endptr)
123         *endptr = __UNCONST(nptr);
124       return UINTMAX_MAX;
125 #else
126       any = -1;
127       acc = UINTMAX_MAX;
128       errno = ERANGE;
129 #endif
130     } else {
131       any = 1;
132       acc *= (uintmax_t)base;
133       acc += c;
134     }
135   }
136   if (neg && any > 0)
137     acc = (uintmax_t)(-((intmax_t)acc));
138   if (endptr != 0)
139     *endptr = __UNCONST(any ? s - 1 : nptr);
140   return (acc);
141 }
142