diff options
Diffstat (limited to 'stdlib')
-rw-r--r-- | stdlib/Makefile | 12 | ||||
-rw-r--r-- | stdlib/Versions | 8 | ||||
-rw-r--r-- | stdlib/inttypes.h | 40 | ||||
-rw-r--r-- | stdlib/stdlib.h | 119 | ||||
-rw-r--r-- | stdlib/strtod_nan_narrow.h | 2 | ||||
-rw-r--r-- | stdlib/strtod_nan_wide.h | 2 | ||||
-rw-r--r-- | stdlib/strtol.c | 26 | ||||
-rw-r--r-- | stdlib/strtol_l.c | 30 | ||||
-rw-r--r-- | stdlib/strtoll.c | 1 | ||||
-rw-r--r-- | stdlib/strtoll_l.c | 6 | ||||
-rw-r--r-- | stdlib/strtoul_l.c | 6 | ||||
-rw-r--r-- | stdlib/strtoull.c | 1 | ||||
-rw-r--r-- | stdlib/strtoull_l.c | 7 | ||||
-rw-r--r-- | stdlib/tst-strtol-binary-c11.c | 29 | ||||
-rw-r--r-- | stdlib/tst-strtol-binary-c2x.c | 32 | ||||
-rw-r--r-- | stdlib/tst-strtol-binary-gnu11.c | 34 | ||||
-rw-r--r-- | stdlib/tst-strtol-binary-gnu2x.c | 27 | ||||
-rw-r--r-- | stdlib/tst-strtol-binary-main.c | 151 |
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> |