Don't insist on 'long long int' support in the preprocessor. It
authorPaul Eggert <eggert@cs.ucla.edu>
Mon, 12 Nov 2007 23:50:17 +0000 (15:50 -0800)
committerPaul Eggert <eggert@cs.ucla.edu>
Mon, 12 Nov 2007 23:50:17 +0000 (15:50 -0800)
breaks too many things.  For example, PRIdMAX still uses a 'long
long int' format with the latest Sun compiler, even though
HAVE_LONG_LONG_INT isn't defined due to that compiler's
preprocessor problem.  This causes the latest coreutils to dump
core on Solaris 10 sparc with the Sun C compiler.
Instead, fix the 2007-10-16 problem in a different way, by evaluating
the troublesome expressions at configure-time, not at #if-time.
* m4/longlong.m4 (_AC_TYPE_LONG_LONG_SNIPPET): Don't test the
preprocessor.
* m4/inttypes.m4 (gl_INTTYPES_H): Move the #if checks into
compile-time C checks, done at 'configure'-time.
(gl_INTTYPES_CHECK_LONG_LONG_INT_CONDITION): New macro.
* modules/inttypes (Makefile): Substitute the new symbols that
gl_INTTYPES_H now generates.
* lib/inttypes.in.h: Don't use constants wider than 'long' in #if.

ChangeLog
lib/inttypes.in.h
m4/inttypes.m4
m4/longlong.m4
modules/inttypes

index bc64582..6f151bf 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2007-11-12  Paul Eggert  <eggert@cs.ucla.edu>
+
+       Don't insist on 'long long int' support in the preprocessor.  It
+       breaks too many things.  For example, PRIdMAX still uses a 'long
+       long int' format with the latest Sun compiler, even though
+       HAVE_LONG_LONG_INT isn't defined due to that compiler's
+       preprocessor problem.  This causes the latest coreutils to dump
+       core on Solaris 10 sparc with the Sun C compiler.
+       Instead, fix the 2007-10-16 problem in a different way, by evaluating
+       the troublesome expressions at configure-time, not at #if-time.
+       * m4/longlong.m4 (_AC_TYPE_LONG_LONG_SNIPPET): Don't test the
+       preprocessor.
+       * m4/inttypes.m4 (gl_INTTYPES_H): Move the #if checks into
+       compile-time C checks, done at 'configure'-time.
+       (gl_INTTYPES_CHECK_LONG_LONG_INT_CONDITION): New macro.
+       * modules/inttypes (Makefile): Substitute the new symbols that
+       gl_INTTYPES_H now generates.
+       * lib/inttypes.in.h: Don't use constants wider than 'long' in #if.
+
 2007-11-12  Bruno Haible  <bruno@clisp.org>
 
        Tests for Unicode character classification functions.
index f9f3119..8a24850 100644 (file)
 #  endif
 # endif
 # ifdef INT64_MAX
-#  if INT64_MAX == LONG_MAX
+#  if @INT64_MAX_EQ_LONG_MAX@
 #   define _PRI64_PREFIX "l"
 #  elif defined _MSC_VER || defined __MINGW32__
 #   define _PRI64_PREFIX "I64"
 #  endif
 # endif
 # ifdef UINT64_MAX
-#  if UINT64_MAX == ULONG_MAX
+#  if @UINT64_MAX_EQ_ULONG_MAX@
 #   define _PRIu64_PREFIX "l"
 #  elif defined _MSC_VER || defined __MINGW32__
 #   define _PRIu64_PREFIX "I64"
 
 # if !defined PRIdMAX || @PRI_MACROS_BROKEN@
 #  undef PRIdMAX
-#  if INTMAX_MAX > INT32_MAX
+#  if @INT32_MAX_LT_INTMAX_MAX@
 #   define PRIdMAX PRId64
 #  else
 #   define PRIdMAX "ld"
 # endif
 # if !defined PRIiMAX || @PRI_MACROS_BROKEN@
 #  undef PRIiMAX
-#  if INTMAX_MAX > INT32_MAX
+#  if @INT32_MAX_LT_INTMAX_MAX@
 #   define PRIiMAX PRIi64
 #  else
 #   define PRIiMAX "li"
 # endif
 # if !defined PRIoMAX || @PRI_MACROS_BROKEN@
 #  undef PRIoMAX
