strtoimax: Work around AIX 5.1 bug.
authorBruno Haible <bruno@clisp.org>
Thu, 5 Jan 2012 17:47:38 +0000 (18:47 +0100)
committerBruno Haible <bruno@clisp.org>
Thu, 5 Jan 2012 17:47:38 +0000 (18:47 +0100)
* 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.

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

index 980059a..a4e01bf 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,22 @@
 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.
        * lib/inttypes.in.h (strtoimax, strtoumax): Use the C++ safe idioms.
        * modules/inttypes-incomplete (Depends-on): Add snippet/c++defs.
index 0077971..7a15c68 100644 (file)
@@ -11,6 +11,9 @@ Portability problems fixed by Gnulib:
 @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:
index e10f697..b9da2b5 100644 (file)
@@ -1079,12 +1079,22 @@ _GL_WARN_ON_USE (imaxdiv, "imaxdiv is unportable - "
 #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
+#  endif
 _GL_CXXALIAS_SYS (strtoimax, intmax_t, (const char *, char **, int));
+# endif
 _GL_CXXALIASWARN (strtoimax);
 #elif defined GNULIB_POSIXCHECK
 # undef strtoimax
index 989c261..eec4f41 100644 (file)
@@ -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 @@ AC_DEFUN([gl_INTTYPES_H_DEFAULTS],
   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])
index 633cd9e..b4e2d40 100644 (file)
@@ -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 @@ AC_DEFUN([gl_FUNC_STRTOIMAX],
   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.
index 14beccb..5943dae 100644 (file)
@@ -42,6 +42,7 @@ inttypes.h: inttypes.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_U
              -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' \
index 0e20a84..f3f5612 100644 (file)
@@ -3,18 +3,20 @@ strtoimax() function: convert string to 'intmax_t'.
 
 Files:
 lib/strtoimax.c
-m4/longlong.m4
 m4/strtoimax.m4
+m4/stdint_h.m4
+m4/inttypes_h.m4
+m4/longlong.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
index b250190..d3b84cf 100644 (file)
@@ -144,5 +144,38 @@ main (void)
     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;
 }