]> git.ipfire.org Git - thirdparty/glibc.git/blame - stdlib/strtol_l.c
stdlib: Avoid another self-comparison in qsort
[thirdparty/glibc.git] / stdlib / strtol_l.c
CommitLineData
0501d603 1/* Convert string representing a number to integer value, using given locale.
6d7e8eda 2 Copyright (C) 1997-2023 Free Software Foundation, Inc.
0501d603 3 This file is part of the GNU C Library.
0501d603
UD
4
5 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
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.
0501d603
UD
9
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
41bdb6e2 13 Lesser General Public License for more details.
0501d603 14
41bdb6e2 15 You should have received a copy of the GNU Lesser General Public
59ba27a6 16 License along with the GNU C Library; if not, see
5a82c748 17 <https://www.gnu.org/licenses/>. */
0501d603 18
64924422
JM
19#include <features.h>
20#undef __GLIBC_USE_C2X_STRTOL
21#define __GLIBC_USE_C2X_STRTOL 0
0501d603 22
ccadf7b5
UD
23#if HAVE_CONFIG_H
24# include <config.h>
25#endif
26
27#ifdef _LIBC
28# define USE_NUMBER_GROUPING
ccadf7b5
UD
29# define HAVE_LIMITS_H
30#endif
31
32#include <ctype.h>
33#include <errno.h>
34#ifndef __set_errno
35# define __set_errno(Val) errno = (Val)
36#endif
37
38#ifdef HAVE_LIMITS_H
39# include <limits.h>
40#endif
41
42#include <stddef.h>
43#include <stdlib.h>
44#include <string.h>
45#include <locale.h>
e054f494 46#include <stdint.h>
af15df12 47#include <bits/wordsize.h>
ebbad4cc 48
ccadf7b5
UD
49#ifdef USE_NUMBER_GROUPING
50# include "../locale/localeinfo.h"
51#endif
52
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
61
62/* Determine the name. */
63#if UNSIGNED
64# ifdef USE_WIDE_CHAR
65# ifdef QUAD
66# define strtol_l wcstoull_l
64924422 67# define __isoc23_strtol_l __isoc23_wcstoull_l
ccadf7b5
UD
68# else
69# define strtol_l wcstoul_l
64924422 70# define __isoc23_strtol_l __isoc23_wcstoul_l
ccadf7b5
UD
71# endif
72# else
73# ifdef QUAD
74# define strtol_l strtoull_l
64924422 75# define __isoc23_strtol_l __isoc23_strtoull_l
ccadf7b5
UD
76# else
77# define strtol_l strtoul_l
64924422 78# define __isoc23_strtol_l __isoc23_strtoul_l
ccadf7b5
UD
79# endif
80# endif
81#else
82# ifdef USE_WIDE_CHAR
83# ifdef QUAD
84# define strtol_l wcstoll_l
64924422 85# define __isoc23_strtol_l __isoc23_wcstoll_l
ccadf7b5
UD
86# else
87# define strtol_l wcstol_l
64924422 88# define __isoc23_strtol_l __isoc23_wcstol_l
ccadf7b5
UD
89# endif
90# else
91# ifdef QUAD
92# define strtol_l strtoll_l
64924422 93# define __isoc23_strtol_l __isoc23_strtoll_l
ccadf7b5
UD
94# else
95# define strtol_l strtol_l
64924422 96# define __isoc23_strtol_l __isoc23_strtol_l
ccadf7b5
UD
97# endif
98# endif
99#endif
100
101#define __strtol_l __strtol_l2(strtol_l)
102#define __strtol_l2(name) __strtol_l3(name)
103#define __strtol_l3(name) __##name
104
105
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
115
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
126
127
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)
138
139#if defined _LIBC || defined HAVE_WCHAR_H
140# include <wchar.h>
141#endif
142
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)
f5eee5c7
JM
149# define ISALPHA(Ch) __iswalpha_l ((Ch), _nl_C_locobj_ptr)
150# define TOUPPER(Ch) __towupper_l ((Ch), _nl_C_locobj_ptr)
ccadf7b5
UD
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)
f5eee5c7
JM
162# define ISALPHA(Ch) __isalpha_l ((Ch), _nl_C_locobj_ptr)
163# define TOUPPER(Ch) __toupper_l ((Ch), _nl_C_locobj_ptr)
ccadf7b5
UD
164#endif
165
166#define INTERNAL(X) INTERNAL1(X)
167#define INTERNAL1(X) __##X##_internal
168#define WEAKNAME(X) WEAKNAME1(X)
169
170#ifdef USE_NUMBER_GROUPING
171/* This file defines a function to check for correct grouping. */
172# include "grouping.h"
173#endif
174
175
af15df12
UD
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. */
2d1e6277
UD
179extern const unsigned long __strtol_ul_max_tab[] attribute_hidden;
180extern const unsigned char __strtol_ul_rem_tab[] attribute_hidden;
181#if defined(QUAD) && __WORDSIZE == 32
182extern const unsigned long long __strtol_ull_max_tab[] attribute_hidden;
183extern const unsigned char __strtol_ull_rem_tab[] attribute_hidden;
184#endif
af15df12
UD
185
186#define DEF(TYPE, NAME) \
2d1e6277 187 const TYPE NAME[] attribute_hidden = \
af15df12
UD
188 { \
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) \
193 }
194
2d1e6277
UD
195#if !UNSIGNED && !defined (USE_WIDE_CHAR) && !defined (QUAD)
196# define F(X) ULONG_MAX / X
af15df12 197 DEF (unsigned long, __strtol_ul_max_tab);
2d1e6277
UD
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
af15df12
UD
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
af15df12
UD
211#endif
212#undef DEF
213
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
224
ccadf7b5
UD
225
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.
64924422
JM
230 If BIN_CST is true, binary constants starting "0b" or "0B" are accepted
231 in base 0 and 2.
ccadf7b5
UD
232 If ENDPTR is not NULL, a pointer to the character after the last
233 one converted is stored in *ENDPTR. */
234
235INT
80d9be81 236INTERNAL (__strtol_l) (const STRING_TYPE *nptr, STRING_TYPE **endptr,
64924422 237 int base, int group, bool bin_cst, locale_t loc)
ccadf7b5
UD
238{
239 int negative;
2e09a79a
JM
240 unsigned LONG int cutoff;
241 unsigned int cutlim;
242 unsigned LONG int i;
243 const STRING_TYPE *s;
244 UCHAR_TYPE c;
ccadf7b5
UD
245 const STRING_TYPE *save, *end;
246 int overflow;
247#ifndef USE_WIDE_CHAR
248 size_t cnt;
249#endif
250
251#ifdef USE_NUMBER_GROUPING
f095bb72 252 struct __locale_data *current = loc->__locales[LC_NUMERIC];
ccadf7b5
UD
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;
263
a1ffb40e 264 if (__glibc_unlikely (group))
ccadf7b5
UD
265 {
266 grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
267 if (*grouping <= 0 || *grouping == CHAR_MAX)
268 grouping = NULL;
269 else
270 {
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')
284 {
285 thousands = NULL;
286 grouping = NULL;
287 }
288# endif
289 }
290 }
291 else
292 grouping = NULL;
293#endif
294
295 if (base < 0 || base == 1 || base > 36)
296 {
297 __set_errno (EINVAL);
298 return 0;
299 }
300
301 save = s = nptr;
302
303 /* Skip white space. */
304 while (ISSPACE (*s))
305 ++s;
a1ffb40e 306 if (__glibc_unlikely (*s == L_('\0')))
ccadf7b5
UD
307 goto noconv;
308
309 /* Check for a sign. */
310 negative = 0;
311 if (*s == L_('-'))
312 {
313 negative = 1;
314 ++s;
315 }
316 else if (*s == L_('+'))
317 ++s;
318
319 /* Recognize number prefix and if BASE is zero, figure it out ourselves. */
320 if (*s == L_('0'))
321 {
322 if ((base == 0 || base == 16) && TOUPPER (s[1]) == L_('X'))
323 {
324 s += 2;
325 base = 16;
326 }
64924422
JM
327 else if (bin_cst && (base == 0 || base == 2) && TOUPPER (s[1]) == L_('B'))
328 {
329 s += 2;
330 base = 2;
331 }
ccadf7b5
UD
332 else if (base == 0)
333 base = 8;
334 }
335 else if (base == 0)
336 base = 10;
337
338 /* Save the pointer so we can check later if anything happened. */
339 save = s;
340
341#ifdef USE_NUMBER_GROUPING
342 if (base != 10)
343 grouping = NULL;
344
a1ffb40e 345 if (__glibc_unlikely (grouping != NULL))
ccadf7b5
UD
346 {
347# ifndef USE_WIDE_CHAR
348 thousands_len = strlen (thousands);
349# endif
350
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
362 )
363 {
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)
895f3a1f
SE
370 if (thousands[cnt] != end[cnt])
371 break;
ccadf7b5
UD
372 cnt < thousands_len; })
373# endif
374 && (!ISALPHA (c)
375 || (int) (TOUPPER (c) - L_('A') + 10) >= base))
376 break;
377
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
383 }
384 }
385 else
386#endif
387 end = NULL;
388
af15df12
UD
389 /* Avoid runtime division; lookup cutoff and limit. */
390 cutoff = cutoff_tab[base - 2];
391 cutlim = cutlim_tab[base - 2];
ccadf7b5
UD
392
393 overflow = 0;
394 i = 0;
395 c = *s;
396 if (sizeof (long int) != sizeof (LONG int))
397 {
398 unsigned long int j = 0;
af15df12 399 unsigned long int jmax = jmax_tab[base - 2];
ccadf7b5
UD
400
401 for (;c != L_('\0'); c = *++s)
402 {
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)
413 {
414 for (cnt = 0; cnt < thousands_len; ++cnt)
415 if (thousands[cnt] != s[cnt])
416 break;
417 if (cnt == thousands_len)
418 {
419 s += thousands_len - 1;
420 continue;
421 }
422 if (ISALPHA (c))
423 c = TOUPPER (c) - L_('A') + 10;
424 else
425 break;
426 }
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)
437 {
438 /* We have an overflow. Now use the long representation. */
439 i = (unsigned LONG int) j;
440 goto use_long;
441 }
442 else
443 j = j * (unsigned long int) base + c;
444 }
445
446 i = (unsigned LONG int) j;
447 }
448 else
449 for (;c != L_('\0'); c = *++s)
450 {
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)
461 {
462 for (cnt = 0; cnt < thousands_len; ++cnt)
463 if (thousands[cnt] != s[cnt])
464 break;
465 if (cnt == thousands_len)
466 {
467 s += thousands_len - 1;
468 continue;
469 }
470 if (ISALPHA (c))
471 c = TOUPPER (c) - L_('A') + 10;
472 else
473 break;
474 }
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
487 {
488 use_long:
489 i *= (unsigned LONG int) base;
490 i += c;
491 }
492 }
493
494 /* Check if anything actually happened. */
495 if (s == save)
496 goto noconv;
497
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;
502
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
512
a1ffb40e 513 if (__glibc_unlikely (overflow))
ccadf7b5
UD
514 {
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
521 }
522
523 /* Return the result of the appropriate sign. */
524 return negative ? -i : i;
525
526noconv:
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
95c9a6e8
AZ
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'. */
ccadf7b5
UD
533 if (endptr != NULL)
534 {
95c9a6e8
AZ
535 if (save - nptr >= 2
536 && (TOUPPER (save[-1]) == L_('X')
537 || (bin_cst && TOUPPER (save[-1]) == L_('B')))
ccadf7b5
UD
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;
543 }
544
545 return 0L;
546}
547#if defined _LIBC && !defined USE_WIDE_CHAR
548libc_hidden_def (INTERNAL (__strtol_l))
549#endif
550\f
551/* External user entry point. */
552
553#if _LIBC - 0 == 0
ccadf7b5
UD
554
555/* Prototype. */
69db4f8f
MP
556extern INT __strtol_l (const STRING_TYPE *nptr, STRING_TYPE **endptr,
557 int base);
ccadf7b5 558#endif
0501d603 559
da4cfe38 560
ccadf7b5
UD
561INT
562#ifdef weak_function
563weak_function
564#endif
80d9be81 565__strtol_l (const STRING_TYPE *nptr, STRING_TYPE **endptr,
af85385f 566 int base, locale_t loc)
ccadf7b5 567{
64924422 568 return INTERNAL (__strtol_l) (nptr, endptr, base, 0, false, loc);
ccadf7b5 569}
773e305e 570libc_hidden_def (__strtol_l)
da4cfe38 571weak_alias (__strtol_l, strtol_l)
64924422
JM
572
573INT
574__isoc23_strtol_l (const STRING_TYPE *nptr, STRING_TYPE **endptr,
575 int base, locale_t loc)
576{
577 return INTERNAL (__strtol_l) (nptr, endptr, base, 0, true, loc);
578}
579libc_hidden_def (__isoc23_strtol_l)