aboutsummaryrefslogtreecommitdiff
path: root/stdlib
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib')
-rw-r--r--stdlib/Makefile12
-rw-r--r--stdlib/Versions8
-rw-r--r--stdlib/inttypes.h40
-rw-r--r--stdlib/stdlib.h119
-rw-r--r--stdlib/strtod_nan_narrow.h2
-rw-r--r--stdlib/strtod_nan_wide.h2
-rw-r--r--stdlib/strtol.c26
-rw-r--r--stdlib/strtol_l.c30
-rw-r--r--stdlib/strtoll.c1
-rw-r--r--stdlib/strtoll_l.c6
-rw-r--r--stdlib/strtoul_l.c6
-rw-r--r--stdlib/strtoull.c1
-rw-r--r--stdlib/strtoull_l.c7
-rw-r--r--stdlib/tst-strtol-binary-c11.c29
-rw-r--r--stdlib/tst-strtol-binary-c2x.c32
-rw-r--r--stdlib/tst-strtol-binary-gnu11.c34
-rw-r--r--stdlib/tst-strtol-binary-gnu2x.c27
-rw-r--r--stdlib/tst-strtol-binary-main.c151
18 files changed, 523 insertions, 10 deletions
diff --git a/stdlib/Makefile b/stdlib/Makefile
index 83391d00c1..ff5096ad1b 100644
--- a/stdlib/Makefile
+++ b/stdlib/Makefile
@@ -234,6 +234,10 @@ tests := \
tst-strtod5 \
tst-strtod6 \
tst-strtol \
+ tst-strtol-binary-c11 \
+ tst-strtol-binary-c2x \
+ tst-strtol-binary-gnu11 \
+ tst-strtol-binary-gnu2x \
tst-strtol-locale \
tst-strtoll \
tst-swapcontext1 \
@@ -394,6 +398,14 @@ CFLAGS-tst-makecontext2.c += $(stack-align-test-flags)
CFLAGS-testmb.c += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -Wall -Werror
+# Some versions of GCC supported for building glibc do not support -std=c2x
+# or -std=gnu2x, so the tests for those versions use -std=c11 and -std=gnu11
+# and then _ISOC2X_SOURCE is defined in the test as needed.
+CFLAGS-tst-strtol-binary-c11.c += -std=c11
+CFLAGS-tst-strtol-binary-c2x.c += -std=c11
+CFLAGS-tst-strtol-binary-gnu11.c += -std=gnu11
+CFLAGS-tst-strtol-binary-gnu2x.c += -std=gnu11
+
# Run a test on the header files we use.
tests-special += $(objpfx)isomac.out
diff --git a/stdlib/Versions b/stdlib/Versions
index ebc43263d6..6a861c54a1 100644
--- a/stdlib/Versions
+++ b/stdlib/Versions
@@ -143,6 +143,14 @@ libc {
}
GLIBC_2.37 {
}
+ GLIBC_2.38 {
+ __isoc23_strtol;
+ __isoc23_strtoll;
+ __isoc23_strtoul;
+ __isoc23_strtoull;
+ __isoc23_strtoimax;
+ __isoc23_strtoumax;
+ }
GLIBC_PRIVATE {
# functions which have an additional interface since they are
# are cancelable.
diff --git a/stdlib/inttypes.h b/stdlib/inttypes.h
index 791c8e853f..a5fa97b7c8 100644
--- a/stdlib/inttypes.h
+++ b/stdlib/inttypes.h
@@ -311,6 +311,46 @@ extern uintmax_t wcstoumax (const __gwchar_t *__restrict __nptr,
__gwchar_t ** __restrict __endptr, int __base)
__THROW;
+/* Versions of the above functions that handle '0b' and '0B' prefixes
+ in base 0 or 2. */
+#if __GLIBC_USE (C2X_STRTOL)
+# ifdef __REDIRECT
+extern intmax_t __REDIRECT_NTH (strtoimax, (const char *__restrict __nptr,
+ char **__restrict __endptr,
+ int __base), __isoc23_strtoimax);
+extern uintmax_t __REDIRECT_NTH (strtoumax, (const char *__restrict __nptr,
+ char **__restrict __endptr,
+ int __base), __isoc23_strtoumax);
+extern intmax_t __REDIRECT_NTH (wcstoimax,
+ (const __gwchar_t *__restrict __nptr,
+ __gwchar_t **__restrict __endptr, int __base),
+ __isoc23_wcstoimax);
+extern uintmax_t __REDIRECT_NTH (wcstoumax,
+ (const __gwchar_t *__restrict __nptr,
+ __gwchar_t **__restrict __endptr, int __base),
+ __isoc23_wcstoumax);
+# else
+extern intmax_t __isoc23_strtoimax (const char *__restrict __nptr,
+ char **__restrict __endptr, int __base)
+ __THROW;
+extern uintmax_t __isoc23_strtoumax (const char *__restrict __nptr,
+ char ** __restrict __endptr, int __base)
+ __THROW;
+extern intmax_t __isoc23_wcstoimax (const __gwchar_t *__restrict __nptr,
+ __gwchar_t **__restrict __endptr,
+ int __base)
+ __THROW;
+extern uintmax_t __isoc23_wcstoumax (const __gwchar_t *__restrict __nptr,
+ __gwchar_t ** __restrict __endptr,
+ int __base)
+ __THROW;
+# define strtoimax __isoc23_strtoimax
+# define strtoumax __isoc23_strtoumax
+# define wcstoimax __isoc23_wcstoimax
+# define wcstoumax __isoc23_wcstoumax
+# endif
+#endif
+
__END_DECLS
#endif /* inttypes.h */
diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h
index e2c8ffb32b..631b0cbbed 100644
--- a/stdlib/stdlib.h
+++ b/stdlib/stdlib.h
@@ -208,6 +208,71 @@ extern unsigned long long int strtoull (const char *__restrict __nptr,
__THROW __nonnull ((1));
#endif /* ISO C99 or use MISC. */
+/* Versions of the above functions that handle '0b' and '0B' prefixes
+ in base 0 or 2. */
+#if __GLIBC_USE (C2X_STRTOL)
+# ifdef __REDIRECT
+extern long int __REDIRECT_NTH (strtol, (const char *__restrict __nptr,
+ char **__restrict __endptr,
+ int __base), __isoc23_strtol)
+ __nonnull ((1));
+extern unsigned long int __REDIRECT_NTH (strtoul,
+ (const char *__restrict __nptr,
+ char **__restrict __endptr,
+ int __base), __isoc23_strtoul)
+ __nonnull ((1));
+# ifdef __USE_MISC
+__extension__
+extern long long int __REDIRECT_NTH (strtoq, (const char *__restrict __nptr,
+ char **__restrict __endptr,
+ int __base), __isoc23_strtoll)
+ __nonnull ((1));
+__extension__
+extern unsigned long long int __REDIRECT_NTH (strtouq,
+ (const char *__restrict __nptr,
+ char **__restrict __endptr,
+ int __base), __isoc23_strtoull)
+ __nonnull ((1));
+# endif
+__extension__
+extern long long int __REDIRECT_NTH (strtoll, (const char *__restrict __nptr,
+ char **__restrict __endptr,
+ int __base), __isoc23_strtoll)
+ __nonnull ((1));
+__extension__
+extern unsigned long long int __REDIRECT_NTH (strtoull,
+ (const char *__restrict __nptr,
+ char **__restrict __endptr,
+ int __base), __isoc23_strtoull)
+ __nonnull ((1));
+# else
+extern long int __isoc23_strtol (const char *__restrict __nptr,
+ char **__restrict __endptr, int __base)
+ __THROW __nonnull ((1));
+extern unsigned long int __isoc23_strtoul (const char *__restrict __nptr,
+ char **__restrict __endptr,
+ int __base)
+ __THROW __nonnull ((1));
+__extension__
+extern long long int __isoc23_strtoll (const char *__restrict __nptr,
+ char **__restrict __endptr, int __base)
+ __THROW __nonnull ((1));
+__extension__
+extern unsigned long long int __isoc23_strtoull (const char *__restrict __nptr,
+ char **__restrict __endptr,
+ int __base)
+ __THROW __nonnull ((1));
+# define strtol __isoc23_strtol
+# define strtoul __isoc23_strtoul
+# ifdef __USE_MISC
+# define strtoq __isoc23_strtoll
+# define strtouq __isoc23_strtoull
+# endif
+# define strtoll __isoc23_strtoll
+# define strtoull __isoc23_strtoull
+# endif
+#endif
+
/* Convert a floating-point number to a string. */
#if __GLIBC_USE (IEC_60559_BFP_EXT_C2X)
extern int strfromd (char *__dest, size_t __size, const char *__format,
@@ -293,6 +358,60 @@ extern unsigned long long int strtoull_l (const char *__restrict __nptr,
int __base, locale_t __loc)
__THROW __nonnull ((1, 4));
+/* Versions of the above functions that handle '0b' and '0B' prefixes
+ in base 0 or 2. */
+# if __GLIBC_USE (C2X_STRTOL)
+# ifdef __REDIRECT
+extern long int __REDIRECT_NTH (strtol_l, (const char *__restrict __nptr,
+ char **__restrict __endptr,
+ int __base, locale_t __loc),
+ __isoc23_strtol_l)
+ __nonnull ((1, 4));
+extern unsigned long int __REDIRECT_NTH (strtoul_l,
+ (const char *__restrict __nptr,
+ char **__restrict __endptr,
+ int __base, locale_t __loc),
+ __isoc23_strtoul_l)
+ __nonnull ((1, 4));
+__extension__
+extern long long int __REDIRECT_NTH (strtoll_l, (const char *__restrict __nptr,
+ char **__restrict __endptr,
+ int __base,
+ locale_t __loc),
+ __isoc23_strtoll_l)
+ __nonnull ((1, 4));
+__extension__
+extern unsigned long long int __REDIRECT_NTH (strtoull_l,
+ (const char *__restrict __nptr,
+ char **__restrict __endptr,
+ int __base, locale_t __loc),
+ __isoc23_strtoull_l)
+ __nonnull ((1, 4));
+# else
+extern long int __isoc23_strtol_l (const char *__restrict __nptr,
+ char **__restrict __endptr, int __base,
+ locale_t __loc) __THROW __nonnull ((1, 4));
+extern unsigned long int __isoc23_strtoul_l (const char *__restrict __nptr,
+ char **__restrict __endptr,
+ int __base, locale_t __loc)
+ __THROW __nonnull ((1, 4));
+__extension__
+extern long long int __isoc23_strtoll_l (const char *__restrict __nptr,
+ char **__restrict __endptr,
+ int __base, locale_t __loc)
+ __THROW __nonnull ((1, 4));
+__extension__
+extern unsigned long long int __isoc23_strtoull_l (const char *__restrict __nptr,
+ char **__restrict __endptr,
+ int __base, locale_t __loc)
+ __THROW __nonnull ((1, 4));
+# define strtol_l __isoc23_strtol_l
+# define strtoul_l __isoc23_strtoul_l
+# define strtoll_l __isoc23_strtoll_l
+# define strtoull_l __isoc23_strtoull_l
+# endif
+# endif
+
extern double strtod_l (const char *__restrict __nptr,
char **__restrict __endptr, locale_t __loc)
__THROW __nonnull ((1, 3));
diff --git a/stdlib/strtod_nan_narrow.h b/stdlib/strtod_nan_narrow.h
index 81880ac0f6..05318f9e1a 100644
--- a/stdlib/strtod_nan_narrow.h
+++ b/stdlib/strtod_nan_narrow.h
@@ -19,4 +19,4 @@
#define STRING_TYPE char
#define L_(Ch) Ch
#define STRTOULL(S, E, B) ____strtoull_l_internal ((S), (E), (B), 0, \
- _nl_C_locobj_ptr)
+ false, _nl_C_locobj_ptr)
diff --git a/stdlib/strtod_nan_wide.h b/stdlib/strtod_nan_wide.h
index be70cf004a..3ad3c98bb8 100644
--- a/stdlib/strtod_nan_wide.h
+++ b/stdlib/strtod_nan_wide.h
@@ -19,4 +19,4 @@
#define STRING_TYPE wchar_t
#define L_(Ch) L##Ch
#define STRTOULL(S, E, B) ____wcstoull_l_internal ((S), (E), (B), 0, \
- _nl_C_locobj_ptr)
+ false, _nl_C_locobj_ptr)
diff --git a/stdlib/strtol.c b/stdlib/strtol.c
index b250903388..98fb0f8695 100644
--- a/stdlib/strtol.c
+++ b/stdlib/strtol.c
@@ -16,6 +16,9 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
+#include <features.h>
+#undef __GLIBC_USE_C2X_STRTOL
+#define __GLIBC_USE_C2X_STRTOL 0
#include <stdlib.h>
#include <wchar.h>
#include <locale/localeinfo.h>
@@ -32,17 +35,21 @@
# ifdef QUAD
# define strtol wcstoull
# define __strtol_l __wcstoull_l
+# define __isoc23_strtol __isoc23_wcstoull
# else
# define strtol wcstoul
# define __strtol_l __wcstoul_l
+# define __isoc23_strtol __isoc23_wcstoul
# endif
# else
# ifdef QUAD
# define strtol strtoull
# define __strtol_l __strtoull_l
+# define __isoc23_strtol __isoc23_strtoull
# else
# define strtol strtoul
# define __strtol_l __strtoul_l
+# define __isoc23_strtol __isoc23_strtoul
# endif
# endif
#else
@@ -50,14 +57,17 @@
# ifdef QUAD
# define strtol wcstoll
# define __strtol_l __wcstoll_l
+# define __isoc23_strtol __isoc23_wcstoll
# else
# define strtol wcstol
# define __strtol_l __wcstol_l
+# define __isoc23_strtol __isoc23_wcstol
# endif
# else
# ifdef QUAD
# define strtol strtoll
# define __strtol_l __strtoll_l
+# define __isoc23_strtol __isoc23_strtoll
# endif
# endif
#endif
@@ -88,14 +98,15 @@
extern INT INTERNAL (__strtol_l) (const STRING_TYPE *, STRING_TYPE **, int,
- int, locale_t);
+ int, bool, locale_t);
INT
INTERNAL (strtol) (const STRING_TYPE *nptr, STRING_TYPE **endptr,
int base, int group)
{
- return INTERNAL (__strtol_l) (nptr, endptr, base, group, _NL_CURRENT_LOCALE);
+ return INTERNAL (__strtol_l) (nptr, endptr, base, group, false,
+ _NL_CURRENT_LOCALE);
}
libc_hidden_def (INTERNAL (strtol))
@@ -103,7 +114,16 @@ libc_hidden_def (INTERNAL (strtol))
INT
__strtol (const STRING_TYPE *nptr, STRING_TYPE **endptr, int base)
{
- return INTERNAL (__strtol_l) (nptr, endptr, base, 0, _NL_CURRENT_LOCALE);
+ return INTERNAL (__strtol_l) (nptr, endptr, base, 0, false,
+ _NL_CURRENT_LOCALE);
}
weak_alias (__strtol, strtol)
libc_hidden_weak (strtol)
+
+INT
+__isoc23_strtol (const STRING_TYPE *nptr, STRING_TYPE **endptr, int base)
+{
+ return INTERNAL (__strtol_l) (nptr, endptr, base, 0, true,
+ _NL_CURRENT_LOCALE);
+}
+libc_hidden_def (__isoc23_strtol)
diff --git a/stdlib/strtol_l.c b/stdlib/strtol_l.c
index edbade179b..3424c3feab 100644
--- a/stdlib/strtol_l.c
+++ b/stdlib/strtol_l.c
@@ -16,6 +16,9 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
+#include <features.h>
+#undef __GLIBC_USE_C2X_STRTOL
+#define __GLIBC_USE_C2X_STRTOL 0
#if HAVE_CONFIG_H
# include <config.h>
@@ -61,28 +64,36 @@
# ifdef USE_WIDE_CHAR
# ifdef QUAD
# define strtol_l wcstoull_l
+# define __isoc23_strtol_l __isoc23_wcstoull_l
# else
# define strtol_l wcstoul_l
+# define __isoc23_strtol_l __isoc23_wcstoul_l
# endif
# else
# ifdef QUAD
# define strtol_l strtoull_l
+# define __isoc23_strtol_l __isoc23_strtoull_l
# else
# define strtol_l strtoul_l
+# define __isoc23_strtol_l __isoc23_strtoul_l
# endif
# endif
#else
# ifdef USE_WIDE_CHAR
# ifdef QUAD
# define strtol_l wcstoll_l
+# define __isoc23_strtol_l __isoc23_wcstoll_l
# else
# define strtol_l wcstol_l
+# define __isoc23_strtol_l __isoc23_wcstol_l
# endif
# else
# ifdef QUAD
# define strtol_l strtoll_l
+# define __isoc23_strtol_l __isoc23_strtoll_l
# else
# define strtol_l strtol_l
+# define __isoc23_strtol_l __isoc23_strtol_l
# endif
# endif
#endif
@@ -216,12 +227,14 @@ extern const unsigned char __strtol_ull_rem_tab[] attribute_hidden;
If BASE is 0 the base is determined by the presence of a leading
zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal.
If BASE is < 2 or > 36, it is reset to 10.
+ If BIN_CST is true, binary constants starting "0b" or "0B" are accepted
+ in base 0 and 2.
If ENDPTR is not NULL, a pointer to the character after the last
one converted is stored in *ENDPTR. */
INT
INTERNAL (__strtol_l) (const STRING_TYPE *nptr, STRING_TYPE **endptr,
- int base, int group, locale_t loc)
+ int base, int group, bool bin_cst, locale_t loc)
{
int negative;
unsigned LONG int cutoff;
@@ -311,6 +324,11 @@ INTERNAL (__strtol_l) (const STRING_TYPE *nptr, STRING_TYPE **endptr,
s += 2;
base = 16;
}
+ else if (bin_cst && (base == 0 || base == 2) && TOUPPER (s[1]) == L_('B'))
+ {
+ s += 2;
+ base = 2;
+ }
else if (base == 0)
base = 8;
}
@@ -543,7 +561,15 @@ weak_function
__strtol_l (const STRING_TYPE *nptr, STRING_TYPE **endptr,
int base, locale_t loc)
{
- return INTERNAL (__strtol_l) (nptr, endptr, base, 0, loc);
+ return INTERNAL (__strtol_l) (nptr, endptr, base, 0, false, loc);
}
libc_hidden_def (__strtol_l)
weak_alias (__strtol_l, strtol_l)
+
+INT
+__isoc23_strtol_l (const STRING_TYPE *nptr, STRING_TYPE **endptr,
+ int base, locale_t loc)
+{
+ return INTERNAL (__strtol_l) (nptr, endptr, base, 0, true, loc);
+}
+libc_hidden_def (__isoc23_strtol_l)
diff --git a/stdlib/strtoll.c b/stdlib/strtoll.c
index a273ca43df..63fdf2945e 100644
--- a/stdlib/strtoll.c
+++ b/stdlib/strtoll.c
@@ -31,4 +31,5 @@ compat_symbol (libc, __strtoll_internal, __strtoq_internal, GLIBC_2_0);
# endif
weak_alias (strtoll, strtoq)
weak_alias (strtoll, strtoimax)
+weak_alias (__isoc23_strtoll, __isoc23_strtoimax)
#endif
diff --git a/stdlib/strtoll_l.c b/stdlib/strtoll_l.c
index 32ceda0456..e4a3ac052f 100644
--- a/stdlib/strtoll_l.c
+++ b/stdlib/strtoll_l.c
@@ -18,9 +18,13 @@
#define QUAD 1
+#include <features.h>
+#undef __GLIBC_USE_C2X_STRTOL
+#define __GLIBC_USE_C2X_STRTOL 0
#include <locale.h>
+#include <stdbool.h>
extern long long int ____strtoll_l_internal (const char *, char **, int, int,
- locale_t);
+ bool, locale_t);
#include <strtol_l.c>
diff --git a/stdlib/strtoul_l.c b/stdlib/strtoul_l.c
index f1bd050101..a92a5cedd9 100644
--- a/stdlib/strtoul_l.c
+++ b/stdlib/strtoul_l.c
@@ -18,9 +18,13 @@
#define UNSIGNED 1
+#include <features.h>
+#undef __GLIBC_USE_C2X_STRTOL
+#define __GLIBC_USE_C2X_STRTOL 0
#include <locale.h>
+#include <stdbool.h>
extern unsigned long int ____strtoul_l_internal (const char *, char **, int,
- int, locale_t);
+ int, bool, locale_t);
#include "strtol_l.c"
diff --git a/stdlib/strtoull.c b/stdlib/strtoull.c
index 51859dbd1e..6c9afa3ede 100644
--- a/stdlib/strtoull.c
+++ b/stdlib/strtoull.c
@@ -31,4 +31,5 @@ compat_symbol (libc, __strtoull_internal, __strtouq_internal, GLIBC_2_0);
# endif
weak_alias (strtoull, strtouq)
weak_alias (strtoull, strtoumax)
+weak_alias (__isoc23_strtoull, __isoc23_strtoumax)
#endif
diff --git a/stdlib/strtoull_l.c b/stdlib/strtoull_l.c
index ef102ddf16..2be400799c 100644
--- a/stdlib/strtoull_l.c
+++ b/stdlib/strtoull_l.c
@@ -19,9 +19,14 @@
#define QUAD 1
#define UNSIGNED 1
+#include <features.h>
+#undef __GLIBC_USE_C2X_STRTOL
+#define __GLIBC_USE_C2X_STRTOL 0
#include <locale.h>
+#include <stdbool.h>
extern unsigned long long int ____strtoull_l_internal (const char *, char **,
- int, int, locale_t);
+ int, int, bool,
+ locale_t);
#include <strtol_l.c>
diff --git a/stdlib/tst-strtol-binary-c11.c b/stdlib/tst-strtol-binary-c11.c
new file mode 100644
index 0000000000..6e58bb2599
--- /dev/null
+++ b/stdlib/tst-strtol-binary-c11.c
@@ -0,0 +1,29 @@
+/* Test strtol functions with C2X binary integers (narrow strings,
+ no extensions to C11).
+ Copyright (C) 2022-2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#undef _GNU_SOURCE
+
+#define CHAR char
+#define FNPFX strto
+#define L_(C) C
+#define TEST_C2X 0
+#define TEST_Q 0
+#define TEST_LOCALE 0
+
+#include <tst-strtol-binary-main.c>
diff --git a/stdlib/tst-strtol-binary-c2x.c b/stdlib/tst-strtol-binary-c2x.c
new file mode 100644
index 0000000000..b9ccfda759
--- /dev/null
+++ b/stdlib/tst-strtol-binary-c2x.c
@@ -0,0 +1,32 @@
+/* Test strtol functions with C2X binary integers (narrow strings,
+ no extensions).
+ Copyright (C) 2022-2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/* Some versions of GCC supported for building glibc do not support
+ -std=c2x. */
+#undef _GNU_SOURCE
+#define _ISOC2X_SOURCE
+
+#define CHAR char
+#define FNPFX strto
+#define L_(C) C
+#define TEST_C2X 1
+#define TEST_Q 0
+#define TEST_LOCALE 0
+
+#include <tst-strtol-binary-main.c>
diff --git a/stdlib/tst-strtol-binary-gnu11.c b/stdlib/tst-strtol-binary-gnu11.c
new file mode 100644
index 0000000000..a029591c8b
--- /dev/null
+++ b/stdlib/tst-strtol-binary-gnu11.c
@@ -0,0 +1,34 @@
+/* Test strtol functions with C2X binary integers (narrow strings, GNU
+ extensions, C2X strtol features disabled).
+ Copyright (C) 2022-2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <features.h>
+/* This file tests the old versions of GNU extension functions, which
+ are not normally available to new binaries because GNU extensions
+ normally imply C2X strtol features. */
+#undef __GLIBC_USE_C2X_STRTOL
+#define __GLIBC_USE_C2X_STRTOL 0
+
+#define CHAR char
+#define FNPFX strto
+#define L_(C) C
+#define TEST_C2X 0
+#define TEST_Q 1
+#define TEST_LOCALE 1
+
+#include <tst-strtol-binary-main.c>
diff --git a/stdlib/tst-strtol-binary-gnu2x.c b/stdlib/tst-strtol-binary-gnu2x.c
new file mode 100644
index 0000000000..0a7fdd4d4d
--- /dev/null
+++ b/stdlib/tst-strtol-binary-gnu2x.c
@@ -0,0 +1,27 @@
+/* Test strtol functions with C2X binary integers (narrow strings, GNU
+ extensions).
+ Copyright (C) 2022-2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#define CHAR char
+#define FNPFX strto
+#define L_(C) C
+#define TEST_C2X 1
+#define TEST_Q 1
+#define TEST_LOCALE 1
+
+#include <tst-strtol-binary-main.c>
diff --git a/stdlib/tst-strtol-binary-main.c b/stdlib/tst-strtol-binary-main.c
new file mode 100644
index 0000000000..ece3100298
--- /dev/null
+++ b/stdlib/tst-strtol-binary-main.c
@@ -0,0 +1,151 @@
+/* Test strtol functions with C2X binary integers.
+ Copyright (C) 2022-2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <inttypes.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <wchar.h>
+
+#include <support/check.h>
+#if TEST_LOCALE
+# include <support/support.h>
+#endif
+
+#define CONCAT_(X, Y) X ## Y
+#define CONCAT(X, Y) CONCAT_ (X, Y)
+#define FNX(FN) CONCAT (FNPFX, FN)
+
+#define CHECK_RES(ARG, RES, EP, EXPECTED) \
+ do \
+ { \
+ if (TEST_C2X) \
+ { \
+ TEST_COMPARE ((RES), EXPECTED); \
+ TEST_COMPARE (*(EP), 0); \
+ } \
+ else \
+ { \
+ TEST_COMPARE ((RES), 0); \
+ TEST_VERIFY ((EP) == ((ARG)[0] == L_('-') \
+ ? (ARG) + 2 \
+ : (ARG) + 1)); \
+ } \
+ } \
+ while (0)
+
+static void
+one_check (const CHAR *s, long int expected_l, unsigned long int expected_ul,
+ long long int expected_ll, unsigned long long int expected_ull)
+{
+ CHAR *ep;
+ long int ret_l;
+ unsigned long int ret_ul;
+ long long int ret_ll;
+ unsigned long long int ret_ull;
+ ret_l = FNX (l) (s, &ep, 0);
+ CHECK_RES (s, ret_l, ep, expected_l);
+ ret_l = FNX (l) (s, &ep, 2);
+ CHECK_RES (s, ret_l, ep, expected_l);
+ ret_ul = FNX (ul) (s, &ep, 0);
+ CHECK_RES (s, ret_ul, ep, expected_ul);
+ ret_ul = FNX (ul) (s, &ep, 2);
+ CHECK_RES (s, ret_ul, ep, expected_ul);
+ ret_ll = FNX (ll) (s, &ep, 0);
+ CHECK_RES (s, ret_ll, ep, expected_ll);
+ ret_ll = FNX (ll) (s, &ep, 2);
+ CHECK_RES (s, ret_ll, ep, expected_ll);
+ ret_ull = FNX (ull) (s, &ep, 0);
+ CHECK_RES (s, ret_ull, ep, expected_ull);
+ ret_ull = FNX (ull) (s, &ep, 2);
+ CHECK_RES (s, ret_ull, ep, expected_ull);
+ ret_ll = FNX (imax) (s, &ep, 0);
+ CHECK_RES (s, ret_ll, ep, expected_ll);
+ ret_ll = FNX (imax) (s, &ep, 2);
+ CHECK_RES (s, ret_ll, ep, expected_ll);
+ ret_ull = FNX (umax) (s, &ep, 0);
+ CHECK_RES (s, ret_ull, ep, expected_ull);
+ ret_ull = FNX (umax) (s, &ep, 2);
+ CHECK_RES (s, ret_ull, ep, expected_ull);
+#if TEST_Q
+ ret_ll = FNX (q) (s, &ep, 0);
+ CHECK_RES (s, ret_ll, ep, expected_ll);
+ ret_ll = FNX (q) (s, &ep, 2);
+ CHECK_RES (s, ret_ll, ep, expected_ll);
+ ret_ull = FNX (uq) (s, &ep, 0);
+ CHECK_RES (s, ret_ull, ep, expected_ull);
+ ret_ull = FNX (uq) (s, &ep, 2);
+ CHECK_RES (s, ret_ull, ep, expected_ull);
+#endif
+#if TEST_LOCALE
+ locale_t loc = xnewlocale (LC_NUMERIC_MASK, "C", (locale_t) 0);
+ ret_l = FNX (l_l) (s, &ep, 0, loc);
+ CHECK_RES (s, ret_l, ep, expected_l);
+ ret_l = FNX (l_l) (s, &ep, 2, loc);
+ CHECK_RES (s, ret_l, ep, expected_l);
+ ret_ul = FNX (ul_l) (s, &ep, 0, loc);
+ CHECK_RES (s, ret_ul, ep, expected_ul);
+ ret_ul = FNX (ul_l) (s, &ep, 2, loc);
+ CHECK_RES (s, ret_ul, ep, expected_ul);
+ ret_ll = FNX (ll_l) (s, &ep, 0, loc);
+ CHECK_RES (s, ret_ll, ep, expected_ll);
+ ret_ll = FNX (ll_l) (s, &ep, 2, loc);
+ CHECK_RES (s, ret_ll, ep, expected_ll);
+ ret_ull = FNX (ull_l) (s, &ep, 0, loc);
+ CHECK_RES (s, ret_ull, ep, expected_ull);
+ ret_ull = FNX (ull_l) (s, &ep, 2, loc);
+ CHECK_RES (s, ret_ull, ep, expected_ull);
+#endif
+}
+
+static int
+do_test (void)
+{
+ one_check (L_("0b101"), 5, 5, 5, 5);
+ one_check (L_("0B101"), 5, 5, 5, 5);
+ one_check (L_("-0b11111"), -31, -31, -31, -31);
+ one_check (L_("-0B11111"), -31, -31, -31, -31);
+ one_check (L_("0b111111111111111111111111111111111"),
+ LONG_MAX >= 0x1ffffffffLL ? (long int) 0x1ffffffffLL : LONG_MAX,
+ (ULONG_MAX >= 0x1ffffffffULL
+ ? (unsigned long int) 0x1ffffffffULL
+ : ULONG_MAX),
+ 0x1ffffffffLL, 0x1ffffffffULL);
+ one_check (L_("0B111111111111111111111111111111111"),
+ LONG_MAX >= 0x1ffffffffLL ? (long int) 0x1ffffffffLL : LONG_MAX,
+ (ULONG_MAX >= 0x1ffffffffULL
+ ? (unsigned long int) 0x1ffffffffULL
+ : ULONG_MAX),
+ 0x1ffffffffLL, 0x1ffffffffULL);
+ one_check (L_("-0b111111111111111111111111111111111"),
+ LONG_MIN <= -0x1ffffffffLL ? (long int) -0x1ffffffffLL : LONG_MIN,
+ (ULONG_MAX >= 0x1ffffffffULL
+ ? (unsigned long int) -0x1ffffffffULL
+ : ULONG_MAX),
+ -0x1ffffffffLL, -0x1ffffffffULL);
+ one_check (L_("-0B111111111111111111111111111111111"),
+ LONG_MIN <= -0x1ffffffffLL ? (long int) -0x1ffffffffLL : LONG_MIN,
+ (ULONG_MAX >= 0x1ffffffffULL
+ ? (unsigned long int) -0x1ffffffffULL
+ : ULONG_MAX),
+ -0x1ffffffffLL, -0x1ffffffffULL);
+ return 0;
+}
+
+#include <support/test-driver.c>