On NetBSD 7.1.1, I'm seeing a compilation error: gcc -std=gnu11 -DHAVE_CONFIG_H -DEXEEXT=\"\" -DEXEEXT=\"\" -I. -I../../gltests -I.. -DGNULIB_STRICT_CHECKING=1 -DIN_GNULIB_TESTS=1 -I. -I../../gltests -I.. -I../../gltests/.. -I../gllib -I../../gltests/../gllib -I/home/bruno/include -Wall -Wno-error -g -O2 -MT test-htonl.o -MD -MP -MF $depbase.Tpo -c -o test-htonl.o ../../gltests/test-htonl.c &&\ mv -f $depbase.Tpo $depbase.Po In file included from /usr/include/amd64/bswap.h:13:0, from /usr/include/sys/endian.h:107, from /usr/include/amd64/endian.h:3, from /usr/include/sys/types.h:98, from ../gllib/sys/types.h:46, from ../gllib/sys/socket.h:51, from ../gllib/arpa/inet.h:34, from ../../gltests/test-htonl.c:22: ../gllib/endian.h:112:1: error: expected declaration specifiers or '...' before '(' token be16toh (uint16_t x) ^ ../gllib/endian.h:112:1: error: expected ')' before '?' token be16toh (uint16_t x) ^ ../gllib/endian.h:122:1: error: expected declaration specifiers or '...' before '(' token be32toh (uint32_t x) ^ ../gllib/endian.h:122:1: error: expected ')' before '?' token be32toh (uint32_t x) ^ ../gllib/endian.h:133:1: error: expected declaration specifiers or '...' before '(' token be64toh (uint64_t x) ^ ../gllib/endian.h:133:1: error: expected ')' before '?' token be64toh (uint64_t x) ^ ../gllib/endian.h:146:1: error: expected declaration specifiers or '...' before '(' token htobe16 (uint16_t x) ^ ../gllib/endian.h:146:1: error: expected ')' before '?' token htobe16 (uint16_t x) ^ ../gllib/endian.h:156:1: error: expected declaration specifiers or '...' before '(' token htobe32 (uint32_t x) ^ ../gllib/endian.h:156:1: error: expected ')' before '?' token htobe32 (uint32_t x) ^ ../gllib/endian.h:167:1: error: expected declaration specifiers or '...' before '(' token htobe64 (uint64_t x) ^ ../gllib/endian.h:167:1: error: expected ')' before '?' token htobe64 (uint64_t x) ^ In file included from /usr/include/amd64/endian.h:3:0, from /usr/include/sys/types.h:98, from ../gllib/sys/types.h:46, from ../gllib/sys/socket.h:51, from ../gllib/arpa/inet.h:34, from ../../gltests/test-htonl.c:22: ../gllib/endian.h:180:1: error: expected ')' before 'x' le16toh (uint16_t x) ^ ../gllib/endian.h:190:1: error: expected ')' before 'x' le32toh (uint32_t x) ^ ../gllib/endian.h:201:1: error: expected ')' before 'x' le64toh (uint64_t x) ^ ../gllib/endian.h:214:1: error: expected ')' before 'x' htole16 (uint16_t x) ^ ../gllib/endian.h:224:1: error: expected ')' before 'x' htole32 (uint32_t x) ^ ../gllib/endian.h:235:1: error: expected ')' before 'x' htole64 (uint64_t x) ^ Makefile:27792: recipe for target 'test-htonl.o' failed gmake[4]: *** [test-htonl.o] Error 1
The cause are system definitions of be16toh etc. as macros, in the system's <sys/endian.h>. This patch fixes it. 2024-12-28 Bruno Haible <br...@clisp.org> endian: Fix compilation error on NetBSD 7.1. * m4/endian_h.m4 (gl_ENDIAN_H): Test for <sys/endian.h>. Set HAVE_SYS_ENDIAN_H. * lib/endian.in.h: Test HAVE_SYS_ENDIAN_H as an alternative to HAVE_ENDIAN_H. * modules/endian (Makefile.am): Substitute HAVE_SYS_ENDIAN_H. diff --git a/lib/endian.in.h b/lib/endian.in.h index 156fe49fbd..09b5dfb42c 100644 --- a/lib/endian.in.h +++ b/lib/endian.in.h @@ -29,6 +29,10 @@ /* The include_next requires a split double-inclusion guard. */ # @INCLUDE_NEXT@ @NEXT_ENDIAN_H@ +#elif @HAVE_SYS_ENDIAN_H@ + +# include <sys/endian.h> + #endif @@ -69,7 +73,7 @@ _GL_INLINE_HEADER_BEGIN # define BYTE_ORDER LITTLE_ENDIAN #endif -#if @HAVE_ENDIAN_H@ +#if @HAVE_ENDIAN_H@ || @HAVE_SYS_ENDIAN_H@ /* Make sure we don't have any system definitions. */ # undef be16toh diff --git a/m4/endian_h.m4 b/m4/endian_h.m4 index c205a44464..712c435fe8 100644 --- a/m4/endian_h.m4 +++ b/m4/endian_h.m4 @@ -1,5 +1,5 @@ # endian_h.m4 -# serial 4 +# serial 5 dnl Copyright 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, @@ -80,6 +80,75 @@ AC_DEFUN_ONCE([gl_ENDIAN_H] HAVE_ENDIAN_H=0 fi + AC_CHECK_HEADERS_ONCE([sys/endian.h]) + if test $ac_cv_header_sys_endian_h = yes; then + HAVE_SYS_ENDIAN_H=1 + dnl Check if sys/endian.h defines uint16_t, uint32_t, and uint64_t. + dnl Note: We don't use the result of this test for now. + AC_CACHE_CHECK([if sys/endian.h defines stdint types], + [gl_cv_header_sys_endian_h_stdint_types], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include <sys/endian.h> + ]], + [[uint16_t t1 = 0; + uint32_t t2 = 0; + uint64_t t3 = 0; + return !(t1 + t2 + t3); + ]])], + [gl_cv_header_sys_endian_h_stdint_types=yes], + [gl_cv_header_sys_endian_h_stdint_types=no]) + ]) + dnl Note: We don't use the result of this test for now. + AC_CACHE_CHECK([if sys/endian.h defines functions and macros], + [gl_cv_header_working_sys_endian_h], + [gl_cv_header_working_sys_endian_h=no + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( +[[ +#include <sys/endian.h> +]], +[[ +#if LITTLE_ENDIAN == BIG_ENDIAN +# error "Endian macros not unique." +#endif +#if BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN +# error "Byte order not defined." +#endif + +/* Big endian to host. */ +int value16_1 = be16toh (0.0); +int value32_1 = be32toh (0.0); +int value64_1 = be64toh (0.0); + +/* Host to big endian. */ +int value16_2 = htobe16 (0.0); +int value32_2 = htobe32 (0.0); +int value64_2 = htobe64 (0.0); + +/* Little endian to host. */ +int value16_3 = le16toh (0.0); +int value32_3 = le32toh (0.0); +int value64_3 = le64toh (0.0); + +/* Host to little endian. */ +int value16_4 = htole16 (0.0); +int value32_4 = htole32 (0.0); +int value64_4 = htole64 (0.0); + +/* Make sure the variables get used. */ +return !(value16_1 + value32_1 + value64_1 + + value16_2 + value32_2 + value64_2 + + value16_3 + value32_3 + value64_3 + + value16_4 + value32_4 + value64_4); +]])], + [gl_cv_header_working_sys_endian_h=yes], + [gl_cv_header_working_sys_endian_h=no]) + ]) + else + HAVE_SYS_ENDIAN_H=0 + fi + dnl Check if endian.h should be generated. if test "$gl_cv_header_endian_h_stdint_types" = yes \ && test "$gl_cv_header_working_endian_h" = yes; then @@ -100,5 +169,6 @@ AC_DEFUN_ONCE([gl_ENDIAN_H] fi AC_SUBST([HAVE_ENDIAN_H]) + AC_SUBST([HAVE_SYS_ENDIAN_H]) AC_SUBST([ENDIAN_H_JUST_MISSING_STDINT]) ]) diff --git a/modules/endian b/modules/endian index c4cef9dc90..676d5b6064 100644 --- a/modules/endian +++ b/modules/endian @@ -33,6 +33,7 @@ endian.h: endian.in.h $(top_builddir)/config.status -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ -e 's|@''HAVE_ENDIAN_H''@|$(HAVE_ENDIAN_H)|g' \ -e 's|@''NEXT_ENDIAN_H''@|$(NEXT_ENDIAN_H)|g' \ + -e 's|@''HAVE_SYS_ENDIAN_H''@|$(HAVE_SYS_ENDIAN_H)|g' \ -e 's|@''ENDIAN_H_JUST_MISSING_STDINT''@|$(ENDIAN_H_JUST_MISSING_STDINT)|g' \ $(srcdir)/endian.in.h > $@-t $(AM_V_at)mv $@-t $@