sh: Fix static build with --enable-fortify
[glibc.git] / stdlib / strtol_l.c
blob66c40358695ee7284f78503285bade4bcf75fb09
1 /* Convert string representing a number to integer value, using given locale.
2 Copyright (C) 1997-2024 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
19 #include <features.h>
20 #undef __GLIBC_USE_C2X_STRTOL
21 #define __GLIBC_USE_C2X_STRTOL 0
23 #if HAVE_CONFIG_H
24 # include <config.h>
25 #endif
27 #ifdef _LIBC
28 # define USE_NUMBER_GROUPING
29 # define HAVE_LIMITS_H
30 #endif
32 #include <ctype.h>
33 #include <errno.h>
34 #ifndef __set_errno
35 # define __set_errno(Val) errno = (Val)
36 #endif
38 #ifdef HAVE_LIMITS_H
39 # include <limits.h>
40 #endif
42 #include <stddef.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <locale.h>
46 #include <stdint.h>
47 #include <bits/wordsize.h>
49 #ifdef USE_NUMBER_GROUPING
50 # include "../locale/localeinfo.h"
51 #endif
53 /* Nonzero if we are defining `strtoul' or `strtoull', operating on
54 unsigned integers. */
55 #ifndef UNSIGNED
56 # define UNSIGNED 0
57 # define INT LONG int
58 #else
59 # define INT unsigned LONG int
60 #endif
62 /* Determine the name. */
63 #if UNSIGNED
64 # ifdef USE_WIDE_CHAR
65 # ifdef QUAD
66 # define strtol_l wcstoull_l
67 # define __isoc23_strtol_l __isoc23_wcstoull_l
68 # else
69 # define strtol_l wcstoul_l
70 # define __isoc23_strtol_l __isoc23_wcstoul_l
71 # endif
72 # else
73 # ifdef QUAD
74 # define strtol_l strtoull_l
75 # define __isoc23_strtol_l __isoc23_strtoull_l
76 # else
77 # define strtol_l strtoul_l
78 # define __isoc23_strtol_l __isoc23_strtoul_l
79 # endif
80 # endif
81 #else
82 # ifdef USE_WIDE_CHAR
83 # ifdef QUAD
84 # define strtol_l wcstoll_l
85 # define __isoc23_strtol_l __isoc23_wcstoll_l
86 # else
87 # define strtol_l wcstol_l
88 # define __isoc23_strtol_l __isoc23_wcstol_l
89 # endif
90 # else
91 # ifdef QUAD
92 # define strtol_l strtoll_l
93 # define __isoc23_strtol_l __isoc23_strtoll_l
94 # else
95 # define strtol_l strtol_l
96 # define __isoc23_strtol_l __isoc23_strtol_l
97 # endif
98 # endif
99 #endif
101 #define __strtol_l __strtol_l2(strtol_l)
102 #define __strtol_l2(name) __strtol_l3(name)
103 #define __strtol_l3(name) __##name
106 /* If QUAD is defined, we are defining `strtoll' or `strtoull',
107 operating on `long long int's. */
108 #ifdef QUAD
109 # define LONG long long
110 # define STRTOL_LONG_MIN LONG_LONG_MIN
111 # define STRTOL_LONG_MAX LONG_LONG_MAX
112 # define STRTOL_ULONG_MAX ULONG_LONG_MAX
113 #else
114 # define LONG long
116 # ifndef ULONG_MAX
117 # define ULONG_MAX ((unsigned long int) ~(unsigned long int) 0)
118 # endif
119 # ifndef LONG_MAX
120 # define LONG_MAX ((long int) (ULONG_MAX >> 1))
121 # endif
122 # define STRTOL_LONG_MIN LONG_MIN
123 # define STRTOL_LONG_MAX LONG_MAX
124 # define STRTOL_ULONG_MAX ULONG_MAX
125 #endif
128 /* We use this code for the extended locale handling where the
129 function gets as an additional argument the locale which has to be
130 used. To access the values we have to redefine the _NL_CURRENT and
131 _NL_CURRENT_WORD macros. */
132 #undef _NL_CURRENT
133 #define _NL_CURRENT(category, item) \
134 (current->values[_NL_ITEM_INDEX (item)].string)
135 #undef _NL_CURRENT_WORD
136 #define _NL_CURRENT_WORD(category, item) \
137 ((uint32_t) current->values[_NL_ITEM_INDEX (item)].word)
139 #if defined _LIBC || defined HAVE_WCHAR_H
140 # include <wchar.h>
141 #endif
143 #ifdef USE_WIDE_CHAR
144 # include <wctype.h>
145 # define L_(Ch) L##Ch
146 # define UCHAR_TYPE wint_t
147 # define STRING_TYPE wchar_t
148 # define ISSPACE(Ch) __iswspace_l ((Ch), loc)
149 # define ISALPHA(Ch) __iswalpha_l ((Ch), _nl_C_locobj_ptr)
150 # define TOUPPER(Ch) __towupper_l ((Ch), _nl_C_locobj_ptr)
151 #else
152 # if defined _LIBC \
153 || defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII)
154 # define IN_CTYPE_DOMAIN(c) 1
155 # else
156 # define IN_CTYPE_DOMAIN(c) isascii(c)
157 # endif
158 # define L_(Ch) Ch
159 # define UCHAR_TYPE unsigned char
160 # define STRING_TYPE char
161 # define ISSPACE(Ch) __isspace_l ((Ch), loc)
162 # define ISALPHA(Ch) __isalpha_l ((Ch), _nl_C_locobj_ptr)
163 # define TOUPPER(Ch) __toupper_l ((Ch), _nl_C_locobj_ptr)
164 #endif
166 #define INTERNAL(X) INTERNAL1(X)
167 #define INTERNAL1(X) __##X##_internal
168 #define WEAKNAME(X) WEAKNAME1(X)
170 #ifdef USE_NUMBER_GROUPING
171 /* This file defines a function to check for correct grouping. */
172 # include "grouping.h"
173 #endif
176 /* Define tables of maximum values and remainders in order to detect
177 overflow. Do this at compile-time in order to avoid the runtime
178 overhead of the division. */
179 extern const unsigned long __strtol_ul_max_tab[] attribute_hidden;
180 extern const unsigned char __strtol_ul_rem_tab[] attribute_hidden;
181 #if defined(QUAD) && __WORDSIZE == 32
182 extern const unsigned long long __strtol_ull_max_tab[] attribute_hidden;
183 extern const unsigned char __strtol_ull_rem_tab[] attribute_hidden;
184 #endif
186 #define DEF(TYPE, NAME) \
187 const TYPE NAME[] attribute_hidden = \
189 F(2), F(3), F(4), F(5), F(6), F(7), F(8), F(9), F(10), \
190 F(11), F(12), F(13), F(14), F(15), F(16), F(17), F(18), F(19), F(20), \
191 F(21), F(22), F(23), F(24), F(25), F(26), F(27), F(28), F(29), F(30), \
192 F(31), F(32), F(33), F(34), F(35), F(36) \
195 #if !UNSIGNED && !defined (USE_WIDE_CHAR) && !defined (QUAD)
196 # define F(X) ULONG_MAX / X
197 DEF (unsigned long, __strtol_ul_max_tab);
198 # undef F
199 # define F(X) ULONG_MAX % X
200 DEF (unsigned char, __strtol_ul_rem_tab);
201 # undef F
202 #endif
203 #if !UNSIGNED && !defined (USE_WIDE_CHAR) && defined (QUAD) \
204 && __WORDSIZE == 32
205 # define F(X) ULONG_LONG_MAX / X
206 DEF (unsigned long long, __strtol_ull_max_tab);
207 # undef F
208 # define F(X) ULONG_LONG_MAX % X
209 DEF (unsigned char, __strtol_ull_rem_tab);
210 # undef F
211 #endif
212 #undef DEF
214 /* Define some more readable aliases for these arrays which correspond
215 to how they'll be used in the function below. */
216 #define jmax_tab __strtol_ul_max_tab
217 #if defined(QUAD) && __WORDSIZE == 32
218 # define cutoff_tab __strtol_ull_max_tab
219 # define cutlim_tab __strtol_ull_rem_tab
220 #else
221 # define cutoff_tab __strtol_ul_max_tab
222 # define cutlim_tab __strtol_ul_rem_tab
223 #endif
226 /* Convert NPTR to an `unsigned long int' or `long int' in base BASE.
227 If BASE is 0 the base is determined by the presence of a leading
228 zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal.
229 If BASE is < 2 or > 36, it is reset to 10.
230 If BIN_CST is true, binary constants starting "0b" or "0B" are accepted
231 in base 0 and 2.
232 If ENDPTR is not NULL, a pointer to the character after the last
233 one converted is stored in *ENDPTR. */
236 INTERNAL (__strtol_l) (const STRING_TYPE *nptr, STRING_TYPE **endptr,
237 int base, int group, bool bin_cst, locale_t loc)
239 int negative;
240 unsigned LONG int cutoff;
241 unsigned int cutlim;
242 unsigned LONG int i;
243 const STRING_TYPE *s;
244 UCHAR_TYPE c;
245 const STRING_TYPE *save, *end;
246 int overflow;
247 #ifndef USE_WIDE_CHAR
248 size_t cnt;
249 #endif
251 #ifdef USE_NUMBER_GROUPING
252 struct __locale_data *current = loc->__locales[LC_NUMERIC];
253 /* The thousands character of the current locale. */
254 # ifdef USE_WIDE_CHAR
255 wchar_t thousands = L'\0';
256 # else
257 const char *thousands = NULL;
258 size_t thousands_len = 0;
259 # endif
260 /* The numeric grouping specification of the current locale,
261 in the format described in <locale.h>. */
262 const char *grouping;
264 if (__glibc_unlikely (group))
266 grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
267 if (*grouping <= 0 || *grouping == CHAR_MAX)
268 grouping = NULL;
269 else
271 /* Figure out the thousands separator character. */
272 # ifdef USE_WIDE_CHAR
273 # ifdef _LIBC
274 thousands = _NL_CURRENT_WORD (LC_NUMERIC,
275 _NL_NUMERIC_THOUSANDS_SEP_WC);
276 # endif
277 if (thousands == L'\0')
278 grouping = NULL;
279 # else
280 # ifdef _LIBC
281 thousands = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
282 # endif
283 if (*thousands == '\0')
285 thousands = NULL;
286 grouping = NULL;
288 # endif
291 else
292 grouping = NULL;
293 #endif
295 if (base < 0 || base == 1 || base > 36)
297 __set_errno (EINVAL);
298 return 0;
301 save = s = nptr;
303 /* Skip white space. */
304 while (ISSPACE (*s))
305 ++s;
306 if (__glibc_unlikely (*s == L_('\0')))
307 goto noconv;
309 /* Check for a sign. */
310 negative = 0;
311 if (*s == L_('-'))
313 negative = 1;
314 ++s;
316 else if (*s == L_('+'))
317 ++s;
319 /* Recognize number prefix and if BASE is zero, figure it out ourselves. */
320 if (*s == L_('0'))
322 if ((base == 0 || base == 16) && TOUPPER (s[1]) == L_('X'))
324 s += 2;
325 base = 16;
327 else if (bin_cst && (base == 0 || base == 2) && TOUPPER (s[1]) == L_('B'))
329 s += 2;
330 base = 2;
332 else if (base == 0)
333 base = 8;
335 else if (base == 0)
336 base = 10;
338 /* Save the pointer so we can check later if anything happened. */
339 save = s;
341 #ifdef USE_NUMBER_GROUPING
342 if (base != 10)
343 grouping = NULL;
345 if (__glibc_unlikely (grouping != NULL))
347 # ifndef USE_WIDE_CHAR
348 thousands_len = strlen (thousands);
349 # endif
351 /* Find the end of the digit string and check its grouping. */
352 end = s;
353 if (
354 # ifdef USE_WIDE_CHAR
355 *s != thousands
356 # else
357 ({ for (cnt = 0; cnt < thousands_len; ++cnt)
358 if (thousands[cnt] != end[cnt])
359 break;
360 cnt < thousands_len; })
361 # endif
364 for (c = *end; c != L_('\0'); c = *++end)
365 if (((STRING_TYPE) c < L_('0') || (STRING_TYPE) c > L_('9'))
366 # ifdef USE_WIDE_CHAR
367 && (wchar_t) c != thousands
368 # else
369 && ({ for (cnt = 0; cnt < thousands_len; ++cnt)
370 if (thousands[cnt] != end[cnt])
371 break;
372 cnt < thousands_len; })
373 # endif
374 && (!ISALPHA (c)
375 || (int) (TOUPPER (c) - L_('A') + 10) >= base))
376 break;
378 # ifdef USE_WIDE_CHAR
379 end = __correctly_grouped_prefixwc (s, end, thousands, grouping);
380 # else
381 end = __correctly_grouped_prefixmb (s, end, thousands, grouping);
382 # endif
385 else
386 #endif
387 end = NULL;
389 /* Avoid runtime division; lookup cutoff and limit. */
390 cutoff = cutoff_tab[base - 2];
391 cutlim = cutlim_tab[base - 2];
393 overflow = 0;
394 i = 0;
395 c = *s;
396 if (sizeof (long int) != sizeof (LONG int))
398 unsigned long int j = 0;
399 unsigned long int jmax = jmax_tab[base - 2];
401 for (;c != L_('\0'); c = *++s)
403 if (s == end)
404 break;
405 if (c >= L_('0') && c <= L_('9'))
406 c -= L_('0');
407 #ifdef USE_NUMBER_GROUPING
408 # ifdef USE_WIDE_CHAR
409 else if (grouping && (wchar_t) c == thousands)
410 continue;
411 # else
412 else if (thousands_len)
414 for (cnt = 0; cnt < thousands_len; ++cnt)
415 if (thousands[cnt] != s[cnt])
416 break;
417 if (cnt == thousands_len)
419 s += thousands_len - 1;
420 continue;
422 if (ISALPHA (c))
423 c = TOUPPER (c) - L_('A') + 10;
424 else
425 break;
427 # endif
428 #endif
429 else if (ISALPHA (c))
430 c = TOUPPER (c) - L_('A') + 10;
431 else
432 break;
433 if ((int) c >= base)
434 break;
435 /* Note that we never can have an overflow. */
436 else if (j >= jmax)
438 /* We have an overflow. Now use the long representation. */
439 i = (unsigned LONG int) j;
440 goto use_long;
442 else
443 j = j * (unsigned long int) base + c;
446 i = (unsigned LONG int) j;
448 else
449 for (;c != L_('\0'); c = *++s)
451 if (s == end)
452 break;
453 if (c >= L_('0') && c <= L_('9'))
454 c -= L_('0');
455 #ifdef USE_NUMBER_GROUPING
456 # ifdef USE_WIDE_CHAR
457 else if (grouping && (wchar_t) c == thousands)
458 continue;
459 # else
460 else if (thousands_len)
462 for (cnt = 0; cnt < thousands_len; ++cnt)
463 if (thousands[cnt] != s[cnt])
464 break;
465 if (cnt == thousands_len)
467 s += thousands_len - 1;
468 continue;
470 if (ISALPHA (c))
471 c = TOUPPER (c) - L_('A') + 10;
472 else
473 break;
475 # endif
476 #endif
477 else if (ISALPHA (c))
478 c = TOUPPER (c) - L_('A') + 10;
479 else
480 break;
481 if ((int) c >= base)
482 break;
483 /* Check for overflow. */
484 if (i > cutoff || (i == cutoff && c > cutlim))
485 overflow = 1;
486 else
488 use_long:
489 i *= (unsigned LONG int) base;
490 i += c;
494 /* Check if anything actually happened. */
495 if (s == save)
496 goto noconv;
498 /* Store in ENDPTR the address of one character
499 past the last character we converted. */
500 if (endptr != NULL)
501 *endptr = (STRING_TYPE *) s;
503 #if !UNSIGNED
504 /* Check for a value that is within the range of
505 `unsigned LONG int', but outside the range of `LONG int'. */
506 if (overflow == 0
507 && i > (negative
508 ? -((unsigned LONG int) (STRTOL_LONG_MIN + 1)) + 1
509 : (unsigned LONG int) STRTOL_LONG_MAX))
510 overflow = 1;
511 #endif
513 if (__glibc_unlikely (overflow))
515 __set_errno (ERANGE);
516 #if UNSIGNED
517 return STRTOL_ULONG_MAX;
518 #else
519 return negative ? STRTOL_LONG_MIN : STRTOL_LONG_MAX;
520 #endif
523 /* Return the result of the appropriate sign. */
524 return negative ? -i : i;
526 noconv:
527 /* We must handle a special case here: the base is 0 or 16 and the
528 first two characters are '0' and 'x', but the rest are no
529 hexadecimal digits. Likewise when the base is 0 or 2 and the
530 first two characters are '0' and 'b', but the rest are no binary
531 digits. This is no error case. We return 0 and ENDPTR points to
532 the 'x' or 'b'. */
533 if (endptr != NULL)
535 if (save - nptr >= 2
536 && (TOUPPER (save[-1]) == L_('X')
537 || (bin_cst && TOUPPER (save[-1]) == L_('B')))
538 && save[-2] == L_('0'))
539 *endptr = (STRING_TYPE *) &save[-1];
540 else
541 /* There was no number to convert. */
542 *endptr = (STRING_TYPE *) nptr;
545 return 0L;
547 #if defined _LIBC && !defined USE_WIDE_CHAR
548 libc_hidden_def (INTERNAL (__strtol_l))
549 #endif
551 /* External user entry point. */
553 #if _LIBC - 0 == 0
555 /* Prototype. */
556 extern INT __strtol_l (const STRING_TYPE *nptr, STRING_TYPE **endptr,
557 int base);
558 #endif
562 #ifdef weak_function
563 weak_function
564 #endif
565 __strtol_l (const STRING_TYPE *nptr, STRING_TYPE **endptr,
566 int base, locale_t loc)
568 return INTERNAL (__strtol_l) (nptr, endptr, base, 0, false, loc);
570 libc_hidden_def (__strtol_l)
571 weak_alias (__strtol_l, strtol_l)
574 __isoc23_strtol_l (const STRING_TYPE *nptr, STRING_TYPE **endptr,
575 int base, locale_t loc)
577 return INTERNAL (__strtol_l) (nptr, endptr, base, 0, true, loc);
579 libc_hidden_def (__isoc23_strtol_l)