I haven't pushed this since it is my first time attempting the gnulib
header wizardry and doing anything of value in Autoconf.
The configure check should check for unique values of LITTLE_ENDIAN
and BIG_ENDIAN, and that BYTE_ORDER is defined to one of them. POSIX
doesn't require PDP_ENDIAN and I would rather not think about it. :)
Then it checks for uint16_t, uint32_t, and uint64_t being defined and
the existence of the be16toh macros/functions and friends.
Let me know if I missed anything. Other than the docs and test module
which I can do later today (assuming this patch is decent enough).
Collin
From fe97691b765e57a9c5ea35dca5cb9502d284fb2b Mon Sep 17 00:00:00 2001
From: Collin Funk <collin.fu...@gmail.com>
Date: Mon, 13 May 2024 04:43:18 -0700
Subject: [PATCH] endian: New module.
* modules/endian: New file.
* lib/endian.in.h: New file, based on POSIX draft and glibc.
* m4/endian_h.m4: New file, checks for required types and macro/function
definitions.
---
ChangeLog | 8 +++++
lib/endian.in.h | 89 +++++++++++++++++++++++++++++++++++++++++++++++++
m4/endian_h.m4 | 68 +++++++++++++++++++++++++++++++++++++
modules/endian | 40 ++++++++++++++++++++++
4 files changed, 205 insertions(+)
create mode 100644 lib/endian.in.h
create mode 100644 m4/endian_h.m4
create mode 100644 modules/endian
diff --git a/ChangeLog b/ChangeLog
index b1cc7ffcf0..91acd31590 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2024-05-13 Collin Funk <collin.fu...@gmail.com>
+
+ endian: New module.
+ * modules/endian: New file.
+ * lib/endian.in.h: New file, based on POSIX draft and glibc.
+ * m4/endian_h.m4: New file, checks for required types and macro/function
+ definitions.
+
2024-05-13 Paul Eggert <egg...@cs.ucla.edu>
stdbit: port to theoretical platforms
diff --git a/lib/endian.in.h b/lib/endian.in.h
new file mode 100644
index 0000000000..6b287760a5
--- /dev/null
+++ b/lib/endian.in.h
@@ -0,0 +1,89 @@
+/* endian.h - Byte order macros
+
+ Copyright 2024 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* Written by Collin Funk. */
+
+#ifndef _GL_ENDIAN_H
+#define _GL_ENDIAN_H 1
+
+/* This file uses WORDS_BIGENDIAN. */
+#if !_GL_CONFIG_H_INCLUDED
+ #error "Please include config.h first."
+#endif
+
+/* Byteswap macros. */
+#include <byteswap.h>
+
+/* Define uint16_t, uint32_t, and uint64_t. */
+#include <stdint.h>
+
+#define LITTLE_ENDIAN 1234
+#define BIG_ENDIAN 4321
+
+#ifdef WORDS_BIGENDIAN
+# define BYTE_ORDER BIG_ENDIAN
+#else
+# define BYTE_ORDER LITTLE_ENDIAN
+#endif
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+
+/* Big endian to host. */
+# define be16toh(x) bswap_16 (x)
+# define be32toh(x) bswap_32 (x)
+# define be64toh(x) bswap_64 (x)
+
+/* Host to big endian. */
+# define htobe16(x) bswap_16 (x)
+# define htobe32(x) bswap_32 (x)
+# define htobe64(x) bswap_64 (x)
+
+/* Host to little endian. */
+# define htole16(x) ((uint16_t) (x))
+# define htole32(x) ((uint32_t) (x))
+# define htole64(x) ((uint64_t) (x))
+
+/* Little endian to host. */
+# define le16toh(x) ((uint16_t) (x))
+# define le32toh(x) ((uint32_t) (x))
+# define le64toh(x) ((uint64_t) (x))
+
+#else /* BYTE_ORDER == BIG_ENDIAN */
+
+/* Big endian to host. */
+# define be16toh(x) ((uint16_t) (x))
+# define be32toh(x) ((uint32_t) (x))
+# define be64toh(x) ((uint64_t) (x))
+
+/* Host to big endian. */
+# define htobe16(x) ((uint16_t) (x))
+# define htobe32(x) ((uint32_t) (x))
+# define htobe64(x) ((uint64_t) (x))
+
+/* Host to little endian. */
+# define htole16(x) bswap_16 (x)
+# define htole32(x) bswap_32 (x)
+# define htole64(x) bswap_64 (x)
+
+/* Little endian to host. */
+# define le16toh(x) bswap_16 (x)
+# define le32toh(x) bswap_32 (x)
+# define le64toh(x) bswap_64 (x)
+
+#endif
+
+#endif /* _GL_ENDIAN_H */
diff --git a/m4/endian_h.m4 b/m4/endian_h.m4
new file mode 100644
index 0000000000..2c4a781b73
--- /dev/null
+++ b/m4/endian_h.m4
@@ -0,0 +1,68 @@
+# endian_h.m4
+# serial 1
+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,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl A placeholder for <endian.h>, for platforms that have issues.
+
+AC_DEFUN_ONCE([gl_ENDIAN_H],
+[
+ AC_REQUIRE([gl_BIGENDIAN])
+
+ dnl Check for the header.
+ AC_CHECK_HEADERS_ONCE([endian.h])
+
+ dnl Check macros and type definitions.
+ if test $ac_cv_header_endian_h = yes; then
+ AC_CACHE_CHECK([if endian.h conforms to POSIX],
+ [gl_cv_header_working_endian_h],
+ [gl_cv_header_working_endian_h=no
+ AC_COMPILE_IFELSE([
+ AC_LANG_PROGRAM(
+[[
+#include <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
+
+/* Check for uint16_t, uint32_t, uint64_t along with
+ byte order conversion macros/functions. */
+
+/* Big endian to host. */
+uint16_t value16_1 = be16toh (0);
+uint32_t value32_1 = be32toh (0);
+uint64_t value64_1 = be64toh (0);
+
+/* Host to big endian. */
+uint16_t value16_2 = htobe16 (0);
+uint32_t value32_2 = htobe32 (0);
+uint64_t value64_2 = htobe64 (0);
+
+/* Host to little endian. */
+uint16_t value16_3 = htole16 (0);
+uint32_t value32_3 = htole32 (0);
+uint64_t value64_3 = htole64 (0);
+
+/* Little endian to host. */
+uint16_t value16_4 = le16toh (0);
+uint32_t value32_4 = le32toh (0);
+uint64_t value64_4 = le64toh (0);
+
+]])],
+ [gl_cv_header_working_endian_h=yes],
+ [gl_cv_header_working_endian_h=no])
+ ])
+ if test $gl_cv_header_working_endian_h = yes; then
+ GL_GENERATE_ENDIAN_H=false
+ else
+ GL_GENERATE_ENDIAN_H=true
+ fi
+ fi
+])
diff --git a/modules/endian b/modules/endian
new file mode 100644
index 0000000000..f954abb1f4
--- /dev/null
+++ b/modules/endian
@@ -0,0 +1,40 @@
+Description:
+A POSIX-like endian.h.
+
+Files:
+lib/endian.in.h
+m4/endian_h.m4
+
+Depends-on:
+byteswap [$GL_GENERATE_ENDIAN_H]
+stdint [$GL_GENERATE_ENDIAN_H]
+
+configure.ac:
+gl_ENDIAN_H
+gl_CONDITIONAL_HEADER([endian.h])
+AC_PROG_MKDIR_P
+
+Makefile.am:
+BUILT_SOURCES += $(ENDIAN_H)
+
+# We need the following in order to create <endian.h> when the system
+# doesn't have one that works with the given compiler.
+if GL_GENERATE_ENDIAN_H
+endian.h: endian.in.h $(top_builddir)/config.status
+@NMD@ $(AM_V_GEN)$(MKDIR_P) '%reldir%'
+ $(gl_V_at)cp $(srcdir)/endian.in.h $@-t
+ $(AM_V_at)mv $@-t $@
+else
+endian.h: $(top_builddir)/config.status
+ rm -f $@
+endif
+MOSTLYCLEANFILES += endian.h endian.h-t
+
+Include:
+<endian.h>
+
+License:
+LGPLv2+
+
+Maintainer:
+all
--
2.45.0