summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2021-04-02 19:56:28 +0200
committerBruno Haible <bruno@clisp.org>2021-04-02 20:03:36 +0200
commitcbff21f910e678340da2cadf0bbf2bdc191c0eb9 (patch)
treee2d71678fe7d114328bb500dbbb1512f3e308b4d
parent022521230ffa940a5428ee2a50120dc882920b16 (diff)
downloadgnulib-cbff21f910e678340da2cadf0bbf2bdc191c0eb9.tar.gz
strtoul: Work around a bug on native Windows and Minix.
Reported by Eric Blake <eblake@redhat.com> in <https://lists.gnu.org/archive/html/bug-gnulib/2021-03/msg00082.html>. * lib/stdlib.in.h (strtoul): New declaration. * m4/stdlib_h.m4 (gl_STDLIB_H): Test whether strtoul is declared. (gl_STDLIB_H_DEFAULTS): Initialize GNULIB_STRTOUL, HAVE_STRTOUL, REPLACE_STRTOUL. * m4/strtoul.m4 (gl_FUNC_STRTOUL): Require gl_STDLIB_H_DEFAULTS. Test whether strtoul works. Set REPLACE_STRTOUL. * modules/stdlib (Makefile.am): Substitute GNULIB_STRTOUL, HAVE_STRTOUL, REPLACE_STRTOUL. * modules/strtoul (Status, Notice): Remove. (Depends-on): Add stdlib. (configure.ac): Test HAVE_STRTOUL and REPLACE_STRTOUL. Invoke gl_STDLIB_MODULE_INDICATOR. * tests/test-strtoul.c (main): Add tests of hexadecimal integer syntax. * doc/posix-functions/strtoul.texi: Mention the bug.
-rw-r--r--ChangeLog20
-rw-r--r--doc/posix-functions/strtoul.texi4
-rw-r--r--lib/stdlib.in.h40
-rw-r--r--m4/stdlib_h.m47
-rw-r--r--m4/strtoul.m438
-rw-r--r--modules/stdlib3
-rw-r--r--modules/strtoul10
-rw-r--r--tests/test-strtoul.c62
8 files changed, 174 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index d5b833ae3b..9ce3baeb4f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,25 @@
2021-04-02 Bruno Haible <bruno@clisp.org>
+ strtoul: Work around a bug on native Windows and Minix.
+ Reported by Eric Blake <eblake@redhat.com> in
+ <https://lists.gnu.org/archive/html/bug-gnulib/2021-03/msg00082.html>.
+ * lib/stdlib.in.h (strtoul): New declaration.
+ * m4/stdlib_h.m4 (gl_STDLIB_H): Test whether strtoul is declared.
+ (gl_STDLIB_H_DEFAULTS): Initialize GNULIB_STRTOUL, HAVE_STRTOUL,
+ REPLACE_STRTOUL.
+ * m4/strtoul.m4 (gl_FUNC_STRTOUL): Require gl_STDLIB_H_DEFAULTS. Test
+ whether strtoul works. Set REPLACE_STRTOUL.
+ * modules/stdlib (Makefile.am): Substitute GNULIB_STRTOUL, HAVE_STRTOUL,
+ REPLACE_STRTOUL.
+ * modules/strtoul (Status, Notice): Remove.
+ (Depends-on): Add stdlib.
+ (configure.ac): Test HAVE_STRTOUL and REPLACE_STRTOUL. Invoke
+ gl_STDLIB_MODULE_INDICATOR.
+ * tests/test-strtoul.c (main): Add tests of hexadecimal integer syntax.
+ * doc/posix-functions/strtoul.texi: Mention the bug.
+
+2021-04-02 Bruno Haible <bruno@clisp.org>
+
strtol, strtoul, strtoll, strtoull: Optimize.
* lib/strtol.c (GROUP_PARAM_PROTO): New macro.
(INTERNAL): Define differently if !USE_NUMBER_GROUPING.
diff --git a/doc/posix-functions/strtoul.texi b/doc/posix-functions/strtoul.texi
index b79b56bb68..3b1fa7fb5e 100644
--- a/doc/posix-functions/strtoul.texi
+++ b/doc/posix-functions/strtoul.texi
@@ -10,6 +10,10 @@ Portability problems fixed by Gnulib:
@itemize
@item
This function is missing on some old platforms.
+@item
+This function does not parse the leading @samp{0} when the input string is
+@code{"0x"} and the base is 16 or 0 on some platforms:
+Minix 3.3, mingw, MSVC 14.
@end itemize
Portability problems not fixed by Gnulib:
diff --git a/lib/stdlib.in.h b/lib/stdlib.in.h
index 49fc44e14a..0a377c0755 100644
--- a/lib/stdlib.in.h
+++ b/lib/stdlib.in.h
@@ -1229,6 +1229,46 @@ _GL_WARN_ON_USE (strtoll, "strtoll is unportable - "
# endif
#endif
+#if @GNULIB_STRTOUL@
+/* Parse an unsigned integer whose textual representation starts at STRING.
+ The integer is expected to be in base BASE (2 <= BASE <= 36); if BASE == 0,
+ it may be decimal or octal (with prefix "0") or hexadecimal (with prefix
+ "0x").
+ If ENDPTR is not NULL, the address of the first byte after the integer is
+ stored in *ENDPTR.
+ Upon overflow, the return value is ULONG_MAX, and errno is set to ERANGE. */
+# if @REPLACE_STRTOUL@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# define strtoul rpl_strtoul
+# endif
+# define GNULIB_defined_strtoul_function 1
+_GL_FUNCDECL_RPL (strtoul, unsigned long,
+ (const char *restrict string, char **restrict endptr,
+ int base)
+ _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (strtoul, unsigned long,
+ (const char *restrict string, char **restrict endptr,
+ int base));
+# else
+# if !@HAVE_STRTOUL@
+_GL_FUNCDECL_SYS (strtoul, unsigned long,
+ (const char *restrict string, char **restrict endptr,
+ int base)
+ _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (strtoul, unsigned long,
+ (const char *restrict string, char **restrict endptr,
+ int base));
+# endif
+_GL_CXXALIASWARN (strtoul);
+#elif defined GNULIB_POSIXCHECK
+# undef strtoul
+# if HAVE_RAW_DECL_STRTOUL
+_GL_WARN_ON_USE (strtoul, "strtoul is unportable - "
+ "use gnulib module strtoul for portability");
+# endif
+#endif
+
#if @GNULIB_STRTOULL@
/* Parse an unsigned integer whose textual representation starts at STRING.
The integer is expected to be in base BASE (2 <= BASE <= 36); if BASE == 0,
diff --git a/m4/stdlib_h.m4 b/m4/stdlib_h.m4
index 5a02972e05..5895586a23 100644
--- a/m4/stdlib_h.m4
+++ b/m4/stdlib_h.m4
@@ -1,4 +1,4 @@
-# stdlib_h.m4 serial 55
+# stdlib_h.m4 serial 56
dnl Copyright (C) 2007-2021 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -28,7 +28,7 @@ AC_DEFUN([gl_STDLIB_H],
posix_memalign posix_openpt ptsname ptsname_r qsort_r
random random_r reallocarray realpath rpmatch secure_getenv setenv
setstate setstate_r srandom srandom_r
- strtod strtold strtoll strtoull unlockpt unsetenv])
+ strtod strtold strtoll strtoul strtoull unlockpt unsetenv])
AC_REQUIRE([AC_C_RESTRICT])
@@ -90,6 +90,7 @@ AC_DEFUN([gl_STDLIB_H_DEFAULTS],
GNULIB_STRTOD=0; AC_SUBST([GNULIB_STRTOD])
GNULIB_STRTOLD=0; AC_SUBST([GNULIB_STRTOLD])
GNULIB_STRTOLL=0; AC_SUBST([GNULIB_STRTOLL])
+ GNULIB_STRTOUL=0; AC_SUBST([GNULIB_STRTOUL])
GNULIB_STRTOULL=0; AC_SUBST([GNULIB_STRTOULL])
GNULIB_SYSTEM_POSIX=0; AC_SUBST([GNULIB_SYSTEM_POSIX])
GNULIB_UNLOCKPT=0; AC_SUBST([GNULIB_UNLOCKPT])
@@ -139,6 +140,7 @@ AC_DEFUN([gl_STDLIB_H_DEFAULTS],
HAVE_STRTOD=1; AC_SUBST([HAVE_STRTOD])
HAVE_STRTOLD=1; AC_SUBST([HAVE_STRTOLD])
HAVE_STRTOLL=1; AC_SUBST([HAVE_STRTOLL])
+ HAVE_STRTOUL=1; AC_SUBST([HAVE_STRTOUL])
HAVE_STRTOULL=1; AC_SUBST([HAVE_STRTOULL])
HAVE_STRUCT_RANDOM_DATA=1; AC_SUBST([HAVE_STRUCT_RANDOM_DATA])
HAVE_SYS_LOADAVG_H=0; AC_SUBST([HAVE_SYS_LOADAVG_H])
@@ -165,6 +167,7 @@ AC_DEFUN([gl_STDLIB_H_DEFAULTS],
REPLACE_SETSTATE=0; AC_SUBST([REPLACE_SETSTATE])
REPLACE_STRTOD=0; AC_SUBST([REPLACE_STRTOD])
REPLACE_STRTOLD=0; AC_SUBST([REPLACE_STRTOLD])
+ REPLACE_STRTOUL=0; AC_SUBST([REPLACE_STRTOUL])
REPLACE_UNSETENV=0; AC_SUBST([REPLACE_UNSETENV])
REPLACE_WCTOMB=0; AC_SUBST([REPLACE_WCTOMB])
])
diff --git a/m4/strtoul.m4 b/m4/strtoul.m4
index 853c1a6deb..b915679703 100644
--- a/m4/strtoul.m4
+++ b/m4/strtoul.m4
@@ -1,4 +1,4 @@
-# strtoul.m4 serial 5
+# strtoul.m4 serial 6
dnl Copyright (C) 2002, 2006, 2009-2021 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -6,5 +6,41 @@ dnl with or without modifications, as long as this notice is preserved.
AC_DEFUN([gl_FUNC_STRTOUL],
[
+ AC_REQUIRE([gl_STDLIB_H_DEFAULTS])
+ AC_REQUIRE([AC_CANONICAL_HOST])
AC_CHECK_FUNCS([strtoul])
+ if test $ac_cv_func_strtoul = yes; then
+ AC_CACHE_CHECK([whether strtoul works],
+ [gl_cv_func_strtoul_works],
+ [AC_RUN_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <stdlib.h>]],
+ [[int result = 0;
+ char *term;
+ /* This test fails on Minix and native Windows. */
+ {
+ const char input[] = "0x";
+ (void) strtoul (input, &term, 16);
+ if (term != input + 1)
+ result |= 1;
+ }
+ return result;
+ ]])
+ ],
+ [gl_cv_func_strtoul_works=yes],
+ [gl_cv_func_strtoul_works=no],
+ [case "$host_os" in
+ # Guess no on native Windows.
+ mingw*) gl_cv_func_strtoul_works="guessing no" ;;
+ *) gl_cv_func_strtoul_works="$gl_cross_guess_normal" ;;
+ esac
+ ])
+ ])
+ case "$gl_cv_func_strtoul_works" in
+ *yes) ;;
+ *) REPLACE_STRTOUL=1 ;;
+ esac
+ else
+ HAVE_STRTOUL=0
+ fi
])
diff --git a/modules/stdlib b/modules/stdlib
index 9b65a0181c..998f44d240 100644
--- a/modules/stdlib
+++ b/modules/stdlib
@@ -64,6 +64,7 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \
-e 's/@''GNULIB_STRTOD''@/$(GNULIB_STRTOD)/g' \
-e 's/@''GNULIB_STRTOLD''@/$(GNULIB_STRTOLD)/g' \
-e 's/@''GNULIB_STRTOLL''@/$(GNULIB_STRTOLL)/g' \
+ -e 's/@''GNULIB_STRTOUL''@/$(GNULIB_STRTOUL)/g' \
-e 's/@''GNULIB_STRTOULL''@/$(GNULIB_STRTOULL)/g' \
-e 's/@''GNULIB_SYSTEM_POSIX''@/$(GNULIB_SYSTEM_POSIX)/g' \
-e 's/@''GNULIB_UNLOCKPT''@/$(GNULIB_UNLOCKPT)/g' \
@@ -111,6 +112,7 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \
-e 's|@''HAVE_STRTOD''@|$(HAVE_STRTOD)|g' \
-e 's|@''HAVE_STRTOLD''@|$(HAVE_STRTOLD)|g' \
-e 's|@''HAVE_STRTOLL''@|$(HAVE_STRTOLL)|g' \
+ -e 's|@''HAVE_STRTOUL''@|$(HAVE_STRTOUL)|g' \
-e 's|@''HAVE_STRTOULL''@|$(HAVE_STRTOULL)|g' \
-e 's|@''HAVE_STRUCT_RANDOM_DATA''@|$(HAVE_STRUCT_RANDOM_DATA)|g' \
-e 's|@''HAVE_SYS_LOADAVG_H''@|$(HAVE_SYS_LOADAVG_H)|g' \
@@ -137,6 +139,7 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \
-e 's|@''REPLACE_SETSTATE''@|$(REPLACE_SETSTATE)|g' \
-e 's|@''REPLACE_STRTOD''@|$(REPLACE_STRTOD)|g' \
-e 's|@''REPLACE_STRTOLD''@|$(REPLACE_STRTOLD)|g' \
+ -e 's|@''REPLACE_STRTOUL''@|$(REPLACE_STRTOUL)|g' \
-e 's|@''REPLACE_UNSETENV''@|$(REPLACE_UNSETENV)|g' \
-e 's|@''REPLACE_WCTOMB''@|$(REPLACE_WCTOMB)|g' \
-e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
diff --git a/modules/strtoul b/modules/strtoul
index 7f3139ca48..c790e41f78 100644
--- a/modules/strtoul
+++ b/modules/strtoul
@@ -1,24 +1,20 @@
Description:
strtoul() function: convert string to 'unsigned long'.
-Status:
-obsolete
-
-Notice:
-This module is obsolete.
-
Files:
lib/strtol.c
lib/strtoul.c
m4/strtoul.m4
Depends-on:
+stdlib
configure.ac:
gl_FUNC_STRTOUL
-if test $ac_cv_func_strtoul = no; then
+if test $HAVE_STRTOUL = 0 || test $REPLACE_STRTOUL = 1; then
AC_LIBOBJ([strtoul])
fi
+gl_STDLIB_MODULE_INDICATOR([strtoul])
Makefile.am:
diff --git a/tests/test-strtoul.c b/tests/test-strtoul.c
index 0e1917daea..d34272bccd 100644
--- a/tests/test-strtoul.c
+++ b/tests/test-strtoul.c
@@ -176,5 +176,67 @@ main (void)
ASSERT (errno == 0);
}
+ /* Hexadecimal integer syntax. */
+ {
+ const char input[] = "0x2A";
+ char *ptr;
+ unsigned long result;
+ errno = 0;
+ result = strtoul (input, &ptr, 10);
+ ASSERT (result == 0UL);
+ ASSERT (ptr == input + 1);
+ ASSERT (errno == 0);
+ }
+ {
+ const char input[] = "0x2A";
+ char *ptr;
+ unsigned long result;
+ errno = 0;
+ result = strtoul (input, &ptr, 16);
+ ASSERT (result == 42UL);
+ ASSERT (ptr == input + 4);
+ ASSERT (errno == 0);
+ }
+ {
+ const char input[] = "0x2A";
+ char *ptr;
+ unsigned long result;
+ errno = 0;
+ result = strtoul (input, &ptr, 0);
+ ASSERT (result == 42UL);
+ ASSERT (ptr == input + 4);
+ ASSERT (errno == 0);
+ }
+ {
+ const char input[] = "0x";
+ char *ptr;
+ unsigned long result;
+ errno = 0;
+ result = strtoul (input, &ptr, 10);
+ ASSERT (result == 0UL);
+ ASSERT (ptr == input + 1);
+ ASSERT (errno == 0);
+ }
+ {
+ const char input[] = "0x";
+ char *ptr;
+ unsigned long result;
+ errno = 0;
+ result = strtoul (input, &ptr, 16);
+ ASSERT (result == 0UL);
+ ASSERT (ptr == input + 1);
+ ASSERT (errno == 0);
+ }
+ {
+ const char input[] = "0x";
+ char *ptr;
+ unsigned long result;
+ errno = 0;
+ result = strtoul (input, &ptr, 0);
+ ASSERT (result == 0UL);
+ ASSERT (ptr == input + 1);
+ ASSERT (errno == 0);
+ }
+
return 0;
}