[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);
- limits-h: provide numerical limits macros,
Bruno Haible <=