summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2021-04-02 20:46:15 +0200
committerBruno Haible <bruno@clisp.org>2021-04-02 20:46:15 +0200
commitea1816fd6d334b4bfd8368a63d9bda3cad1c9b0d (patch)
tree68ad3316295d89b4d4e54ba1f6dedabf2f258b1a
parent705c23696fcaf5bd9d4f0aaecd106b4a2c1417b2 (diff)
downloadgnulib-ea1816fd6d334b4bfd8368a63d9bda3cad1c9b0d.tar.gz
strtoll: Work around a bug on native Windows and Minix.
* lib/stdlib.in.h (strtoll): Override if REPLACE_STRTOLL is 1. * m4/stdlib_h.m4 (gl_STDLIB_H_DEFAULTS): Initialize REPLACE_STRTOLL. * m4/strtoll.m4 (gl_FUNC_STRTOLL): Test whether strtoll works. Set REPLACE_STRTOLL. * modules/stdlib (Makefile.am): Substitute REPLACE_STRTOLL. * modules/strtoll (configure.ac): Test REPLACE_STRTOLL. * tests/test-strtoll.c (main): Add tests of hexadecimal integer syntax. * doc/posix-functions/strtoll.texi: Mention the bug.
-rw-r--r--ChangeLog12
-rw-r--r--doc/posix-functions/strtoll.texi4
-rw-r--r--lib/stdlib.in.h18
-rw-r--r--m4/stdlib_h.m43
-rw-r--r--m4/strtoll.m436
-rw-r--r--modules/stdlib1
-rw-r--r--modules/strtoll2
-rw-r--r--tests/test-strtoll.c62
8 files changed, 132 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index 9a84589cbc..b479574576 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
2021-04-02 Bruno Haible <bruno@clisp.org>
+ strtoll: Work around a bug on native Windows and Minix.
+ * lib/stdlib.in.h (strtoll): Override if REPLACE_STRTOLL is 1.
+ * m4/stdlib_h.m4 (gl_STDLIB_H_DEFAULTS): Initialize REPLACE_STRTOLL.
+ * m4/strtoll.m4 (gl_FUNC_STRTOLL): Test whether strtoll works. Set
+ REPLACE_STRTOLL.
+ * modules/stdlib (Makefile.am): Substitute REPLACE_STRTOLL.
+ * modules/strtoll (configure.ac): Test REPLACE_STRTOLL.
+ * tests/test-strtoll.c (main): Add tests of hexadecimal integer syntax.
+ * doc/posix-functions/strtoll.texi: Mention the bug.
+
+2021-04-02 Bruno Haible <bruno@clisp.org>
+
strtol: Work around a bug on native Windows and Minix.
* lib/stdlib.in.h (strtol): New declaration.
* m4/stdlib_h.m4 (gl_STDLIB_H): Test whether strtol is declared.
diff --git a/doc/posix-functions/strtoll.texi b/doc/posix-functions/strtoll.texi
index 45a70350d7..b507fc33c6 100644
--- a/doc/posix-functions/strtoll.texi
+++ b/doc/posix-functions/strtoll.texi
@@ -11,6 +11,10 @@ Portability problems fixed by Gnulib:
@item
This function is missing on some platforms:
HP-UX 11.11, MSVC 9.
+@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 e2c461b59a..c07fd1f5d7 100644
--- a/lib/stdlib.in.h
+++ b/lib/stdlib.in.h
@@ -1252,15 +1252,29 @@ _GL_WARN_ON_USE (strtol, "strtol is unportable - "
stored in *ENDPTR.
Upon overflow, the return value is LLONG_MAX or LLONG_MIN, and errno is set
to ERANGE. */
-# if !@HAVE_STRTOLL@
+# if @REPLACE_STRTOLL@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# define strtoll rpl_strtoll
+# endif
+# define GNULIB_defined_strtoll_function 1
+_GL_FUNCDECL_RPL (strtoll, long long,
+ (const char *restrict string, char **restrict endptr,
+ int base)
+ _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (strtoll, long long,
+ (const char *restrict string, char **restrict endptr,
+ int base));
+# else
+# if !@HAVE_STRTOLL@
_GL_FUNCDECL_SYS (strtoll, long long,
(const char *restrict string, char **restrict endptr,
int base)
_GL_ARG_NONNULL ((1)));
-# endif
+# endif
_GL_CXXALIAS_SYS (strtoll, long long,
(const char *restrict string, char **restrict endptr,
int base));
+# endif
_GL_CXXALIASWARN (strtoll);
#elif defined GNULIB_POSIXCHECK
# undef strtoll
diff --git a/m4/stdlib_h.m4 b/m4/stdlib_h.m4
index 7f084f1ba6..5fdb0a7063 100644
--- a/m4/stdlib_h.m4
+++ b/m4/stdlib_h.m4
@@ -1,4 +1,4 @@
-# stdlib_h.m4 serial 58
+# stdlib_h.m4 serial 59
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,
@@ -170,6 +170,7 @@ AC_DEFUN([gl_STDLIB_H_DEFAULTS],
REPLACE_STRTOD=0; AC_SUBST([REPLACE_STRTOD])
REPLACE_STRTOL=0; AC_SUBST([REPLACE_STRTOL])
REPLACE_STRTOLD=0; AC_SUBST([REPLACE_STRTOLD])
+ REPLACE_STRTOLL=0; AC_SUBST([REPLACE_STRTOLL])
REPLACE_STRTOUL=0; AC_SUBST([REPLACE_STRTOUL])
REPLACE_STRTOULL=0; AC_SUBST([REPLACE_STRTOULL])
REPLACE_UNSETENV=0; AC_SUBST([REPLACE_UNSETENV])
diff --git a/m4/strtoll.m4 b/m4/strtoll.m4
index d2c9e5310d..14455dc3db 100644
--- a/m4/strtoll.m4
+++ b/m4/strtoll.m4
@@ -1,4 +1,4 @@
-# strtoll.m4 serial 8
+# strtoll.m4 serial 9
dnl Copyright (C) 2002, 2004, 2006, 2008-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,
@@ -7,8 +7,40 @@ dnl with or without modifications, as long as this notice is preserved.
AC_DEFUN([gl_FUNC_STRTOLL],
[
AC_REQUIRE([gl_STDLIB_H_DEFAULTS])
+ AC_REQUIRE([AC_CANONICAL_HOST])
AC_CHECK_FUNCS([strtoll])
- if test $ac_cv_func_strtoll = no; then
+ if test $ac_cv_func_strtoll = yes; then
+ AC_CACHE_CHECK([whether strtoll works],
+ [gl_cv_func_strtoll_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) strtoll (input, &term, 16);
+ if (term != input + 1)
+ result |= 1;
+ }
+ return result;
+ ]])
+ ],
+ [gl_cv_func_strtoll_works=yes],
+ [gl_cv_func_strtoll_works=no],
+ [case "$host_os" in
+ # Guess no on native Windows.
+ mingw*) gl_cv_func_strtoll_works="guessing no" ;;
+ *) gl_cv_func_strtoll_works="$gl_cross_guess_normal" ;;
+ esac
+ ])
+ ])
+ case "$gl_cv_func_strtoll_works" in
+ *yes) ;;
+ *) REPLACE_STRTOLL=1 ;;
+ esac
+ else
HAVE_STRTOLL=0
fi
])
diff --git a/modules/stdlib b/modules/stdlib
index 33b8d500cc..ad04ede819 100644
--- a/modules/stdlib
+++ b/modules/stdlib
@@ -142,6 +142,7 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \
-e 's|@''REPLACE_STRTOD''@|$(REPLACE_STRTOD)|g' \
-e 's|@''REPLACE_STRTOL''@|$(REPLACE_STRTOL)|g' \
-e 's|@''REPLACE_STRTOLD''@|$(REPLACE_STRTOLD)|g' \
+ -e 's|@''REPLACE_STRTOLL''@|$(REPLACE_STRTOLL)|g' \
-e 's|@''REPLACE_STRTOUL''@|$(REPLACE_STRTOUL)|g' \
-e 's|@''REPLACE_STRTOULL''@|$(REPLACE_STRTOULL)|g' \
-e 's|@''REPLACE_UNSETENV''@|$(REPLACE_UNSETENV)|g' \
diff --git a/modules/strtoll b/modules/strtoll
index 7b6d80c55d..da5a5a157a 100644
--- a/modules/strtoll
+++ b/modules/strtoll
@@ -12,7 +12,7 @@ stdlib
configure.ac:
gl_FUNC_STRTOLL
-if test $HAVE_STRTOLL = 0; then
+if test $HAVE_STRTOLL = 0 || test $REPLACE_STRTOLL = 1; then
AC_LIBOBJ([strtoll])
gl_PREREQ_STRTOLL
fi
diff --git a/tests/test-strtoll.c b/tests/test-strtoll.c
index ad43fc6f56..5f2b19331f 100644
--- a/tests/test-strtoll.c
+++ b/tests/test-strtoll.c
@@ -177,5 +177,67 @@ main (void)
ASSERT (errno == 0);
}
+ /* Hexadecimal integer syntax. */
+ {
+ const char input[] = "0x2A";
+ char *ptr;
+ long long result;
+ errno = 0;
+ result = strtoll (input, &ptr, 10);
+ ASSERT (result == 0LL);
+ ASSERT (ptr == input + 1);
+ ASSERT (errno == 0);
+ }
+ {
+ const char input[] = "0x2A";
+ char *ptr;
+ long long result;
+ errno = 0;
+ result = strtoll (input, &ptr, 16);
+ ASSERT (result == 42LL);
+ ASSERT (ptr == input + 4);
+ ASSERT (errno == 0);
+ }
+ {
+ const char input[] = "0x2A";
+ char *ptr;
+ long long result;
+ errno = 0;
+ result = strtoll (input, &ptr, 0);
+ ASSERT (result == 42LL);
+ ASSERT (ptr == input + 4);
+ ASSERT (errno == 0);
+ }
+ {
+ const char input[] = "0x";
+ char *ptr;
+ long long result;
+ errno = 0;
+ result = strtoll (input, &ptr, 10);
+ ASSERT (result == 0LL);
+ ASSERT (ptr == input + 1);
+ ASSERT (errno == 0);
+ }
+ {
+ const char input[] = "0x";
+ char *ptr;
+ long long result;
+ errno = 0;
+ result = strtoll (input, &ptr, 16);
+ ASSERT (result == 0LL);
+ ASSERT (ptr == input + 1);
+ ASSERT (errno == 0);
+ }
+ {
+ const char input[] = "0x";
+ char *ptr;
+ long long result;
+ errno = 0;
+ result = strtoll (input, &ptr, 0);
+ ASSERT (result == 0LL);
+ ASSERT (ptr == input + 1);
+ ASSERT (errno == 0);
+ }
+
return 0;
}