Also, improve errno tests.
* m4/calloc.m4 (gl_FUNC_CALLOC_GNU):
* m4/malloc.m4 (gl_FUNC_MALLOC_GNU):
* m4/realloc.m4 (gl_FUNC_REALLOC_GNU):
* m4/scandir.m4 (gl_FUNC_SCANDIR):
Define _LINUX_SOURCE_COMPAT, as this can sometimes help on AIX.
* m4/errno_h.m4 (gl_HEADER_ERRNO_H):
Define _LINUX_SOURCE_COMPAT, to make EEXIST != ENOTEMPTY.
* m4/strerror_r.m4 (gl_FUNC_STRERROR_R):
Define _LINUX_SOURCE_COMPAT, in case someone else does.
* modules/errno-tests (Depends-on): Add assert-h, c99.
* tests/test-errno.c (e1, ..., e131): Remove, replacing with ...
(CHECK_POSIX_ERRNOS, POSITIVE_INTEGER_CONSTANT_EXPRESSION)
(INDEXED_BY_ERRNO, ERRNO_COUNT): These new macros.
Check that all errno values are positive integer constant expressions.
Check that they are all distinct, except perhaps for
EWOULDBLOCK == EAGAIN and ENOTSUP == EOPNOTSUPP.
Also check ESOCKTNOSUPPORT, added in POSIX.1-2024.
Also, check that errno values are distinct except when POSIX says
they needn’t be distinct, since POSIX.1-2024 gives license to
GNU/Linux’s non-distinct values.
---
 ChangeLog                           |  25 ++++
 doc/posix-functions/calloc.texi     |   2 +-
 doc/posix-functions/malloc.texi     |   2 +-
 doc/posix-functions/realloc.texi    |   2 +-
 doc/posix-functions/strerror_r.texi |   3 +-
 doc/posix-headers/errno.texi        |   4 +
 lib/errno.in.h                      |   2 +-
 m4/calloc.m4                        |   7 +-
 m4/errno_h.m4                       |   7 +-
 m4/malloc.m4                        |   7 +-
 m4/passfd.m4                        |   4 +-
 m4/realloc.m4                       |   7 +-
 m4/scandir.m4                       |   5 +-
 m4/strerror_r.m4                    |   9 +-
 modules/errno-tests                 |   3 +-
 tests/test-errno.c                  | 187 +++++++++++++++-------------
 16 files changed, 174 insertions(+), 102 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index bdedb82c3a..78e4bd2f09 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+2024-07-31  Paul Eggert  <egg...@cs.ucla.edu>
+
+       errno: make EEXIST != ENOTEMPTY on AIX
+       Also, improve errno tests.
+       * m4/calloc.m4 (gl_FUNC_CALLOC_GNU):
+       * m4/malloc.m4 (gl_FUNC_MALLOC_GNU):
+       * m4/realloc.m4 (gl_FUNC_REALLOC_GNU):
+       * m4/scandir.m4 (gl_FUNC_SCANDIR):
+       Define _LINUX_SOURCE_COMPAT, as this can sometimes help on AIX.
+       * m4/errno_h.m4 (gl_HEADER_ERRNO_H):
+       Define _LINUX_SOURCE_COMPAT, to make EEXIST != ENOTEMPTY.
+       * m4/strerror_r.m4 (gl_FUNC_STRERROR_R):
+       Define _LINUX_SOURCE_COMPAT, in case someone else does.
+       * modules/errno-tests (Depends-on): Add assert-h, c99.
+       * tests/test-errno.c (e1, ..., e131): Remove, replacing with ...
+       (CHECK_POSIX_ERRNOS, POSITIVE_INTEGER_CONSTANT_EXPRESSION)
+       (INDEXED_BY_ERRNO, ERRNO_COUNT): These new macros.
+       Check that all errno values are positive integer constant expressions.
+       Check that they are all distinct, except perhaps for
+       EWOULDBLOCK == EAGAIN and ENOTSUP == EOPNOTSUPP.
+       Also check ESOCKTNOSUPPORT, added in POSIX.1-2024.
+       Also, check that errno values are distinct except when POSIX says
+       they needn’t be distinct, since POSIX.1-2024 gives license to
+       GNU/Linux’s non-distinct values.
+
 2024-07-31  Bruno Haible  <br...@clisp.org>
 
        float: Update to mostly guarantee ISO C 23 compliance.
