changeset 16230:f9e137049132

strtoimax: Work around AIX 5.1 bug. * lib/inttypes.in.h (strtoimax): Allow overriding the system's definition. * m4/strtoimax.m4 (gl_FUNC_STRTOIMAX): Check against the AIX 5.1 bug. Set HAVE_STRTOIMAX. * m4/inttypes.m4 (gl_INTTYPES_H_DEFAULTS): Initialize REPLACE_STRTOIMAX. * modules/inttypes-incomplete (Makefile.am): Substitute REPLACE_STRTOIMAX. * modules/strtoimax (Files): Add m4/stdint_h.m4, m4/inttypes_h.m4. (configure.ac): Test HAVE_STRTOIMAX, REPLACE_STRTOIMAX. (Depends-on): Update conditions. * tests/test-strtoimax.c (main): Add tests for large values. * doc/posix-functions/strtoimax.texi: Mention the AIX 5.1 bug.
author Bruno Haible <bruno@clisp.org>
date Thu, 05 Jan 2012 18:47:38 +0100
parents daac1ca4c436
children e8cde289d525
files ChangeLog doc/posix-functions/strtoimax.texi lib/inttypes.in.h m4/inttypes.m4 m4/strtoimax.m4 modules/inttypes-incomplete modules/strtoimax tests/test-strtoimax.c
diffstat 8 files changed, 129 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2012-01-05  Bruno Haible  <bruno@clisp.org>
+
+	strtoimax: Work around AIX 5.1 bug.
+	* lib/inttypes.in.h (strtoimax): Allow overriding the system's
+	definition.
+	* m4/strtoimax.m4 (gl_FUNC_STRTOIMAX): Check against the AIX 5.1 bug.
+	Set HAVE_STRTOIMAX.
+	* m4/inttypes.m4 (gl_INTTYPES_H_DEFAULTS): Initialize
+	REPLACE_STRTOIMAX.
+	* modules/inttypes-incomplete (Makefile.am): Substitute
+	REPLACE_STRTOIMAX.
+	* modules/strtoimax (Files): Add m4/stdint_h.m4, m4/inttypes_h.m4.
+	(configure.ac): Test HAVE_STRTOIMAX, REPLACE_STRTOIMAX.
+	(Depends-on): Update conditions.
+	* tests/test-strtoimax.c (main): Add tests for large values.
+	* doc/posix-functions/strtoimax.texi: Mention the AIX 5.1 bug.
+
 2012-01-05  Bruno Haible  <bruno@clisp.org>
 
 	inttypes: Modernize.
--- a/doc/posix-functions/strtoimax.texi
+++ b/doc/posix-functions/strtoimax.texi
@@ -11,6 +11,9 @@
 @item
 This function is missing on some platforms:
 OpenBSD 3.8, Minix 3.1.8, AIX 4.3.2, IRIX 6.5, OSF/1 5.1, Solaris 9, MSVC 9, Interix 3.5.
+@item
+This function fails on valid input strings on some platforms:
+AIX 5.1.
 @end itemize
 
 Portability problems not fixed by Gnulib:
--- a/lib/inttypes.in.h
+++ b/lib/inttypes.in.h
@@ -1079,12 +1079,22 @@
 #endif
 
 #if @GNULIB_STRTOIMAX@
-# if !@HAVE_DECL_STRTOIMAX@
-#  undef strtoimax
+# if @REPLACE_STRTOIMAX@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef strtoimax
+#   define strtoimax rpl_strtoimax
+#  endif
+_GL_FUNCDECL_RPL (strtoimax, intmax_t,
+                  (const char *, char **, int) _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (strtoimax, intmax_t, (const char *, char **, int));
+# else
+#  if !@HAVE_DECL_STRTOIMAX@
+#   undef strtoimax
 _GL_FUNCDECL_SYS (strtoimax, intmax_t,
                   (const char *, char **, int) _GL_ARG_NONNULL ((1)));
+#  endif
+_GL_CXXALIAS_SYS (strtoimax, intmax_t, (const char *, char **, int));
 # endif
-_GL_CXXALIAS_SYS (strtoimax, intmax_t, (const char *, char **, int));
 _GL_CXXALIASWARN (strtoimax);
 #elif defined GNULIB_POSIXCHECK
 # undef strtoimax
--- a/m4/inttypes.m4
+++ b/m4/inttypes.m4
@@ -1,4 +1,4 @@
-# inttypes.m4 serial 25
+# inttypes.m4 serial 26
 dnl Copyright (C) 2006-2012 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -147,6 +147,7 @@
   HAVE_DECL_IMAXDIV=1;   AC_SUBST([HAVE_DECL_IMAXDIV])
   HAVE_DECL_STRTOIMAX=1; AC_SUBST([HAVE_DECL_STRTOIMAX])
   HAVE_DECL_STRTOUMAX=1; AC_SUBST([HAVE_DECL_STRTOUMAX])
+  REPLACE_STRTOIMAX=0;   AC_SUBST([REPLACE_STRTOIMAX])
   INT32_MAX_LT_INTMAX_MAX=1;  AC_SUBST([INT32_MAX_LT_INTMAX_MAX])
   INT64_MAX_EQ_LONG_MAX='defined _LP64';  AC_SUBST([INT64_MAX_EQ_LONG_MAX])
   PRI_MACROS_BROKEN=0;   AC_SUBST([PRI_MACROS_BROKEN])
--- a/m4/strtoimax.m4
+++ b/m4/strtoimax.m4
@@ -1,4 +1,4 @@
-# strtoimax.m4 serial 11
+# strtoimax.m4 serial 12
 dnl Copyright (C) 2002-2004, 2006, 2009-2012 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -14,6 +14,58 @@
   if test "$ac_cv_have_decl_strtoimax" != yes; then
     HAVE_DECL_STRTOIMAX=0
   fi
+
+  if test $ac_cv_func_strtoimax = yes; then
+    HAVE_STRTOIMAX=1
+    dnl On AIX 5.1, strtoimax() fails for values outside the 'int' range.
+    AC_REQUIRE([gl_AC_HEADER_STDINT_H])
+    AC_REQUIRE([gl_AC_HEADER_INTTYPES_H])
+    AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+    AC_CACHE_CHECK([whether strtoimax works], [gl_cv_func_strtoimax],
+      [AC_RUN_IFELSE(
+         [AC_LANG_SOURCE([[
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#if HAVE_STDINT_H_WITH_UINTMAX
+# include <stdint.h>
+#endif
+#if HAVE_INTTYPES_H_WITH_UINTMAX
+# include <inttypes.h>
+#endif
+int main ()
+{
+  const char *s = "4294967295";
+  char *p;
+  intmax_t res;
+  errno = 0;
+  res = strtoimax (s, &p, 10);
+  if (p != s + strlen (s))
+    return 1;
+  if (errno != 0)
+    return 2;
+  if (res != (intmax_t) 65535 * (intmax_t) 65537)
+    return 3;
+  return 0;
+}
+]])],
+         [gl_cv_func_strtoimax=yes],
+         [gl_cv_func_strtoimax=no],
+         [case "$host_os" in
+                   # Guess no on AIX 5.
+            aix5*) gl_cv_func_strtoimax="guessing no" ;;
+                   # Guess yes otherwise.
+            *)     gl_cv_func_strtoimax="guessing yes" ;;
+          esac
+         ])
+      ])
+    case "$gl_cv_func_strtoimax" in
+      *no) REPLACE_STRTOIMAX=1 ;;
+    esac
+  else
+    HAVE_STRTOIMAX=0
+  fi
 ])
 
 # Prerequisites of lib/strtoimax.c.
