Line | Count | Source (jump to first uncovered line) |
1 | | /* Convert string representation of a number into an integer value. |
2 | | |
3 | | Copyright (C) 1991-1992, 1994-1999, 2003, 2005-2007, 2009-2025 Free Software |
4 | | Foundation, Inc. |
5 | | |
6 | | NOTE: The canonical source of this file is maintained with the GNU C |
7 | | Library. Bugs can be reported to bug-glibc@gnu.org. |
8 | | |
9 | | This file is free software: you can redistribute it and/or modify |
10 | | it under the terms of the GNU Lesser General Public License as |
11 | | published by the Free Software Foundation, either version 3 of the |
12 | | License, or (at your option) any later version. |
13 | | |
14 | | This file is distributed in the hope that it will be useful, |
15 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | | GNU Lesser General Public License for more details. |
18 | | |
19 | | You should have received a copy of the GNU Lesser General Public License |
20 | | along with this program. If not, see <https://www.gnu.org/licenses/>. */ |
21 | | |
22 | | #ifdef _LIBC |
23 | | # define USE_NUMBER_GROUPING |
24 | | #else |
25 | | # include <config.h> |
26 | | #endif |
27 | | |
28 | | #include <ctype.h> |
29 | | #include <errno.h> |
30 | | #ifndef __set_errno |
31 | 1.08k | # define __set_errno(Val) errno = (Val) |
32 | | #endif |
33 | | |
34 | | #include <limits.h> |
35 | | #include <stddef.h> |
36 | | #include <stdlib.h> |
37 | | #include <string.h> |
38 | | |
39 | | #ifdef USE_NUMBER_GROUPING |
40 | | # include "../locale/localeinfo.h" |
41 | | #endif |
42 | | |
43 | | /* Nonzero if we are defining 'strtoul' or 'strtoull', operating on |
44 | | unsigned integers. */ |
45 | | #ifndef UNSIGNED |
46 | | # define UNSIGNED 0 |
47 | | # define INT LONG int |
48 | | #else |
49 | | # define INT unsigned LONG int |
50 | | #endif |
51 | | |
52 | | /* Determine the name. */ |
53 | | #ifdef USE_IN_EXTENDED_LOCALE_MODEL |
54 | | # undef strtol |
55 | | # if UNSIGNED |
56 | | # ifdef USE_WIDE_CHAR |
57 | | # ifdef QUAD |
58 | | # define strtol __wcstoull_l |
59 | | # else |
60 | | # define strtol __wcstoul_l |
61 | | # endif |
62 | | # else |
63 | | # ifdef QUAD |
64 | | # define strtol __strtoull_l |
65 | | # else |
66 | | # define strtol __strtoul_l |
67 | | # endif |
68 | | # endif |
69 | | # else |
70 | | # ifdef USE_WIDE_CHAR |
71 | | # ifdef QUAD |
72 | | # define strtol __wcstoll_l |
73 | | # else |
74 | | # define strtol __wcstol_l |
75 | | # endif |
76 | | # else |
77 | | # ifdef QUAD |
78 | | # define strtol __strtoll_l |
79 | | # else |
80 | | # define strtol __strtol_l |
81 | | # endif |
82 | | # endif |
83 | | # endif |
84 | | #else |
85 | | # if UNSIGNED |
86 | | # undef strtol |
87 | | # ifdef USE_WIDE_CHAR |
88 | | # ifdef QUAD |
89 | | # define strtol wcstoull |
90 | | # else |
91 | | # define strtol wcstoul |
92 | | # endif |
93 | | # else |
94 | | # ifdef QUAD |
95 | | # define strtol strtoull |
96 | | # else |
97 | | # define strtol strtoul |
98 | | # endif |
99 | | # endif |
100 | | # else |
101 | | # ifdef USE_WIDE_CHAR |
102 | | # undef strtol |
103 | | # ifdef QUAD |
104 | | # define strtol wcstoll |
105 | | # else |
106 | | # define strtol wcstol |
107 | | # endif |
108 | | # else |
109 | | # ifdef QUAD |
110 | | # undef strtol |
111 | | # define strtol strtoll |
112 | | # endif |
113 | | # endif |
114 | | # endif |
115 | | #endif |
116 | | |
117 | | /* If QUAD is defined, we are defining 'strtoll' or 'strtoull', |
118 | | operating on 'long long int's. */ |
119 | | #ifdef QUAD |
120 | | # define LONG long long |
121 | 1.83k | # define STRTOL_LONG_MIN LLONG_MIN |
122 | 8.51k | # define STRTOL_LONG_MAX LLONG_MAX |
123 | 47.9k | # define STRTOL_ULONG_MAX ULLONG_MAX |
124 | | # if __GNUC__ == 2 && __GNUC_MINOR__ < 7 |
125 | | /* Work around gcc bug with using this constant. */ |
126 | | static const unsigned long long int maxquad = ULLONG_MAX; |
127 | | # undef STRTOL_ULONG_MAX |
128 | | # define STRTOL_ULONG_MAX maxquad |
129 | | # endif |
130 | | #else |
131 | | # define LONG long |
132 | 0 | # define STRTOL_LONG_MIN LONG_MIN |
133 | 0 | # define STRTOL_LONG_MAX LONG_MAX |
134 | 0 | # define STRTOL_ULONG_MAX ULONG_MAX |
135 | | #endif |
136 | | |
137 | | |
138 | | #ifdef USE_NUMBER_GROUPING |
139 | | # define GROUP_PARAM_PROTO , int group |
140 | | #else |
141 | | # define GROUP_PARAM_PROTO |
142 | | #endif |
143 | | |
144 | | /* We use this code also for the extended locale handling where the |
145 | | function gets as an additional argument the locale which has to be |
146 | | used. To access the values we have to redefine the _NL_CURRENT |
147 | | macro. */ |
148 | | #ifdef USE_IN_EXTENDED_LOCALE_MODEL |
149 | | # undef _NL_CURRENT |
150 | | # define _NL_CURRENT(category, item) \ |
151 | | (current->values[_NL_ITEM_INDEX (item)].string) |
152 | | # define LOCALE_PARAM , loc |
153 | | # define LOCALE_PARAM_PROTO , __locale_t loc |
154 | | #else |
155 | | # define LOCALE_PARAM |
156 | | # define LOCALE_PARAM_PROTO |
157 | | #endif |
158 | | |
159 | | #ifdef USE_WIDE_CHAR |
160 | | # include <wchar.h> |
161 | | # include <wctype.h> |
162 | | # define L_(Ch) L##Ch |
163 | | # define UCHAR_TYPE wint_t |
164 | | # define STRING_TYPE wchar_t |
165 | | # ifdef USE_IN_EXTENDED_LOCALE_MODEL |
166 | | # define ISSPACE(Ch) __iswspace_l ((Ch), loc) |
167 | | # define ISALPHA(Ch) __iswalpha_l ((Ch), loc) |
168 | | # define TOUPPER(Ch) __towupper_l ((Ch), loc) |
169 | | # else |
170 | | # define ISSPACE(Ch) iswspace (Ch) |
171 | | # define ISALPHA(Ch) iswalpha (Ch) |
172 | | # define TOUPPER(Ch) towupper (Ch) |
173 | | # endif |
174 | | #else |
175 | 377k | # define L_(Ch) Ch |
176 | | # define UCHAR_TYPE unsigned char |
177 | | # define STRING_TYPE char |
178 | | # ifdef USE_IN_EXTENDED_LOCALE_MODEL |
179 | | # define ISSPACE(Ch) __isspace_l ((unsigned char) (Ch), loc) |
180 | | # define ISALPHA(Ch) __isalpha_l ((unsigned char) (Ch), loc) |
181 | | # define TOUPPER(Ch) __toupper_l ((unsigned char) (Ch), loc) |
182 | | # else |
183 | | # define ISSPACE(Ch) isspace ((unsigned char) (Ch)) |
184 | 14.3k | # define ISALPHA(Ch) isalpha ((unsigned char) (Ch)) |
185 | 5.98k | # define TOUPPER(Ch) toupper ((unsigned char) (Ch)) |
186 | | # endif |
187 | | #endif |
188 | | |
189 | | #ifdef USE_NUMBER_GROUPING |
190 | | # define INTERNAL(X) INTERNAL1(X) |
191 | | # define INTERNAL1(X) __##X##_internal |
192 | | # define WEAKNAME(X) WEAKNAME1(X) |
193 | | #else |
194 | | # define INTERNAL(X) X |
195 | | #endif |
196 | | |
197 | | #ifdef USE_NUMBER_GROUPING |
198 | | /* This file defines a function to check for correct grouping. */ |
199 | | # include "grouping.h" |
200 | | #endif |
201 | | |
202 | | |
203 | | |
204 | | /* Convert NPTR to an 'unsigned long int' or 'long int' in base BASE. |
205 | | If BASE is 0 the base is determined by the presence of a leading |
206 | | zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal. |
207 | | If BASE is < 2 or > 36, it is reset to 10. |
208 | | If ENDPTR is not NULL, a pointer to the character after the last |
209 | | one converted is stored in *ENDPTR. */ |
210 | | |
211 | | INT |
212 | | INTERNAL (strtol) (const STRING_TYPE *nptr, STRING_TYPE **endptr, |
213 | | int base GROUP_PARAM_PROTO LOCALE_PARAM_PROTO) |
214 | 24.1k | { |
215 | 24.1k | int negative; |
216 | 24.1k | register unsigned LONG int cutoff; |
217 | 24.1k | register unsigned int cutlim; |
218 | 24.1k | register unsigned LONG int i; |
219 | 24.1k | register const STRING_TYPE *s; |
220 | 24.1k | register UCHAR_TYPE c; |
221 | 24.1k | const STRING_TYPE *save, *end; |
222 | 24.1k | int overflow; |
223 | | |
224 | | #ifdef USE_NUMBER_GROUPING |
225 | | # ifdef USE_IN_EXTENDED_LOCALE_MODEL |
226 | | struct locale_data *current = loc->__locales[LC_NUMERIC]; |
227 | | # endif |
228 | | /* The thousands character of the current locale. */ |
229 | | wchar_t thousands = L'\0'; |
230 | | /* The numeric grouping specification of the current locale, |
231 | | in the format described in <locale.h>. */ |
232 | | const char *grouping; |
233 | | |
234 | | if (group) |
235 | | { |
236 | | grouping = _NL_CURRENT (LC_NUMERIC, GROUPING); |
237 | | if (*grouping <= 0 || *grouping == CHAR_MAX) |
238 | | grouping = NULL; |
239 | | else |
240 | | { |
241 | | /* Figure out the thousands separator character. */ |
242 | | # if defined _LIBC || defined _HAVE_BTOWC |
243 | | thousands = __btowc (*_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP)); |
244 | | if (thousands == WEOF) |
245 | | thousands = L'\0'; |
246 | | # endif |
247 | | if (thousands == L'\0') |
248 | | grouping = NULL; |
249 | | } |
250 | | } |
251 | | else |
252 | | grouping = NULL; |
253 | | #endif |
254 | | |
255 | 24.1k | if (base < 0 || base == 1 || base > 36) |
256 | 0 | { |
257 | 0 | __set_errno (EINVAL); |
258 | 0 | return 0; |
259 | 0 | } |
260 | | |
261 | 24.1k | save = s = nptr; |
262 | | |
263 | | /* Skip white space. */ |
264 | 24.1k | while (ISSPACE (*s)) |
265 | 573 | ++s; |
266 | 24.1k | if (*s == L_('\0')) |
267 | 236 | goto noconv; |
268 | | |
269 | | /* Check for a sign. */ |
270 | 23.9k | if (*s == L_('-')) |
271 | 1.78k | { |
272 | 1.78k | negative = 1; |
273 | 1.78k | ++s; |
274 | 1.78k | } |
275 | 22.1k | else if (*s == L_('+')) |
276 | 231 | { |
277 | 231 | negative = 0; |
278 | 231 | ++s; |
279 | 231 | } |
280 | 21.9k | else |
281 | 21.9k | negative = 0; |
282 | | |
283 | | /* Recognize number prefix and if BASE is zero, figure it out ourselves. */ |
284 | 23.9k | if (*s == L_('0')) |
285 | 1.44k | { |
286 | 1.44k | if ((base == 0 || base == 16) && TOUPPER (s[1]) == L_('X')) |
287 | 0 | { |
288 | 0 | s += 2; |
289 | 0 | base = 16; |
290 | 0 | } |
291 | 1.44k | else if ((base == 0 || base == 2) && TOUPPER (s[1]) == L_('B')) |
292 | 0 | { |
293 | 0 | s += 2; |
294 | 0 | base = 2; |
295 | 0 | } |
296 | 1.44k | else if (base == 0) |
297 | 0 | base = 8; |
298 | 1.44k | } |
299 | 22.5k | else if (base == 0) |
300 | 0 | base = 10; |
301 | | |
302 | | /* Save the pointer so we can check later if anything happened. */ |
303 | 23.9k | save = s; |
304 | | |
305 | | #ifdef USE_NUMBER_GROUPING |
306 | | if (group) |
307 | | { |
308 | | /* Find the end of the digit string and check its grouping. */ |
309 | | end = s; |
310 | | for (c = *end; c != L_('\0'); c = *++end) |
311 | | if ((wchar_t) c != thousands |
312 | | && ((wchar_t) c < L_('0') || (wchar_t) c > L_('9')) |
313 | | && (!ISALPHA (c) || (int) (TOUPPER (c) - L_('A') + 10) >= base)) |
314 | | break; |
315 | | if (*s == thousands) |
316 | | end = s; |
317 | | else |
318 | | end = correctly_grouped_prefix (s, end, thousands, grouping); |
319 | | } |
320 | | else |
321 | | #endif |
322 | 23.9k | end = NULL; |
323 | | |
324 | 23.9k | cutoff = STRTOL_ULONG_MAX / (unsigned LONG int) base; |
325 | 23.9k | cutlim = STRTOL_ULONG_MAX % (unsigned LONG int) base; |
326 | | |
327 | 23.9k | overflow = 0; |
328 | 23.9k | i = 0; |
329 | 66.7k | for (c = *s; c != L_('\0'); c = *++s) |
330 | 57.1k | { |
331 | 57.1k | if (s == end) |
332 | 0 | break; |
333 | 57.1k | if (c >= L_('0') && c <= L_('9')) |
334 | 42.7k | c -= L_('0'); |
335 | 14.3k | else if (ISALPHA (c)) |
336 | 5.98k | c = TOUPPER (c) - L_('A') + 10; |
337 | 8.39k | else |
338 | 8.39k | break; |
339 | 48.7k | if ((int) c >= base) |
340 | 5.98k | break; |
341 | | /* Check for overflow. */ |
342 | 42.7k | if (i > cutoff || (i == cutoff && c > cutlim)) |
343 | 1.25k | overflow = 1; |
344 | 41.4k | else |
345 | 41.4k | { |
346 | 41.4k | i *= (unsigned LONG int) base; |
347 | 41.4k | i += c; |
348 | 41.4k | } |
349 | 42.7k | } |
350 | | |
351 | | /* Check if anything actually happened. */ |
352 | 23.9k | if (s == save) |
353 | 15.2k | goto noconv; |
354 | | |
355 | | /* Store in ENDPTR the address of one character |
356 | | past the last character we converted. */ |
357 | 8.71k | if (endptr != NULL) |
358 | 0 | *endptr = (STRING_TYPE *) s; |
359 | | |
360 | 8.71k | #if !UNSIGNED |
361 | | /* Check for a value that is within the range of |
362 | | 'unsigned LONG int', but outside the range of 'LONG int'. */ |
363 | 8.71k | if (overflow == 0 |
364 | 8.71k | && i > (negative |
365 | 8.17k | ? -((unsigned LONG int) (STRTOL_LONG_MIN + 1)) + 1 |
366 | 8.17k | : (unsigned LONG int) STRTOL_LONG_MAX)) |
367 | 546 | overflow = 1; |
368 | 8.71k | #endif |
369 | | |
370 | 8.71k | if (overflow) |
371 | 1.08k | { |
372 | 1.08k | __set_errno (ERANGE); |
373 | | #if UNSIGNED |
374 | | return STRTOL_ULONG_MAX; |
375 | | #else |
376 | 1.08k | return negative ? STRTOL_LONG_MIN : STRTOL_LONG_MAX; |
377 | 1.08k | #endif |
378 | 1.08k | } |
379 | | |
380 | | /* Return the result of the appropriate sign. */ |
381 | 7.62k | return negative ? -i : i; |
382 | | |
383 | 15.4k | noconv: |
384 | | /* We must handle a special case here: the base is 0 or 16 and the |
385 | | first two characters are '0' and 'x', but the rest are no |
386 | | hexadecimal digits. Likewise when the base is 0 or 2 and the |
387 | | first two characters are '0' and 'b', but the rest are no binary |
388 | | digits. This is no error case. We return 0 and ENDPTR points to |
389 | | the 'x' or 'b'. */ |
390 | 15.4k | if (endptr != NULL) |
391 | 0 | { |
392 | 0 | if (save - nptr >= 2 |
393 | 0 | && (TOUPPER (save[-1]) == L_('X') || TOUPPER (save[-1]) == L_('B')) |
394 | 0 | && save[-2] == L_('0')) |
395 | 0 | *endptr = (STRING_TYPE *) &save[-1]; |
396 | 0 | else |
397 | | /* There was no number to convert. */ |
398 | 0 | *endptr = (STRING_TYPE *) nptr; |
399 | 0 | } |
400 | | |
401 | 15.4k | return 0L; |
402 | 8.71k | } Unexecuted instantiation: rpl_strtol Line | Count | Source | 214 | 24.1k | { | 215 | 24.1k | int negative; | 216 | 24.1k | register unsigned LONG int cutoff; | 217 | 24.1k | register unsigned int cutlim; | 218 | 24.1k | register unsigned LONG int i; | 219 | 24.1k | register const STRING_TYPE *s; | 220 | 24.1k | register UCHAR_TYPE c; | 221 | 24.1k | const STRING_TYPE *save, *end; | 222 | 24.1k | int overflow; | 223 | | | 224 | | #ifdef USE_NUMBER_GROUPING | 225 | | # ifdef USE_IN_EXTENDED_LOCALE_MODEL | 226 | | struct locale_data *current = loc->__locales[LC_NUMERIC]; | 227 | | # endif | 228 | | /* The thousands character of the current locale. */ | 229 | | wchar_t thousands = L'\0'; | 230 | | /* The numeric grouping specification of the current locale, | 231 | | in the format described in <locale.h>. */ | 232 | | const char *grouping; | 233 | | | 234 | | if (group) | 235 | | { | 236 | | grouping = _NL_CURRENT (LC_NUMERIC, GROUPING); | 237 | | if (*grouping <= 0 || *grouping == CHAR_MAX) | 238 | | grouping = NULL; | 239 | | else | 240 | | { | 241 | | /* Figure out the thousands separator character. */ | 242 | | # if defined _LIBC || defined _HAVE_BTOWC | 243 | | thousands = __btowc (*_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP)); | 244 | | if (thousands == WEOF) | 245 | | thousands = L'\0'; | 246 | | # endif | 247 | | if (thousands == L'\0') | 248 | | grouping = NULL; | 249 | | } | 250 | | } | 251 | | else | 252 | | grouping = NULL; | 253 | | #endif | 254 | | | 255 | 24.1k | if (base < 0 || base == 1 || base > 36) | 256 | 0 | { | 257 | 0 | __set_errno (EINVAL); | 258 | 0 | return 0; | 259 | 0 | } | 260 | | | 261 | 24.1k | save = s = nptr; | 262 | | | 263 | | /* Skip white space. */ | 264 | 24.1k | while (ISSPACE (*s)) | 265 | 573 | ++s; | 266 | 24.1k | if (*s == L_('\0')) | 267 | 236 | goto noconv; | 268 | | | 269 | | /* Check for a sign. */ | 270 | 23.9k | if (*s == L_('-')) | 271 | 1.78k | { | 272 | 1.78k | negative = 1; | 273 | 1.78k | ++s; | 274 | 1.78k | } | 275 | 22.1k | else if (*s == L_('+')) | 276 | 231 | { | 277 | 231 | negative = 0; | 278 | 231 | ++s; | 279 | 231 | } | 280 | 21.9k | else | 281 | 21.9k | negative = 0; | 282 | | | 283 | | /* Recognize number prefix and if BASE is zero, figure it out ourselves. */ | 284 | 23.9k | if (*s == L_('0')) | 285 | 1.44k | { | 286 | 1.44k | if ((base == 0 || base == 16) && TOUPPER (s[1]) == L_('X')) | 287 | 0 | { | 288 | 0 | s += 2; | 289 | 0 | base = 16; | 290 | 0 | } | 291 | 1.44k | else if ((base == 0 || base == 2) && TOUPPER (s[1]) == L_('B')) | 292 | 0 | { | 293 | 0 | s += 2; | 294 | 0 | base = 2; | 295 | 0 | } | 296 | 1.44k | else if (base == 0) | 297 | 0 | base = 8; | 298 | 1.44k | } | 299 | 22.5k | else if (base == 0) | 300 | 0 | base = 10; | 301 | | | 302 | | /* Save the pointer so we can check later if anything happened. */ | 303 | 23.9k | save = s; | 304 | | | 305 | | #ifdef USE_NUMBER_GROUPING | 306 | | if (group) | 307 | | { | 308 | | /* Find the end of the digit string and check its grouping. */ | 309 | | end = s; | 310 | | for (c = *end; c != L_('\0'); c = *++end) | 311 | | if ((wchar_t) c != thousands | 312 | | && ((wchar_t) c < L_('0') || (wchar_t) c > L_('9')) | 313 | | && (!ISALPHA (c) || (int) (TOUPPER (c) - L_('A') + 10) >= base)) | 314 | | break; | 315 | | if (*s == thousands) | 316 | | end = s; | 317 | | else | 318 | | end = correctly_grouped_prefix (s, end, thousands, grouping); | 319 | | } | 320 | | else | 321 | | #endif | 322 | 23.9k | end = NULL; | 323 | | | 324 | 23.9k | cutoff = STRTOL_ULONG_MAX / (unsigned LONG int) base; | 325 | 23.9k | cutlim = STRTOL_ULONG_MAX % (unsigned LONG int) base; | 326 | | | 327 | 23.9k | overflow = 0; | 328 | 23.9k | i = 0; | 329 | 66.7k | for (c = *s; c != L_('\0'); c = *++s) | 330 | 57.1k | { | 331 | 57.1k | if (s == end) | 332 | 0 | break; | 333 | 57.1k | if (c >= L_('0') && c <= L_('9')) | 334 | 42.7k | c -= L_('0'); | 335 | 14.3k | else if (ISALPHA (c)) | 336 | 5.98k | c = TOUPPER (c) - L_('A') + 10; | 337 | 8.39k | else | 338 | 8.39k | break; | 339 | 48.7k | if ((int) c >= base) | 340 | 5.98k | break; | 341 | | /* Check for overflow. */ | 342 | 42.7k | if (i > cutoff || (i == cutoff && c > cutlim)) | 343 | 1.25k | overflow = 1; | 344 | 41.4k | else | 345 | 41.4k | { | 346 | 41.4k | i *= (unsigned LONG int) base; | 347 | 41.4k | i += c; | 348 | 41.4k | } | 349 | 42.7k | } | 350 | | | 351 | | /* Check if anything actually happened. */ | 352 | 23.9k | if (s == save) | 353 | 15.2k | goto noconv; | 354 | | | 355 | | /* Store in ENDPTR the address of one character | 356 | | past the last character we converted. */ | 357 | 8.71k | if (endptr != NULL) | 358 | 0 | *endptr = (STRING_TYPE *) s; | 359 | | | 360 | 8.71k | #if !UNSIGNED | 361 | | /* Check for a value that is within the range of | 362 | | 'unsigned LONG int', but outside the range of 'LONG int'. */ | 363 | 8.71k | if (overflow == 0 | 364 | 8.71k | && i > (negative | 365 | 8.17k | ? -((unsigned LONG int) (STRTOL_LONG_MIN + 1)) + 1 | 366 | 8.17k | : (unsigned LONG int) STRTOL_LONG_MAX)) | 367 | 546 | overflow = 1; | 368 | 8.71k | #endif | 369 | | | 370 | 8.71k | if (overflow) | 371 | 1.08k | { | 372 | 1.08k | __set_errno (ERANGE); | 373 | | #if UNSIGNED | 374 | | return STRTOL_ULONG_MAX; | 375 | | #else | 376 | 1.08k | return negative ? STRTOL_LONG_MIN : STRTOL_LONG_MAX; | 377 | 1.08k | #endif | 378 | 1.08k | } | 379 | | | 380 | | /* Return the result of the appropriate sign. */ | 381 | 7.62k | return negative ? -i : i; | 382 | | | 383 | 15.4k | noconv: | 384 | | /* We must handle a special case here: the base is 0 or 16 and the | 385 | | first two characters are '0' and 'x', but the rest are no | 386 | | hexadecimal digits. Likewise when the base is 0 or 2 and the | 387 | | first two characters are '0' and 'b', but the rest are no binary | 388 | | digits. This is no error case. We return 0 and ENDPTR points to | 389 | | the 'x' or 'b'. */ | 390 | 15.4k | if (endptr != NULL) | 391 | 0 | { | 392 | 0 | if (save - nptr >= 2 | 393 | 0 | && (TOUPPER (save[-1]) == L_('X') || TOUPPER (save[-1]) == L_('B')) | 394 | 0 | && save[-2] == L_('0')) | 395 | 0 | *endptr = (STRING_TYPE *) &save[-1]; | 396 | 0 | else | 397 | | /* There was no number to convert. */ | 398 | 0 | *endptr = (STRING_TYPE *) nptr; | 399 | 0 | } | 400 | | | 401 | 15.4k | return 0L; | 402 | 8.71k | } |
|
403 | | |
404 | | #ifdef USE_NUMBER_GROUPING |
405 | | /* External user entry point. */ |
406 | | |
407 | | INT |
408 | | # ifdef weak_function |
409 | | weak_function |
410 | | # endif |
411 | | strtol (const STRING_TYPE *nptr, STRING_TYPE **endptr, |
412 | | int base LOCALE_PARAM_PROTO) |
413 | | { |
414 | | return INTERNAL (strtol) (nptr, endptr, base, 0 LOCALE_PARAM); |
415 | | } |
416 | | #endif |