diff --git a/doc/posix-functions/calloc.texi b/doc/posix-functions/calloc.texi
index 20fb026a2f..9e3b5a4929 100644
--- a/doc/posix-functions/calloc.texi
+++ b/doc/posix-functions/calloc.texi
@@ -30,5 +30,5 @@ It fixes this portability problem:
 @item
 @code{calloc (0, s)} and @code{calloc (n, 0)} return @code{NULL} on success
 on some platforms:
-AIX 7.2.
+AIX 7.3.
 @end itemize
diff --git a/doc/posix-functions/malloc.texi b/doc/posix-functions/malloc.texi
index 2137ba2b81..9ec84fce5d 100644
--- a/doc/posix-functions/malloc.texi
+++ b/doc/posix-functions/malloc.texi
@@ -27,5 +27,5 @@ by fixing this portability problem:
 @itemize
 @item
 @code{malloc (0)} returns @code{NULL} on success on some platforms:
-AIX 7.2.
+AIX 7.3.
 @end itemize
diff --git a/doc/posix-functions/realloc.texi b/doc/posix-functions/realloc.texi
index 6bb61dd7e4..bd130195c2 100644
--- a/doc/posix-functions/realloc.texi
+++ b/doc/posix-functions/realloc.texi
@@ -40,7 +40,7 @@ It fixes these portability problems:
 @itemize
 @item
 @code{realloc (NULL, 0)} returns @code{NULL} on success on some platforms:
-AIX 7.2.
+AIX 7.3.
 
 @item
 On some platforms, @code{realloc (p, 0)} with non-null @code{p}
diff --git a/doc/posix-functions/strerror_r.texi 
b/doc/posix-functions/strerror_r.texi
index cff950f963..52f56fcfc5 100644
--- a/doc/posix-functions/strerror_r.texi
+++ b/doc/posix-functions/strerror_r.texi
@@ -20,7 +20,8 @@ Portability problems fixed by Gnulib:
 This function is missing on some platforms:
 NetBSD 3.0, Minix 3.1.8, HP-UX 11.23, Solaris 9, mingw, MSVC 14.
 @item
-glibc, Cygwin, and Android have an incompatible version of this function.
+glibc, Cygwin, Android, and AIX+@code{_LINUX_SOURCE_COMPAT}
+have an incompatible version of this function.
 The POSIX compliant code
 @smallexample
 char *s = (strerror_r (err, buf, buflen) == 0 ? buf : NULL);
diff --git a/doc/posix-headers/errno.texi b/doc/posix-headers/errno.texi
index 2adb323d9a..ab8aff39fc 100644
--- a/doc/posix-headers/errno.texi
+++ b/doc/posix-headers/errno.texi
@@ -53,6 +53,10 @@ Mac OS X 10.5, FreeBSD 6.0, NetBSD 9.3, OpenBSD 6.0, Minix 
3.1.8, AIX 5.1, HP-UX
 @item
 The macro @code{EILSEQ} is not defined on some platforms:
 LynxOS 178 2.2.2.
+@item
+The macros @code{EEXIST} and @code{ENOTEMPTY} have the same value on
+some platforms:
+AIX 7.3.
 @end itemize
 
 Portability problems not fixed by Gnulib:
diff --git a/lib/errno.in.h b/lib/errno.in.h
index aa658e6270..ba927037f6 100644
--- a/lib/errno.in.h
+++ b/lib/errno.in.h
@@ -133,7 +133,7 @@
 
 /* These are intentionally the same values as the WSA* error numbers, defined
    in <winsock2.h>.  */
-#  define ESOCKTNOSUPPORT 10044  /* not required by POSIX */
+#  define ESOCKTNOSUPPORT 10044
 #  define EPFNOSUPPORT    10046  /* not required by POSIX */
 #  define ESHUTDOWN       10058  /* not required by POSIX */
 #  define ETOOMANYREFS    10059  /* not required by POSIX */
