1 | /* $NetBSD: _strtoul.h,v 1.10 2016/11/05 21:11:30 riastradh 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 | * Original version ID: |
32 | * NetBSD: src/lib/libc/locale/_wcstoul.h,v 1.2 2003/08/07 16:43:03 agc Exp |
33 | */ |
34 | |
35 | /* |
36 | * function template for strtoul, strtoull and strtoumax. |
37 | * |
38 | * parameters: |
39 | * _FUNCNAME : function name |
40 | * __UINT : return type |
41 | * __UINT_MAX : upper limit of the return type |
42 | */ |
43 | #if defined(_KERNEL) || defined(_STANDALONE) || \ |
44 | defined(HAVE_NBTOOL_CONFIG_H) || defined(BCS_ONLY) |
45 | __UINT |
46 | _FUNCNAME(const char *nptr, char **endptr, int base) |
47 | #else |
48 | #include <locale.h> |
49 | #include "setlocale_local.h" |
50 | #define INT_FUNCNAME_(pre, name, post) pre ## name ## post |
51 | #define INT_FUNCNAME(pre, name, post) INT_FUNCNAME_(pre, name, post) |
52 | |
53 | static __UINT |
54 | INT_FUNCNAME(_int_, _FUNCNAME, _l)(const char *nptr, char **endptr, |
55 | int base, locale_t loc) |
56 | #endif |
57 | { |
58 | const char *s; |
59 | __UINT acc, cutoff; |
60 | unsigned char c; |
61 | int i, neg, any, cutlim; |
62 | |
63 | _DIAGASSERT(nptr != NULL); |
64 | /* endptr may be NULL */ |
65 | |
66 | /* check base value */ |
67 | if (base && (base < 2 || base > 36)) { |
68 | #if !defined(_KERNEL) && !defined(_STANDALONE) |
69 | errno = EINVAL; |
70 | if (endptr != NULL) |
71 | /* LINTED interface specification */ |
72 | *endptr = __UNCONST(nptr); |
73 | return 0; |
74 | #else |
75 | panic("%s: invalid base %d" , __func__, base); |
76 | #endif |
77 | } |
78 | |
79 | /* |
80 | * Skip white space and pick up leading +/- sign if any. |
81 | * If base is 0, allow 0x for hex and 0 for octal, else |
82 | * assume decimal; if base is already 16, allow 0x. |
83 | */ |
84 | s = nptr; |
85 | #if defined(_KERNEL) || defined(_STANDALONE) || \ |
86 | defined(HAVE_NBTOOL_CONFIG_H) || defined(BCS_ONLY) |
87 | do { |
88 | c = *s++; |
89 | } while (isspace(c)); |
90 | #else |
91 | do { |
92 | c = *s++; |
93 | } while (isspace_l(c, loc)); |
94 | #endif |
95 | if (c == '-') { |
96 | neg = 1; |
97 | c = *s++; |
98 | } else { |
99 | neg = 0; |
100 | if (c == '+') |
101 | c = *s++; |
102 | } |
103 | if ((base == 0 || base == 16) && |
104 | c == '0' && (*s == 'x' || *s == 'X')) { |
105 | c = s[1]; |
106 | s += 2; |
107 | base = 16; |
108 | #if 0 |
109 | } else if ((base == 0 || base == 2) && |
110 | c == '0' && (*s == 'b' || *s == 'B')) { |
111 | c = s[1]; |
112 | s += 2; |
113 | base = 2; |
114 | #endif |
115 | } else if (base == 0) |
116 | base = (c == '0' ? 8 : 10); |
117 | |
118 | /* |
119 | * See strtol for comments as to the logic used. |
120 | */ |
121 | cutoff = ((__UINT)__UINT_MAX / (__UINT)base); |
122 | cutlim = (int)((__UINT)__UINT_MAX % (__UINT)base); |
123 | for (acc = 0, any = 0;; c = *s++) { |
124 | if (c >= '0' && c <= '9') |
125 | i = c - '0'; |
126 | else if (c >= 'a' && c <= 'z') |
127 | i = (c - 'a') + 10; |
128 | else if (c >= 'A' && c <= 'Z') |
129 | i = (c - 'A') + 10; |
130 | else |
131 | break; |
132 | if (i >= base) |
133 | break; |
134 | if (any < 0) |
135 | continue; |
136 | if (acc > cutoff || (acc == cutoff && i > cutlim)) { |
137 | acc = __UINT_MAX; |
138 | #if !defined(_KERNEL) && !defined(_STANDALONE) |
139 | any = -1; |
140 | errno = ERANGE; |
141 | #else |
142 | any = 0; |
143 | break; |
144 | #endif |
145 | } else { |
146 | any = 1; |
147 | acc *= (__UINT)base; |
148 | acc += i; |
149 | } |
150 | } |
151 | if (neg && any > 0) |
152 | acc = -acc; |
153 | if (endptr != NULL) |
154 | /* LINTED interface specification */ |
155 | *endptr = __UNCONST(any ? s - 1 : nptr); |
156 | return(acc); |
157 | } |
158 | |
159 | #if !defined(_KERNEL) && !defined(_STANDALONE) && \ |
160 | !defined(HAVE_NBTOOL_CONFIG_H) && !defined(BCS_ONLY) |
161 | __UINT |
162 | _FUNCNAME(const char *nptr, char **endptr, int base) |
163 | { |
164 | return INT_FUNCNAME(_int_, _FUNCNAME, _l)(nptr, endptr, base, _current_locale()); |
165 | } |
166 | |
167 | __UINT |
168 | INT_FUNCNAME(, _FUNCNAME, _l)(const char *nptr, char **endptr, int base, locale_t loc) |
169 | { |
170 | return INT_FUNCNAME(_int_, _FUNCNAME, _l)(nptr, endptr, base, loc); |
171 | } |
172 | #endif |
173 | |