]> Savannah Git Hosting - gnulib.git/commitdiff
strtol: Work around a bug on native Windows and Minix.
authorBruno Haible <bruno@clisp.org>
Fri, 2 Apr 2021 18:42:13 +0000 (20:42 +0200)
committerBruno Haible <bruno@clisp.org>
Fri, 2 Apr 2021 18:42:13 +0000 (20:42 +0200)
* lib/stdlib.in.h (strtol): New declaration.
* m4/stdlib_h.m4 (gl_STDLIB_H): Test whether strtol is declared.
(gl_STDLIB_H_DEFAULTS): Initialize GNULIB_STRTOL, HAVE_STRTOL,
REPLACE_STRTOL.
* m4/strtol.m4 (gl_FUNC_STRTOL): Require gl_STDLIB_H_DEFAULTS. Test
whether strtol works. Set REPLACE_STRTOL.
* modules/stdlib (Makefile.am): Substitute GNULIB_STRTOL, HAVE_STRTOL,
REPLACE_STRTOL.
* modules/strtol (Status, Notice): Remove.
(Depends-on): Add stdlib.
(configure.ac): Test HAVE_STRTOL and REPLACE_STRTOL. Invoke
gl_STDLIB_MODULE_INDICATOR.
* tests/test-strtol.c (main): Add tests of hexadecimal integer syntax.
* doc/posix-functions/strtol.texi: Mention the bug.

ChangeLog
doc/posix-functions/strtol.texi
lib/stdlib.in.h
m4/stdlib_h.m4
m4/strtol.m4
modules/stdlib
modules/strtol
tests/test-strtol.c

index 5d752aba3f668ab4e587248d613e906a3788900b..9a84589cbc078f08e08bab70f83a81297fed7bba 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+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.
+       (gl_STDLIB_H_DEFAULTS): Initialize GNULIB_STRTOL, HAVE_STRTOL,
+       REPLACE_STRTOL.
+       * m4/strtol.m4 (gl_FUNC_STRTOL): Require gl_STDLIB_H_DEFAULTS. Test
+       whether strtol works. Set REPLACE_STRTOL.
+       * modules/stdlib (Makefile.am): Substitute GNULIB_STRTOL, HAVE_STRTOL,
+       REPLACE_STRTOL.
+       * modules/strtol (Status, Notice): Remove.
+       (Depends-on): Add stdlib.
+       (configure.ac): Test HAVE_STRTOL and REPLACE_STRTOL. Invoke
+       gl_STDLIB_MODULE_INDICATOR.
+       * tests/test-strtol.c (main): Add tests of hexadecimal integer syntax.
+       * doc/posix-functions/strtol.texi: Mention the bug.
+
 2021-04-02  Bruno Haible  <bruno@clisp.org>
 
        strtoull: Work around a bug on native Windows and Minix.
index bf539c416eceb1c145c8764bdf8d55dd6464e2a7..c9333ce3971c651cbfa4f5f200f981d1087deba0 100644 (file)
@@ -11,6 +11,10 @@ Portability problems fixed by Gnulib:
 @item
 This function is missing on some old platforms.
 @end itemize
+@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.
 
 Portability problems not fixed by Gnulib:
 @itemize
