bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

limits-h: provide numerical limits macros


From: Bruno Haible
Subject: limits-h: provide numerical limits macros
Date: Thu, 06 Sep 2018 14:29:36 +0200
User-agent: KMail/5.1.3 (Linux/4.4.0-134-generic; KDE/5.18.0; x86_64; ; )

While testing the 'fcntl' module on Fedora 1 (a distribution from 2003),
I got these compilation errors:

test-intprops.c: In function `main':
test-intprops.c:137: error: `LLONG_MIN' undeclared (first use in this function)
test-intprops.c:137: error: (Each undeclared identifier is reported only once
test-intprops.c:137: error: for each function it appears in.)
test-intprops.c:137: error: `LLONG_MAX' undeclared (first use in this function)
test-intprops.c:137: error: bit-field `_gl_verify_error_if_negative' width not 
an integer constant
test-intprops.c:138: error: `ULLONG_MAX' undeclared (first use in this function)
test-intprops.c:138: error: bit-field `_gl_verify_error_if_negative' width not 
an integer constant
test-intprops.c:344: warning: integer overflow in expression
test-intprops.c:346: warning: integer overflow in expression
make[4]: *** [test-intprops.o] Error 1

The reasons are:
  * Gnulib defines LLONG_WIDTH as _GL_INTEGER_WIDTH (LLONG_MIN, LLONG_MAX),
    therefore it needs LLONG_MIN and LLONG_MAX.
  * The <limits.h> from gcc 3.3.2 defines LLONG_MIN, LLONG_MAX only
    when C99 or newer is requested.
  * The 'limits-h' module does not provide a fallback for LLONG_MIN, LLONG_MAX.

This fixes it, by expanding the scope of the 'limits-h' module.

Tested on older glibc, newer glibc, AIX 7 with xlc, HP-UX 11 with cc,
IRIX 6.5 with cc, Solaris 10 with cc, Cygwin, mingw.


2018-09-06  Bruno Haible  <address@hidden>

        limits-h: Provide numerical limits macros.
        * lib/limits.in.h (LLONG_MIN, LLONG_MAX, ULLONG_MAX): Define also for
        IRIX and for GCC.
        (WORD_BIT, LONG_BIT): Define.
        * m4/limits-h.m4 (gl_LIMITS_H): Set LIMITS_H to non-empty also when
        <limits.h> does not define LLONG_MAX or WORD_BIT.
        * tests/test-limits-h.c (TYPE_SIGNED, TYPE_WIDTH, TYPE_MINIMUM,
        TYPE_MAXIMUM): New macros, from intprops.h.
        Add tests for CHAR_BIT, WORD_BIT, LONG_BIT, <type>_MIN, and <type>_MAX.
        * doc/posix-headers/limits.texi: Document what the 'limits-h' module
        provides.

diff --git a/doc/posix-headers/limits.texi b/doc/posix-headers/limits.texi
index be1220e..2cf51ac 100644
--- a/doc/posix-headers/limits.texi
+++ b/doc/posix-headers/limits.texi
@@ -3,28 +3,32 @@
 
 POSIX specification:@* 