diff --git a/m4/calloc.m4 b/m4/calloc.m4
index 550cf5cc90..0fbd0d8090 100644
--- a/m4/calloc.m4
+++ b/m4/calloc.m4
@@ -1,5 +1,5 @@
 # calloc.m4
-# serial 31
+# serial 32
 dnl Copyright (C) 2004-2024 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -58,6 +58,11 @@ AC_DEFUN([gl_FUNC_CALLOC_GNU],
 [
   AC_REQUIRE([gl_STDLIB_H_DEFAULTS])
   AC_REQUIRE([gl_FUNC_CALLOC_POSIX])
+
+  dnl This helps if !(__VEC__ || __AIXVEC), and shouldn't hurt otherwise.
+  AC_DEFINE([_LINUX_SOURCE_COMPAT], [1],
+    [Define so that AIX headers are more compatible with GNU/Linux.])
+
   REPLACE_CALLOC_FOR_CALLOC_GNU="$REPLACE_CALLOC_FOR_CALLOC_POSIX"
   if test $REPLACE_CALLOC_FOR_CALLOC_GNU = 0; then
     _AC_FUNC_CALLOC_IF([], [REPLACE_CALLOC_FOR_CALLOC_GNU=1])
diff --git a/m4/errno_h.m4 b/m4/errno_h.m4
index b6050e5d8e..f6a2e81b5d 100644
--- a/m4/errno_h.m4
+++ b/m4/errno_h.m4
@@ -1,5 +1,5 @@
 # errno_h.m4
-# serial 14
+# serial 15
 dnl Copyright (C) 2004, 2006, 2008-2024 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -10,6 +10,11 @@ AC_PREREQ([2.61])
 AC_DEFUN_ONCE([gl_HEADER_ERRNO_H],
 [
   AC_REQUIRE([AC_PROG_CC])
+
+  dnl Persuade AIX 7.3 errno.h to make EEXIST != ENOTEMPTY.
+  AC_DEFINE([_LINUX_SOURCE_COMPAT], [1],
+    [Define so that AIX headers are more compatible with GNU/Linux.])
+
   AC_CACHE_CHECK([for complete errno.h], [gl_cv_header_errno_h_complete], [
     AC_EGREP_CPP([booboo],[
 #include <errno.h>
diff --git a/m4/malloc.m4 b/m4/malloc.m4
index 41a46937ea..a410a5c24f 100644
--- a/m4/malloc.m4
+++ b/m4/malloc.m4
@@ -1,5 +1,5 @@
 # malloc.m4
-# serial 31
+# serial 32
 dnl Copyright (C) 2007, 2009-2024 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -45,6 +45,11 @@ AC_DEFUN([gl_FUNC_MALLOC_GNU],
 [
   AC_REQUIRE([gl_STDLIB_H_DEFAULTS])
   AC_REQUIRE([gl_FUNC_MALLOC_POSIX])
+
+  dnl This helps if !(__VEC__ || __AIXVEC), and shouldn't hurt otherwise.
+  AC_DEFINE([_LINUX_SOURCE_COMPAT], [1],
+    [Define so that AIX headers are more compatible with GNU/Linux.])
+
   REPLACE_MALLOC_FOR_MALLOC_GNU="$REPLACE_MALLOC_FOR_MALLOC_POSIX"
   if test $REPLACE_MALLOC_FOR_MALLOC_GNU = 0; then
     _AC_FUNC_MALLOC_IF([], [REPLACE_MALLOC_FOR_MALLOC_GNU=1])
diff --git a/m4/passfd.m4 b/m4/passfd.m4
index 67e9c2fed0..fe7ad86fd2 100644
--- a/m4/passfd.m4
+++ b/m4/passfd.m4
@@ -1,5 +1,5 @@
 # passfd.m4
-# serial 9
+# serial 10
 dnl Copyright (C) 2011-2024 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -13,7 +13,7 @@ AC_DEFUN([gl_PASSFD],
   dnl Persuade AIX 5.2 <sys/socket.h> to declare CMSG_SPACE, CMSG_LEN.
   dnl CMSG_FIRSTHDR is POSIX 2008, but CMSG_SPACE is only in RFC 3542.
   AC_DEFINE([_LINUX_SOURCE_COMPAT], [1],
-    [Define in order to get some macros on AIX systems.])
+    [Define so that AIX headers are more compatible with GNU/Linux.])
 
   dnl Passfd prefers the POSIX use of msg.msg_control if the CMSG_* macros
   dnl are present, but can fall back to BSD 4.3 style of msg.msg_accrights.
diff --git a/m4/realloc.m4 b/m4/realloc.m4
index eb90d5885c..13bb28ce9d 100644
--- a/m4/realloc.m4
+++ b/m4/realloc.m4
@@ -1,5 +1,5 @@
 # realloc.m4
-# serial 29
+# serial 30
 dnl Copyright (C) 2007, 2009-2024 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -45,6 +45,11 @@ AC_DEFUN([gl_FUNC_REALLOC_GNU],
 [
   AC_REQUIRE([gl_STDLIB_H_DEFAULTS])
   AC_REQUIRE([gl_FUNC_REALLOC_POSIX])
+
+  dnl This helps if !(__VEC__ || __AIXVEC), and shouldn't hurt otherwise.
+  AC_DEFINE([_LINUX_SOURCE_COMPAT], [1],
+    [Define so that AIX headers are more compatible with GNU/Linux.])
+
   if test $REPLACE_REALLOC_FOR_REALLOC_GNU = 0; then
     _AC_FUNC_REALLOC_IF([], [REPLACE_REALLOC_FOR_REALLOC_GNU=1])
   fi
diff --git a/m4/scandir.m4 b/m4/scandir.m4
index f981e1f839..192ac5f154 100644
--- a/m4/scandir.m4
+++ b/m4/scandir.m4
@@ -1,5 +1,5 @@
 # scandir.m4
-# serial 2
+# serial 3
 dnl Copyright (C) 2009-2024 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -12,6 +12,9 @@ AC_DEFUN([gl_FUNC_SCANDIR],
   dnl Persuade glibc and Solaris <dirent.h> to declare scandir().
   AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
 
+  AC_DEFINE([_LINUX_SOURCE_COMPAT], [1],
+    [Define so that AIX headers are more compatible with GNU/Linux.])
+
   AC_CHECK_FUNCS([scandir])
   if test $ac_cv_func_scandir = no; then
     HAVE_SCANDIR=0
diff --git a/m4/strerror_r.m4 b/m4/strerror_r.m4
index a83136c686..eae9f1c419 100644
--- a/m4/strerror_r.m4
+++ b/m4/strerror_r.m4
@@ -1,5 +1,5 @@
 # strerror_r.m4
-# serial 26
+# serial 27
 dnl Copyright (C) 2002, 2007-2024 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -10,6 +10,13 @@ AC_DEFUN([gl_FUNC_STRERROR_R],
   AC_REQUIRE([gl_STRING_H_DEFAULTS])
   AC_REQUIRE([gl_FUNC_STRERROR_R_WORKS])
 
+  dnl On AIX, ask for the GNU/Linux API.  Other modules might ask for
+  dnl that API for other reasons, so we will will need override it because
+  dnl we cannot easily ask AIX for the GNU/Linux API for everything
+  dnl but strerror_r.
+  AC_DEFINE([_LINUX_SOURCE_COMPAT], [1],
+    [Define so that AIX headers are more compatible with GNU/Linux.])
+
   dnl Some systems don't declare strerror_r() if _THREAD_SAFE and _REENTRANT
   dnl are not defined.
   AC_CHECK_DECLS_ONCE([strerror_r])
diff --git a/modules/errno-tests b/modules/errno-tests
index 71e732ce3e..f77aa5ae6b 100644
--- a/modules/errno-tests
+++ b/modules/errno-tests
@@ -2,6 +2,8 @@ Files:
 tests/test-errno.c
 
 Depends-on:
+assert-h
+c99
 errno-c++-tests
 
 configure.ac:
@@ -9,4 +11,3 @@ configure.ac:
 Makefile.am:
 TESTS += test-errno
 check_PROGRAMS += test-errno
-
diff --git a/tests/test-errno.c b/tests/test-errno.c
index 99600add83..7403ee1432 100644
--- a/tests/test-errno.c
+++ b/tests/test-errno.c
@@ -20,90 +20,92 @@
 
 #include <errno.h>
 
-/* Verify that the POSIX mandated errno values exist and can be used as
-   initializers outside of a function.
-   The variable names happen to match the Linux/x86 error numbers.  */
-int e1 = EPERM;
-int e2 = ENOENT;
-int e3 = ESRCH;
-int e4 = EINTR;
-int e5 = EIO;
-int e6 = ENXIO;
-int e7 = E2BIG;
-int e8 = ENOEXEC;
-int e9 = EBADF;
-int e10 = ECHILD;
-int e11 = EAGAIN;
-int e11a = EWOULDBLOCK;
-int e12 = ENOMEM;
-int e13 = EACCES;
-int e14 = EFAULT;
-int e16 = EBUSY;
-int e17 = EEXIST;
-int e18 = EXDEV;
-int e19 = ENODEV;
-int e20 = ENOTDIR;
-int e21 = EISDIR;
-int e22 = EINVAL;
-int e23 = ENFILE;
-int e24 = EMFILE;
-int e25 = ENOTTY;
-int e26 = ETXTBSY;
-int e27 = EFBIG;
-int e28 = ENOSPC;
-int e29 = ESPIPE;
-int e30 = EROFS;
-int e31 = EMLINK;
-int e32 = EPIPE;
-int e33 = EDOM;
-int e34 = ERANGE;
-int e35 = EDEADLK;
-int e36 = ENAMETOOLONG;
-int e37 = ENOLCK;
-int e38 = ENOSYS;
-int e39 = ENOTEMPTY;
-int e40 = ELOOP;
-int e42 = ENOMSG;
-int e43 = EIDRM;
-int e67 = ENOLINK;
-int e71 = EPROTO;
-int e72 = EMULTIHOP;
-int e74 = EBADMSG;
-int e75 = EOVERFLOW;
-int e84 = EILSEQ;
-int e88 = ENOTSOCK;
-int e89 = EDESTADDRREQ;
-int e90 = EMSGSIZE;
-int e91 = EPROTOTYPE;
-int e92 = ENOPROTOOPT;
-int e93 = EPROTONOSUPPORT;
-int e95 = EOPNOTSUPP;
-int e95a = ENOTSUP;
-int e97 = EAFNOSUPPORT;
-int e98 = EADDRINUSE;
-int e99 = EADDRNOTAVAIL;
-int e100 = ENETDOWN;
-int e101 = ENETUNREACH;
-int e102 = ENETRESET;
-int e103 = ECONNABORTED;
-int e104 = ECONNRESET;
-int e105 = ENOBUFS;
-int e106 = EISCONN;
-int e107 = ENOTCONN;
-int e110 = ETIMEDOUT;
-int e111 = ECONNREFUSED;
-int e113 = EHOSTUNREACH;
-int e114 = EALREADY;
-int e115 = EINPROGRESS;
-int e116 = ESTALE;
-int e122 = EDQUOT;
-int e125 = ECANCELED;
-int e130 = EOWNERDEAD;
-int e131 = ENOTRECOVERABLE;
+/* Check all POSIX-defined errno values, using M (v) to check value v.  */
+#define CHECK_POSIX_ERRNOS(m) \
+  m (E2BIG) \
+  m (EACCES) \
+  m (EADDRINUSE) \
+  m (EADDRNOTAVAIL) \
+  m (EAFNOSUPPORT) \
+  m (EAGAIN) \
+  m (EALREADY) \
+  m (EBADF) \
+  m (EBADMSG) \
+  m (EBUSY) \
+  m (ECANCELED) \
+  m (ECHILD) \
+  m (ECONNABORTED) \
+  m (ECONNREFUSED) \
+  m (ECONNRESET) \
+  m (EDEADLK) \
+  m (EDESTADDRREQ) \
+  m (EDOM) \
+  m (EDQUOT) \
+  m (EEXIST) \
+  m (EFAULT) \
+  m (EFBIG) \
+  m (EHOSTUNREACH) \
+  m (EIDRM) \
+  m (EILSEQ) \
+  m (EINPROGRESS) \
+  m (EINTR) \
+  m (EINVAL) \
+  m (EIO) \
+  m (EISCONN) \
+  m (EISDIR) \
+  m (ELOOP) \
+  m (EMFILE) \
+  m (EMLINK) \
+  m (EMSGSIZE) \
+  m (EMULTIHOP) \
+  m (ENAMETOOLONG) \
+  m (ENETDOWN) \
+  m (ENETRESET) \
+  m (ENETUNREACH) \
+  m (ENFILE) \
+  m (ENOBUFS) \
+  m (ENODEV) \
+  m (ENOENT) \
+  m (ENOEXEC) \
+  m (ENOLCK) \
+  m (ENOLINK) \
+  m (ENOMEM) \
+  m (ENOMSG) \
+  m (ENOPROTOOPT) \
+  m (ENOSPC) \
+  m (ENOSYS) \
+  m (ENOTCONN) \
+  m (ENOTDIR) \
+  m (ENOTEMPTY) \
+  m (ENOTRECOVERABLE) \
+  m (ENOTSOCK) \
+  m (ENOTSUP) \
+  m (ENOTTY) \
+  m (ENXIO) \
+  m (EOPNOTSUPP) \
+  m (EOVERFLOW) \
+  m (EOWNERDEAD) \
+  m (EPERM) \
+  m (EPIPE) \
+  m (EPROTO) \
+  m (EPROTONOSUPPORT) \
+  m (EPROTOTYPE) \
+  m (ERANGE) \
+  m (EROFS) \
+  m (ESOCKTNOSUPPORT) \
+  m (ESPIPE) \
+  m (ESRCH) \
+  m (ESTALE) \
+  m (ETIMEDOUT) \
+  m (ETXTBSY) \
+  m (EWOULDBLOCK) \
+  m (EXDEV) \
+  /* end of CHECK_POSIX_ERRNOS */
 
-/* Don't verify that these errno values are all different, except for possibly
-   EWOULDBLOCK == EAGAIN.  Even Linux/x86 does not pass this check: it has
-   ENOTSUP == EOPNOTSUPP.  */
+/* Verify that the POSIX mandated errno values can be used as integer
+   constant expressions and are all positive.  */
+#define POSITIVE_INTEGER_CONSTANT_EXPRESSION(e) static_assert (0 < (e) << 0);
+CHECK_POSIX_ERRNOS (POSITIVE_INTEGER_CONSTANT_EXPRESSION)
 
 int
 main ()
@@ -111,9 +113,18 @@ main ()
   /* Verify that errno can be assigned.  */
   errno = EOVERFLOW;
 
-  /* snprintf() callers want to distinguish EINVAL and EOVERFLOW.  */
-  if (errno == EINVAL)
-    return 1;
-
-  return 0;
+  /* Check that errno values all differ, except possibly for
+     EWOULDBLOCK == EAGAIN and ENOTSUP == EOPNOTSUPP.  */
+  #define INDEXED_BY_ERRNO(e) [e] = 1,
+  #define ERRNO_COUNT(e) 0,
+  static char const
+    indexed_by_errno[] = { CHECK_POSIX_ERRNOS (INDEXED_BY_ERRNO) },
+    errno_count[] = { CHECK_POSIX_ERRNOS (ERRNO_COUNT) };
+  int distinct_errnos = 0;
+  for (int i = 0; i < sizeof indexed_by_errno; i++)
+    distinct_errnos += indexed_by_errno[i];
+  return ((sizeof errno_count
+           - (EWOULDBLOCK == EAGAIN)
+           - (ENOTSUP == EOPNOTSUPP))
+          != distinct_errnos);
 }
-- 
2.43.0


Reply via email to