-#  if UINTMAX_MAX > UINT32_MAX
+#  if @UINT32_MAX_LT_UINTMAX_MAX@
 #   define PRIoMAX PRIo64
 #  else
 #   define PRIoMAX "lo"
 # endif
 # if !defined PRIuMAX || @PRI_MACROS_BROKEN@
 #  undef PRIuMAX
-#  if UINTMAX_MAX > UINT32_MAX
+#  if @UINT32_MAX_LT_UINTMAX_MAX@
 #   define PRIuMAX PRIu64
 #  else
 #   define PRIuMAX "lu"
 # endif
 # if !defined PRIxMAX || @PRI_MACROS_BROKEN@
 #  undef PRIxMAX
-#  if UINTMAX_MAX > UINT32_MAX
+#  if @UINT32_MAX_LT_UINTMAX_MAX@
 #   define PRIxMAX PRIx64
 #  else
 #   define PRIxMAX "lx"
 # endif
 # if !defined PRIXMAX || @PRI_MACROS_BROKEN@
 #  undef PRIXMAX
-#  if UINTMAX_MAX > UINT32_MAX
+#  if @UINT32_MAX_LT_UINTMAX_MAX@
 #   define PRIXMAX PRIX64
 #  else
 #   define PRIXMAX "lX"
 #  endif
 # endif
 # ifdef INT64_MAX
-#  if INT64_MAX == LONG_MAX
+#  if @INT64_MAX_EQ_LONG_MAX@
 #   define _SCN64_PREFIX "l"
 #  elif defined _MSC_VER || defined __MINGW32__
 #   define _SCN64_PREFIX "I64"
 #  endif
 # endif
 # ifdef UINT64_MAX
-#  if UINT64_MAX == ULONG_MAX
+#  if @UINT64_MAX_EQ_ULONG_MAX@
 #   define _SCNu64_PREFIX "l"
 #  elif defined _MSC_VER || defined __MINGW32__
 #   define _SCNu64_PREFIX "I64"
 
 # if !defined SCNdMAX || @PRI_MACROS_BROKEN@
 #  undef SCNdMAX
-#  if INTMAX_MAX > INT32_MAX
+#  if @INT32_MAX_LT_INTMAX_MAX@
 #   define SCNdMAX SCNd64
 #  else
 #   define SCNdMAX "ld"
 # endif
 # if !defined SCNiMAX || @PRI_MACROS_BROKEN@
 #  undef SCNiMAX
-#  if INTMAX_MAX > INT32_MAX
+#  if @INT32_MAX_LT_INTMAX_MAX@
 #   define SCNiMAX SCNi64
 #  else
 #   define SCNiMAX "li"
 # endif
 # if !defined SCNoMAX || @PRI_MACROS_BROKEN@
 #  undef SCNoMAX
-#  if UINTMAX_MAX > UINT32_MAX
+#  if @UINT32_MAX_LT_UINTMAX_MAX@
 #   define SCNoMAX SCNo64
 #  else
 #   define SCNoMAX "lo"
 # endif
 # if !defined SCNuMAX || @PRI_MACROS_BROKEN@
 #  undef SCNuMAX
-#  if UINTMAX_MAX > UINT32_MAX
+#  if @UINT32_MAX_LT_UINTMAX_MAX@
 #   define SCNuMAX SCNu64
 #  else
 #   define SCNuMAX "lu"
 # endif
 # if !defined SCNxMAX || @PRI_MACROS_BROKEN@
 #  undef SCNxMAX
-#  if UINTMAX_MAX > UINT32_MAX
+#  if @UINT32_MAX_LT_UINTMAX_MAX@
 #   define SCNxMAX SCNx64
 #  else
 #   define SCNxMAX "lx"
index 8f949d0..b17cbda 100644 (file)
@@ -207,11 +207,73 @@ const char *l = /* implicit string concatenation */
       HAVE_DECL_STRTOUMAX=0
     fi
 