@url{http://www.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html}
 
-Gnulib module: gethostname
+Gnulib module: limits-h or gethostname
 
-Portability problems fixed by Gnulib:
+Portability problems fixed by Gnulib module @code{limits-h}:
 @itemize
 @item
-The @code{HOST_NAME_MAX} macro is not defined on some platforms:
-Mac OS X 10.5, FreeBSD 6.0, NetBSD 5.0, OpenBSD 3.8, AIX 5.1, HP-UX 11,
-IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin 1.5.x, mingw, MSVC 14, Interix 3.5, 
BeOS.
+The macros @code{LLONG_MIN}, @code{LLONG_MAX}, @code{ULLONG_MAX} are not
+defined on some platforms:
+older glibc systems (e.g. Fedora 1), AIX 5.1, HP-UX 11, IRIX 6.5, OpenVMS, 
OSF/1 5.1 with gcc.
address@hidden
+The macros @code{WORD_BIT}, @code{LONG_BIT} are not defined on some platforms:
+glibc 2.11 without @code{-D_GNU_SOURCE}, Cygwin, mingw, MSVC 14.
 @item
 Macros like @code{CHAR_WIDTH} are not defined on some platforms:
 glibc 2.24, many others.
 @end itemize
 
-Portability problems not fixed by Gnulib:
+Portability problems fixed by Gnulib module @code{gethostname}:
 @itemize
 @item
-The macros @code{LLONG_MIN}, @code{LLONG_MAX}, @code{ULLONG_MAX} are not
-defined on some platforms:
-AIX 5.1, HP-UX 11, IRIX 6.5, OpenVMS, OSF/1 5.1 with gcc.
address@hidden
-The macros @code{WORD_BIT}, @code{LONG_BIT} are not defined on some platforms:
-glibc 2.11 without @code{-D_GNU_SOURCE}, Cygwin, mingw, MSVC 14.
+The @code{HOST_NAME_MAX} macro is not defined on some platforms:
+Mac OS X 10.5, FreeBSD 6.0, NetBSD 5.0, OpenBSD 3.8, AIX 5.1, HP-UX 11,
+IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin 1.5.x, mingw, MSVC 14, Interix 3.5, 
BeOS.
address@hidden itemize
+
+Portability problems not fixed by Gnulib:
address@hidden
 @item
 The macro @code{SSIZE_MAX} has the wrong type,
 albeit with the correct value:
diff --git a/lib/limits.in.h b/lib/limits.in.h
index c3915dc..5b4c3ee 100644
--- a/lib/limits.in.h
+++ b/lib/limits.in.h
@@ -28,15 +28,32 @@
 #ifndef address@hidden@_LIMITS_H
 #define address@hidden@_LIMITS_H
 
-/* For HP-UX 11.31.  */
-#if defined LONG_LONG_MIN && !defined LLONG_MIN
-# define LLONG_MIN LONG_LONG_MIN
+#ifndef LLONG_MIN
+# if defined LONG_LONG_MIN /* HP-UX 11.31 */
+#  define LLONG_MIN LONG_LONG_MIN
+# elif defined LONGLONG_MIN /* IRIX 6.5 */
+#  define LLONG_MIN LONGLONG_MIN
+# elif defined __GNUC__
+#  define LLONG_MIN (- __LONG_LONG_MAX__ - 1LL)
+# endif
 #endif
-#if defined LONG_LONG_MAX && !defined LLONG_MAX
-# define LLONG_MAX LONG_LONG_MAX
+#ifndef LLONG_MAX
+# if defined LONG_LONG_MAX /* HP-UX 11.31 */
+#  define LLONG_MAX LONG_LONG_MAX
+# elif defined LONGLONG_MAX /* IRIX 6.5 */
+#  define LLONG_MAX LONGLONG_MAX
+# elif defined __GNUC__
+#  define LLONG_MAX __LONG_LONG_MAX__
+# endif
 #endif
-#if defined ULONG_LONG_MAX && !defined ULLONG_MAX
-# define ULLONG_MAX ULONG_LONG_MAX
+#ifndef ULLONG_MAX
+# if defined ULONG_LONG_MAX /* HP-UX 11.31 */
+#  define ULLONG_MAX ULONG_LONG_MAX
+# elif defined ULONGLONG_MAX /* IRIX 6.5 */
+#  define ULLONG_MAX ULONGLONG_MAX
+# elif defined __GNUC__
+#  define ULLONG_MAX (__LONG_LONG_MAX__ * 2ULL + 1ULL)
+# endif
 #endif
 
 /* The number of usable bits in an unsigned or signed integer type
@@ -53,6 +70,19 @@
 #define _GL_COB8(n) (_GL_COB4 ((n) >> 4) + _GL_COB4 (n))
 #define _GL_COB4(n) (!!((n) & 8) + !!((n) & 4) + !!((n) & 2) + !!((n) & 1))
 
+#ifndef WORD_BIT
+/* Assume 'int' is 32 bits wide.  */
+# define WORD_BIT 32
+#endif
+#ifndef LONG_BIT
+/* Assume 'long' is 32 or 64 bits wide.  */
+# if LONG_MAX == INT_MAX
+#  define LONG_BIT 32
+# else
+#  define LONG_BIT 64
+# endif
+#endif
+
 /* Macros specified by ISO/IEC TS 18661-1:2014.  */
 
 #if (! defined ULLONG_WIDTH                                             \
diff --git a/m4/limits-h.m4 b/m4/limits-h.m4
index 8388663..3a2cd91 100644
--- a/m4/limits-h.m4
+++ b/m4/limits-h.m4
@@ -11,14 +11,18 @@ AC_DEFUN_ONCE([gl_LIMITS_H],
 [
   gl_CHECK_NEXT_HEADERS([limits.h])
 
-  AC_CACHE_CHECK([whether limits.h has ULLONG_WIDTH etc.],
+  AC_CACHE_CHECK([whether limits.h has LLONG_MAX, WORD_BIT, ULLONG_WIDTH etc.],
     [gl_cv_header_limits_width],
     [AC_COMPILE_IFELSE(
-       [AC_LANG_PROGRAM([[#ifndef __STDC_WANT_IEC_60559_BFP_EXT__
-                           #define __STDC_WANT_IEC_60559_BFP_EXT__ 1
-                          #endif
-                          #include <limits.h>
-                          int ullw = ULLONG_WIDTH;]])],
+       [AC_LANG_PROGRAM(
+          [[#ifndef __STDC_WANT_IEC_60559_BFP_EXT__
+             #define __STDC_WANT_IEC_60559_BFP_EXT__ 1
+            #endif
+            #include <limits.h>
+            long long llm = LLONG_MAX;
+            int wb = WORD_BIT;
+            int ullw = ULLONG_WIDTH;
+          ]])],
        [gl_cv_header_limits_width=yes],
        [gl_cv_header_limits_width=no])])
   if test "$gl_cv_header_limits_width" = yes; then
diff --git a/tests/test-limits-h.c b/tests/test-limits-h.c
index 29b5127..ee30bde 100644
--- a/tests/test-limits-h.c
+++ b/tests/test-limits-h.c
@@ -26,11 +26,78 @@
 # pragma GCC diagnostic ignored "-Woverlength-strings"
 #endif
 
-/* Macros specified by ISO/IEC TS 18661-1:2014.  */
-
 #define verify_width(width, min, max) \
   verify ((max) >> ((width) - 1 - ((min) < 0)) == 1)
 
+/* Macros borrowed from intprops.h.  */
+#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
+#define TYPE_WIDTH(t) (sizeof (t) * CHAR_BIT)
+#define TYPE_MINIMUM(t) ((t) ~ TYPE_MAXIMUM (t))
+#define TYPE_MAXIMUM(t)                                                 \
+  ((t) (! TYPE_SIGNED (t)                                               \
+        ? (t) -1                                                        \
+        : ((((t) 1 << (TYPE_WIDTH (t) - 2)) - 1) * 2 + 1)))
+
+/* Type width macros.  */
+
+int type_bits[] =
+  {
+    CHAR_BIT,
+    WORD_BIT,
+    LONG_BIT
+  };
+verify_width (CHAR_BIT, CHAR_MIN, CHAR_MAX);
+verify_width (WORD_BIT, INT_MIN, INT_MAX);
+verify_width (LONG_BIT, LONG_MIN, LONG_MAX);
+
+/* Numerical limit macros.  */
+
+char               limits1[]  = { CHAR_MIN, CHAR_MAX };
+verify (TYPE_MINIMUM (char) == CHAR_MIN);
+verify (TYPE_MAXIMUM (char) == CHAR_MAX);
+
+signed char        limits2[]  = { SCHAR_MIN, SCHAR_MAX };
+verify (TYPE_MINIMUM (signed char) == SCHAR_MIN);
+verify (TYPE_MAXIMUM (signed char) == SCHAR_MAX);
+
+unsigned char      limits3[]  = { UCHAR_MAX };
+verify (TYPE_MINIMUM (unsigned char) == 0);
+verify (TYPE_MAXIMUM (unsigned char) == UCHAR_MAX);
+
+short              limits4[]  = { SHRT_MIN, SHRT_MAX };
+verify (TYPE_MINIMUM (short int) == SHRT_MIN);
+verify (TYPE_MAXIMUM (short int) == SHRT_MAX);
+
+unsigned short     limits5[]  = { USHRT_MAX };
+verify (TYPE_MINIMUM (unsigned short int) == 0);
+verify (TYPE_MAXIMUM (unsigned short int) == USHRT_MAX);
+
+int                limits6[]  = { INT_MIN, INT_MAX };
+verify (TYPE_MINIMUM (int) == INT_MIN);
+verify (TYPE_MAXIMUM (int) == INT_MAX);
+
+unsigned int       limits7[]  = { UINT_MAX };
+verify (TYPE_MINIMUM (unsigned int) == 0);
+verify (TYPE_MAXIMUM (unsigned int) == UINT_MAX);
+
+long               limits8[]  = { LONG_MIN, LONG_MAX };
+verify (TYPE_MINIMUM (long int) == LONG_MIN);
+verify (TYPE_MAXIMUM (long int) == LONG_MAX);
+
+unsigned long      limits9[]  = { ULONG_MAX };
+verify (TYPE_MINIMUM (unsigned long int) == 0);
+verify (TYPE_MAXIMUM (unsigned long int) == ULONG_MAX);
+
+long long          limits10[] = { LLONG_MIN, LLONG_MAX };
+verify (TYPE_MINIMUM (long long int) == LLONG_MIN);
+verify (TYPE_MAXIMUM (long long int) == LLONG_MAX);
+
+unsigned long long limits11[] = { ULLONG_MAX };
+verify (TYPE_MINIMUM (unsigned long long int) == 0);
+verify (TYPE_MAXIMUM (unsigned long long int) == ULLONG_MAX);
+
+/* Macros specified by ISO/IEC TS 18661-1:2014.  */
+
 verify_width (CHAR_WIDTH, CHAR_MIN, CHAR_MAX);
 verify_width (SCHAR_WIDTH, SCHAR_MIN, SCHAR_MAX);
 verify_width (UCHAR_WIDTH, 0, UCHAR_MAX);




reply via email to

[Prev in Thread] Current Thread [Next in Thread]