--- a/modules/inttypes-incomplete
+++ b/modules/inttypes-incomplete
@@ -42,6 +42,7 @@
 	      -e 's/@''HAVE_DECL_IMAXDIV''@/$(HAVE_DECL_IMAXDIV)/g' \
 	      -e 's/@''HAVE_DECL_STRTOIMAX''@/$(HAVE_DECL_STRTOIMAX)/g' \
 	      -e 's/@''HAVE_DECL_STRTOUMAX''@/$(HAVE_DECL_STRTOUMAX)/g' \
+	      -e 's/@''REPLACE_STRTOIMAX''@/$(REPLACE_STRTOIMAX)/g' \
 	      -e 's/@''INT32_MAX_LT_INTMAX_MAX''@/$(INT32_MAX_LT_INTMAX_MAX)/g' \
 	      -e 's/@''INT64_MAX_EQ_LONG_MAX''@/$(INT64_MAX_EQ_LONG_MAX)/g' \
 	      -e 's/@''UINT32_MAX_LT_UINTMAX_MAX''@/$(UINT32_MAX_LT_UINTMAX_MAX)/g' \
--- a/modules/strtoimax
+++ b/modules/strtoimax
@@ -3,18 +3,20 @@
 
 Files:
 lib/strtoimax.c
+m4/strtoimax.m4
+m4/stdint_h.m4
+m4/inttypes_h.m4
 m4/longlong.m4
-m4/strtoimax.m4
 
 Depends-on:
 inttypes-incomplete
-verify          [test $ac_cv_func_strtoimax = no]
-stdint          [test $ac_cv_func_strtoimax = no]
-strtoll         [test $ac_cv_func_strtoimax = no && test $ac_cv_type_long_long_int = yes]
+verify          [test $HAVE_STRTOIMAX = 0 || test $REPLACE_STRTOIMAX = 1]
+stdint          [test $HAVE_STRTOIMAX = 0 || test $REPLACE_STRTOIMAX = 1]
+strtoll         [{ test $HAVE_STRTOIMAX = 0 || test $REPLACE_STRTOIMAX = 1; } && test $ac_cv_type_long_long_int = yes]
 
 configure.ac:
 gl_FUNC_STRTOIMAX
-if test $ac_cv_func_strtoimax = no; then
+if test $HAVE_STRTOIMAX = 0 || test $REPLACE_STRTOIMAX = 1; then
   AC_LIBOBJ([strtoimax])
   gl_PREREQ_STRTOIMAX
 fi
--- a/tests/test-strtoimax.c
+++ b/tests/test-strtoimax.c
@@ -144,5 +144,38 @@
     ASSERT (errno == 0);
   }
 
+  /* Large integer values.  */
+  {
+    const char input[] = "2147483647";
+    char *ptr;
+    intmax_t result;
+    errno = 0;
+    result = strtoimax (input, &ptr, 10);
+    ASSERT (result == 2147483647);
+    ASSERT (ptr == input + 10);
+    ASSERT (errno == 0);
+  }
+  {
+    const char input[] = "-2147483648";
+    char *ptr;
+    intmax_t result;
+    errno = 0;
+    result = strtoimax (input, &ptr, 10);
+    ASSERT (result == -2147483647 - 1);
+    ASSERT (ptr == input + 11);
+    ASSERT (errno == 0);
+  }
+  if (sizeof (intmax_t) > sizeof (int))
+    {
+      const char input[] = "4294967295";
+      char *ptr;
+      intmax_t result;
+      errno = 0;
+      result = strtoimax (input, &ptr, 10);
+      ASSERT (result == (intmax_t) 65535 * (intmax_t) 65537);
+      ASSERT (ptr == input + 10);
+      ASSERT (errno == 0);
+    }
+
   return 0;
 }