+    gl_INTTYPES_CHECK_LONG_LONG_INT_CONDITION(
+      [INT32_MAX_LT_INTMAX_MAX],
+      [defined INT32_MAX && defined INTMAX_MAX],
+      [INT32_MAX < INTMAX_MAX],
+      [sizeof (int) < sizeof (long long int)])
+    gl_INTTYPES_CHECK_LONG_LONG_INT_CONDITION(
+      [INT64_MAX_EQ_LONG_MAX],
+      [defined INT64_MAX],
+      [INT64_MAX == LONG_MAX],
+      [sizeof (long long int) == sizeof (long int)])
+    gl_INTTYPES_CHECK_LONG_LONG_INT_CONDITION(
+      [UINT32_MAX_LT_UINTMAX_MAX],
+      [defined UINT32_MAX && defined UINTMAX_MAX],
+      [UINT32_MAX < UINTMAX_MAX],
+      [sizeof (unsigned int) < sizeof (unsigned long long int)])
+    gl_INTTYPES_CHECK_LONG_LONG_INT_CONDITION(
+      [UINT64_MAX_EQ_ULONG_MAX],
+      [defined UINT64_MAX],
+      [UINT64_MAX == ULONG_MAX],
+      [sizeof (unsigned long long int) == sizeof (unsigned long int)])
+
     INTTYPES_H='inttypes.h'
   fi
   AC_SUBST(INTTYPES_H)
 ])
 
+# Define the symbol $1 to be 1 if the condition is true, 0 otherwise.
+# If $2 is true, the condition is $3; otherwise if long long int is supported
+# approximate the condition with $4; otherwise, assume the condition is false.
+# The condition should work on all C99 platforms; the approximations should be
+# good enough to work on all practical pre-C99 platforms.
+# $2 is evaluated by the C preprocessor, $3 and $4 as compile-time constants.
+AC_DEFUN([gl_INTTYPES_CHECK_LONG_LONG_INT_CONDITION],
+[
+  AC_CACHE_CHECK([whether $3],
+    [gl_cv_test_$1],
+    [AC_COMPILE_IFELSE(
+       [AC_LANG_PROGRAM(
+         [[/* Work also in C++ mode.  */
+           #define __STDC_LIMIT_MACROS 1
+
+           /* Work if build is not clean.  */
+           #define _GL_JUST_INCLUDE_SYSTEM_STDINT_H
+
+           #include <limits.h>
+           #if HAVE_STDINT_H
+            #include <stdint.h>
+           #endif
+
+           #if $2
+            #define CONDITION ($3)
+           #elif HAVE_LONG_LONG_INT
+            #define CONDITION ($4)
+           #else
+            #define CONDITION 0
+           #endif
+           int test[CONDITION ? 1 : -1];]])],
+       [gl_cv_test_$1=yes],
+       [gl_cv_test_$1=no])])
+  if test $gl_cv_test_$1 = yes; then
+    $1=1;
+  else
+    $1=0;
+  fi
+  AC_SUBST([$1])
+])
+
 AC_DEFUN([gl_INTTYPES_MODULE_INDICATOR],
 [
   dnl Use AC_REQUIRE here, so that the default settings are expanded once only.
index a72e53b..15bf9da 100644 (file)
@@ -82,13 +82,10 @@ AC_DEFUN([AC_TYPE_UNSIGNED_LONG_LONG_INT],
 AC_DEFUN([_AC_TYPE_LONG_LONG_SNIPPET],
 [
   AC_LANG_PROGRAM(
-    [[/* Test preprocessor.  */
-      #if ! (-9223372036854775807LL < 0 && 0 < 9223372036854775807ll)
-        error in preprocessor;
-      #endif
-      #if ! (18446744073709551615ULL <= -1ull)
-        error in preprocessor;
-      #endif
+    [[/* For now, do not test the preprocessor; as of 2007 there are too many
+        implementations with broken preprocessors.  Perhaps this can
+        be revisited in 2012.  In the meantime, code should not expect
+        #if to work with literals wider than 32 bits.  */
       /* Test literals.  */
       long long int ll = 9223372036854775807ll;
       long long int nll = -9223372036854775807LL;
index 2199e4b..91907d9 100644 (file)
@@ -37,6 +37,10 @@ inttypes.h: inttypes.in.h
              -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/@''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' \
+             -e 's/@''UINT64_MAX_EQ_ULONG_MAX''@/$(UINT64_MAX_EQ_ULONG_MAX)/g' \
              -e '/definition of GL_LINK_WARNING/r $(LINK_WARNING_H)' \
              < $(srcdir)/inttypes.in.h; \
        } > $@-t