index 050636245b5af792a12f64675e0ade3c9240fcc2..e2c461b59adaa0c949150a8bd69c550041659226 100644 (file)
@@ -1202,6 +1202,47 @@ _GL_WARN_ON_USE (strtold, "strtold is unportable - "
 # endif
 #endif
 
+#if @GNULIB_STRTOL@
+/* Parse a signed 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 LONG_MAX or LONG_MIN, and errno is set
+   to ERANGE.  */
+# if @REPLACE_STRTOL@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   define strtol rpl_strtol
+#  endif
+#  define GNULIB_defined_strtol_function 1
+_GL_FUNCDECL_RPL (strtol, long,
+                  (const char *restrict string, char **restrict endptr,
+                   int base)
+                  _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (strtol, long,
+                  (const char *restrict string, char **restrict endptr,
+                   int base));
+# else
+#  if !@HAVE_STRTOL@
+_GL_FUNCDECL_SYS (strtol, long,
+                  (const char *restrict string, char **restrict endptr,
+                   int base)
+                  _GL_ARG_NONNULL ((1)));
+#  endif
+_GL_CXXALIAS_SYS (strtol, long,
+                  (const char *restrict string, char **restrict endptr,
+                   int base));
+# endif
+_GL_CXXALIASWARN (strtol);
+#elif defined GNULIB_POSIXCHECK
+# undef strtol
+# if HAVE_RAW_DECL_STRTOL
+_GL_WARN_ON_USE (strtol, "strtol is unportable - "
+                 "use gnulib module strtol for portability");
+# endif
+#endif
+
 #if @GNULIB_STRTOLL@
 /* Parse a signed integer whose textual representation starts at STRING.
    The integer is expected to be in base BASE (2 <= BASE <= 36); if BASE == 0,
index 652ba86ffd26c609d5e7fe36e53c97139c1945bf..7f084f1ba6f53f8cfd30aa54b5efe2b1cba7a59f 100644 (file)
@@ -1,4 +1,4 @@
-# stdlib_h.m4 serial 57
+# stdlib_h.m4 serial 58
 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 strtoul strtoull unlockpt unsetenv])
+    strtod strtol strtold strtoll strtoul strtoull unlockpt unsetenv])
 
   AC_REQUIRE([AC_C_RESTRICT])
 
@@ -88,6 +88,7 @@ AC_DEFUN([gl_STDLIB_H_DEFAULTS],
   GNULIB_SECURE_GETENV=0; AC_SUBST([GNULIB_SECURE_GETENV])
   GNULIB_SETENV=0;        AC_SUBST([GNULIB_SETENV])
   GNULIB_STRTOD=0;        AC_SUBST([GNULIB_STRTOD])
+  GNULIB_STRTOL=0;        AC_SUBST([GNULIB_STRTOL])
   GNULIB_STRTOLD=0;       AC_SUBST([GNULIB_STRTOLD])
   GNULIB_STRTOLL=0;       AC_SUBST([GNULIB_STRTOLL])
   GNULIB_STRTOUL=0;       AC_SUBST([GNULIB_STRTOUL])
@@ -138,6 +139,7 @@ AC_DEFUN([gl_STDLIB_H_DEFAULTS],
   HAVE_SETSTATE=1;           AC_SUBST([HAVE_SETSTATE])
   HAVE_DECL_SETSTATE=1;      AC_SUBST([HAVE_DECL_SETSTATE])
   HAVE_STRTOD=1;             AC_SUBST([HAVE_STRTOD])
+  HAVE_STRTOL=1;             AC_SUBST([HAVE_STRTOL])
   HAVE_STRTOLD=1;            AC_SUBST([HAVE_STRTOLD])
   HAVE_STRTOLL=1;            AC_SUBST([HAVE_STRTOLL])
   HAVE_STRTOUL=1;            AC_SUBST([HAVE_STRTOUL])
@@ -166,6 +168,7 @@ AC_DEFUN([gl_STDLIB_H_DEFAULTS],
   REPLACE_SETENV=0;          AC_SUBST([REPLACE_SETENV])
   REPLACE_SETSTATE=0;        AC_SUBST([REPLACE_SETSTATE])
   REPLACE_STRTOD=0;          AC_SUBST([REPLACE_STRTOD])
+  REPLACE_STRTOL=0;          AC_SUBST([REPLACE_STRTOL])
   REPLACE_STRTOLD=0;         AC_SUBST([REPLACE_STRTOLD])
   REPLACE_STRTOUL=0;         AC_SUBST([REPLACE_STRTOUL])
   REPLACE_STRTOULL=0;        AC_SUBST([REPLACE_STRTOULL])
index ec7b8d1bc0b477a9125df98f51e98180d5e395c0..343507b02fadfc038448ef274bb90e8ffa8297da 100644 (file)
@@ -1,4 +1,4 @@
-# strtol.m4 serial 6
+# strtol.m4 serial 7
 dnl Copyright (C) 2002-2003, 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_STRTOL],
 [
+  AC_REQUIRE([gl_STDLIB_H_DEFAULTS])
+  AC_REQUIRE([AC_CANONICAL_HOST])
   AC_CHECK_FUNCS([strtol])
+  if test $ac_cv_func_strtol = yes; then
+    AC_CACHE_CHECK([whether strtol works],
+      [gl_cv_func_strtol_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) strtol (input, &term, 16);
+                if (term != input + 1)
+                  result |= 1;
+              }
+              return result;
+            ]])
+         ],
+         [gl_cv_func_strtol_works=yes],
+         [gl_cv_func_strtol_works=no],
+         [case "$host_os" in
+                    # Guess no on native Windows.
+            mingw*) gl_cv_func_strtol_works="guessing no" ;;
+            *)      gl_cv_func_strtol_works="$gl_cross_guess_normal" ;;
+          esac
+         ])
+    ])
+    case "$gl_cv_func_strtol_works" in
+      *yes) ;;
+      *)    REPLACE_STRTOL=1 ;;
+    esac
+  else
+    HAVE_STRTOL=0
+  fi
 ])
index 4bd7a5c683347a796214f5fe035f12b9ac1ba8ed..33b8d500cc8c4756a5d0e481f745a78b9948a25e 100644 (file)
@@ -62,6 +62,7 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \
              -e 's/@''GNULIB_SECURE_GETENV''@/$(GNULIB_SECURE_GETENV)/g' \
              -e 's/@''GNULIB_SETENV''@/$(GNULIB_SETENV)/g' \
              -e 's/@''GNULIB_STRTOD''@/$(GNULIB_STRTOD)/g' \
+             -e 's/@''GNULIB_STRTOL''@/$(GNULIB_STRTOL)/g' \
              -e 's/@''GNULIB_STRTOLD''@/$(GNULIB_STRTOLD)/g' \
              -e 's/@''GNULIB_STRTOLL''@/$(GNULIB_STRTOLL)/g' \
              -e 's/@''GNULIB_STRTOUL''@/$(GNULIB_STRTOUL)/g' \
@@ -110,6 +111,7 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \
              -e 's|@''HAVE_SETSTATE''@|$(HAVE_SETSTATE)|g' \
              -e 's|@''HAVE_DECL_SETSTATE''@|$(HAVE_DECL_SETSTATE)|g' \
              -e 's|@''HAVE_STRTOD''@|$(HAVE_STRTOD)|g' \
+             -e 's|@''HAVE_STRTOL''@|$(HAVE_STRTOL)|g' \
              -e 's|@''HAVE_STRTOLD''@|$(HAVE_STRTOLD)|g' \
              -e 's|@''HAVE_STRTOLL''@|$(HAVE_STRTOLL)|g' \
              -e 's|@''HAVE_STRTOUL''@|$(HAVE_STRTOUL)|g' \
@@ -138,6 +140,7 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \
              -e 's|@''REPLACE_SETENV''@|$(REPLACE_SETENV)|g' \
              -e 's|@''REPLACE_SETSTATE''@|$(REPLACE_SETSTATE)|g' \
              -e 's|@''REPLACE_STRTOD''@|$(REPLACE_STRTOD)|g' \
+             -e 's|@''REPLACE_STRTOL''@|$(REPLACE_STRTOL)|g' \
              -e 's|@''REPLACE_STRTOLD''@|$(REPLACE_STRTOLD)|g' \
              -e 's|@''REPLACE_STRTOUL''@|$(REPLACE_STRTOUL)|g' \
              -e 's|@''REPLACE_STRTOULL''@|$(REPLACE_STRTOULL)|g' \
index 65b6946390c091e6880bbca76f814924f31f7920..24d4c734db71282e56d23928b55878542aef682f 100644 (file)
@@ -1,23 +1,19 @@
 Description:
 strtol() function: convert string to 'long'.
 
-Status:
-obsolete
-
-Notice:
-This module is obsolete.
-
 Files:
 lib/strtol.c
 m4/strtol.m4
 
 Depends-on:
+stdlib
 
 configure.ac:
 gl_FUNC_STRTOL
-if test $ac_cv_func_strtol = no; then
+if test $HAVE_STRTOL = 0 || test $REPLACE_STRTOL = 1; then
   AC_LIBOBJ([strtol])
 fi
+gl_STDLIB_MODULE_INDICATOR([strtol])
 
 Makefile.am:
 
index 105bc588bbe7819c40d37161711cb42c91c8c3e9..467514c6c3eb93cfd5564ad96ba794b3b600d4fb 100644 (file)
@@ -177,5 +177,67 @@ main (void)
       ASSERT (errno == 0);
     }
 
+  /* Hexadecimal integer syntax.  */
+  {
+    const char input[] = "0x2A";
+    char *ptr;
+    long result;
+    errno = 0;
+    result = strtol (input, &ptr, 10);
+    ASSERT (result == 0L);
+    ASSERT (ptr == input + 1);
+    ASSERT (errno == 0);
+  }
+  {
+    const char input[] = "0x2A";
+    char *ptr;
+    long result;
+    errno = 0;
+    result = strtol (input, &ptr, 16);
+    ASSERT (result == 42L);
+    ASSERT (ptr == input + 4);
+    ASSERT (errno == 0);
+  }
+  {
+    const char input[] = "0x2A";
+    char *ptr;
+    long result;
+    errno = 0;
+    result = strtol (input, &ptr, 0);
+    ASSERT (result == 42L);
+    ASSERT (ptr == input + 4);
+    ASSERT (errno == 0);
+  }
+  {
+    const char input[] = "0x";
+    char *ptr;
+    long result;
+    errno = 0;
+    result = strtol (input, &ptr, 10);
+    ASSERT (result == 0L);
+    ASSERT (ptr == input + 1);
+    ASSERT (errno == 0);
+  }
+  {
+    const char input[] = "0x";
+    char *ptr;
+    long result;
+    errno = 0;
+    result = strtol (input, &ptr, 16);
+    ASSERT (result == 0L);
+    ASSERT (ptr == input + 1);
+    ASSERT (errno == 0);
+  }
+  {
+    const char input[] = "0x";
+    char *ptr;
+    long result;
+    errno = 0;
+    result = strtol (input, &ptr, 0);
+    ASSERT (result == 0L);
+    ASSERT (ptr == input + 1);
+    ASSERT (errno == 0);
+  }
+
   return 0;
 }