1dnl AC_NEED_BYTEORDER_H ( HEADER-TO-GENERATE ) 2dnl Copyright 2001-2002 by Dan Fandrich <dan@coneharvesters.com> 3dnl This file may be copied and used freely without restrictions. No warranty 4dnl is expressed or implied. 5dnl 6dnl Create a header file that guarantees that byte swapping macros of the 7dnl ntohl variety as well as the extended types included in OpenBSD and 8dnl NetBSD such as le32toh are defined. If possible, the standard ntohl 9dnl are overloaded as they are optimized for the given platform, but when 10dnl this is not possible (e.g. on a big-endian machine) they are defined 11dnl in this file. 12 13dnl Look for a symbol in a header file 14dnl AC_HAVE_SYMBOL ( IDENTIFIER, HEADER-FILE, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND ) 15AC_DEFUN([AC_HAVE_SYMBOL], 16[ 17AC_MSG_CHECKING(for $1 in $2) 18AC_EGREP_CPP([symbol is present|\<$1\>],[ 19#include <$2> 20#ifdef $1 21 symbol is present 22#endif 23 ], 24[AC_MSG_RESULT(yes) 25$3 26], 27[AC_MSG_RESULT(no) 28$4 29])]) 30 31 32dnl Create a header file that defines extended byte swapping macros 33AC_DEFUN([AC_NEED_BYTEORDER_H], 34[ 35changequote(, )dnl 36ac_dir=`echo $1|sed 's%/[^/][^/]*$%%'` 37changequote([, ])dnl 38if test "$ac_dir" != "$1" && test "$ac_dir" != .; then 39 # The file is in a subdirectory. 40 test ! -d "$ac_dir" && mkdir "$ac_dir" 41fi 42 43# We're only interested in the target CPU, but it's not always set 44effective_target="$target" 45if test "x$effective_target" = xNONE -o "x$effective_target" = x ; then 46 effective_target="$host" 47fi 48AC_SUBST(effective_target) 49 50cat > "$1" << EOF 51/* This file is generated automatically by configure */ 52/* It is valid only for the system type ${effective_target} */ 53 54#ifndef __BYTEORDER_H 55#define __BYTEORDER_H 56 57EOF 58 59dnl First, do an endian check 60AC_C_BIGENDIAN 61 62dnl Look for NetBSD-style extended byte swapping macros 63AC_HAVE_SYMBOL(le32toh,machine/endian.h, 64 [HAVE_LE32TOH=1 65 cat >> "$1" << EOF 66/* extended byte swapping macros are already available */ 67#include <machine/endian.h> 68 69EOF], 70 71[ 72 73dnl Look for standard byte swapping macros 74AC_HAVE_SYMBOL(ntohl,arpa/inet.h, 75 [cat >> "$1" << EOF 76/* ntohl and relatives live here */ 77#include <arpa/inet.h> 78 79EOF], 80 81 [AC_HAVE_SYMBOL(ntohl,netinet/in.h, 82 [cat >> "$1" << EOF 83/* ntohl and relatives live here */ 84#include <netinet/in.h> 85 86EOF],true)]) 87]) 88 89dnl Look for generic byte swapping macros 90 91dnl OpenBSD 92AC_HAVE_SYMBOL(swap32,machine/endian.h, 93 [cat >> "$1" << EOF 94/* swap32 and swap16 are defined in machine/endian.h */ 95 96EOF], 97 98 [ 99dnl Linux GLIBC 100 AC_HAVE_SYMBOL(bswap_32,byteswap.h, 101 [cat >> "$1" << EOF 102/* Define generic byte swapping functions */ 103#include <byteswap.h> 104#define swap16(x) bswap_16(x) 105#define swap32(x) bswap_32(x) 106#define swap64(x) bswap_64(x) 107 108EOF], 109 110 [ 111dnl NetBSD 112 AC_HAVE_SYMBOL(bswap32,machine/endian.h, 113 dnl We're already including machine/endian.h if this test succeeds 114 [cat >> "$1" << EOF 115/* Define generic byte swapping functions */ 116EOF 117 if test "$HAVE_LE32TOH" != "1"; then 118 echo '#include <machine/endian.h>'>> "$1" 119 fi 120cat >> "$1" << EOF 121#define swap16(x) bswap16(x) 122#define swap32(x) bswap32(x) 123#define swap64(x) bswap64(x) 124 125EOF], 126 127 [ 128dnl FreeBSD 129 AC_HAVE_SYMBOL(__byte_swap_long,sys/types.h, 130 [cat >> "$1" << EOF 131/* Define generic byte swapping functions */ 132#include <sys/types.h> 133#define swap16(x) __byte_swap_word(x) 134#define swap32(x) __byte_swap_long(x) 135/* No optimized 64 bit byte swapping macro is available */ 136#define swap64(x) ((uint64_t)(((uint64_t)(x) << 56) & 0xff00000000000000ULL | \\ 137 ((uint64_t)(x) << 40) & 0x00ff000000000000ULL | \\ 138 ((uint64_t)(x) << 24) & 0x0000ff0000000000ULL | \\ 139 ((uint64_t)(x) << 8) & 0x000000ff00000000ULL | \\ 140 ((x) >> 8) & 0x00000000ff000000ULL | \\ 141 ((x) >> 24) & 0x0000000000ff0000ULL | \\ 142 ((x) >> 40) & 0x000000000000ff00ULL | \\ 143 ((x) >> 56) & 0x00000000000000ffULL)) 144 145EOF], 146 147 [ 148dnl OS X 149 AC_HAVE_SYMBOL(NXSwapLong,machine/byte_order.h, 150 [cat >> "$1" << EOF 151/* Define generic byte swapping functions */ 152#include <machine/byte_order.h> 153#define swap16(x) NXSwapShort(x) 154#define swap32(x) NXSwapLong(x) 155#define swap64(x) NXSwapLongLong(x) 156 157EOF], 158 [ 159 if test $ac_cv_c_bigendian = yes; then 160 cat >> "$1" << EOF 161/* No other byte swapping functions are available on this big-endian system */ 162#define swap16(x) ((uint16_t)(((x) << 8) | ((uint16_t)(x) >> 8))) 163#define swap32(x) ((uint32_t)(((uint32_t)(x) << 24) & 0xff000000UL | \\ 164 ((uint32_t)(x) << 8) & 0x00ff0000UL | \\ 165 ((x) >> 8) & 0x0000ff00UL | \\ 166 ((x) >> 24) & 0x000000ffUL)) 167#define swap64(x) ((uint64_t)(((uint64_t)(x) << 56) & 0xff00000000000000ULL | \\ 168 ((uint64_t)(x) << 40) & 0x00ff000000000000ULL | \\ 169 ((uint64_t)(x) << 24) & 0x0000ff0000000000ULL | \\ 170 ((uint64_t)(x) << 8) & 0x000000ff00000000ULL | \\ 171 ((x) >> 8) & 0x00000000ff000000ULL | \\ 172 ((x) >> 24) & 0x0000000000ff0000ULL | \\ 173 ((x) >> 40) & 0x000000000000ff00ULL | \\ 174 ((x) >> 56) & 0x00000000000000ffULL)) 175 176EOF 177 else 178 cat >> "$1" << EOF 179/* Use these as generic byteswapping macros on this little endian system */ 180#define swap16(x) ntohs(x) 181#define swap32(x) ntohl(x) 182/* No optimized 64 bit byte swapping macro is available */ 183#define swap64(x) ((uint64_t)(((uint64_t)(x) << 56) & 0xff00000000000000ULL | \\ 184 ((uint64_t)(x) << 40) & 0x00ff000000000000ULL | \\ 185 ((uint64_t)(x) << 24) & 0x0000ff0000000000ULL | \\ 186 ((uint64_t)(x) << 8) & 0x000000ff00000000ULL | \\ 187 ((x) >> 8) & 0x00000000ff000000ULL | \\ 188 ((x) >> 24) & 0x0000000000ff0000ULL | \\ 189 ((x) >> 40) & 0x000000000000ff00ULL | \\ 190 ((x) >> 56) & 0x00000000000000ffULL)) 191 192EOF 193 fi 194]) 195 ]) 196 ]) 197 ]) 198]) 199 200 201[ 202if test "$HAVE_LE32TOH" != "1"; then 203 cat >> "$1" << EOF 204/* The byte swapping macros have the form: */ 205/* EENN[a]toh or htoEENN[a] where EE is be (big endian) or */ 206/* le (little-endian), NN is 16 or 32 (number of bits) and a, */ 207/* if present, indicates that the endian side is a pointer to an */ 208/* array of uint8_t bytes instead of an integer of the specified length. */ 209/* h refers to the host's ordering method. */ 210 211/* So, to convert a 32-bit integer stored in a buffer in little-endian */ 212/* format into a uint32_t usable on this machine, you could use: */ 213/* uint32_t value = le32atoh(&buf[3]); */ 214/* To put that value back into the buffer, you could use: */ 215/* htole32a(&buf[3], value); */ 216 217/* Define aliases for the standard byte swapping macros */ 218/* Arguments to these macros must be properly aligned on natural word */ 219/* boundaries in order to work properly on all architectures */ 220#define htobe16(x) htons(x) 221#define htobe32(x) htonl(x) 222#define be16toh(x) ntohs(x) 223#define be32toh(x) ntohl(x) 224 225#define HTOBE16(x) (x) = htobe16(x) 226#define HTOBE32(x) (x) = htobe32(x) 227#define BE32TOH(x) (x) = be32toh(x) 228#define BE16TOH(x) (x) = be16toh(x) 229 230EOF 231 232 if test $ac_cv_c_bigendian = yes; then 233 cat >> "$1" << EOF 234/* Define our own extended byte swapping macros for big-endian machines */ 235#define htole16(x) swap16(x) 236#define htole32(x) swap32(x) 237#define le16toh(x) swap16(x) 238#define le32toh(x) swap32(x) 239 240#define htobe64(x) (x) 241#define be64toh(x) (x) 242 243#define HTOLE16(x) (x) = htole16(x) 244#define HTOLE32(x) (x) = htole32(x) 245#define LE16TOH(x) (x) = le16toh(x) 246#define LE32TOH(x) (x) = le32toh(x) 247 248#define HTOBE64(x) (void) (x) 249#define BE64TOH(x) (void) (x) 250 251EOF 252 else 253 cat >> "$1" << EOF 254/* On little endian machines, these macros are null */ 255#define htole16(x) (x) 256#define htole32(x) (x) 257#define htole64(x) (x) 258#define le16toh(x) (x) 259#define le32toh(x) (x) 260#define le64toh(x) (x) 261 262#define HTOLE16(x) (void) (x) 263#define HTOLE32(x) (void) (x) 264#define HTOLE64(x) (void) (x) 265#define LE16TOH(x) (void) (x) 266#define LE32TOH(x) (void) (x) 267#define LE64TOH(x) (void) (x) 268 269/* These don't have standard aliases */ 270#define htobe64(x) swap64(x) 271#define be64toh(x) swap64(x) 272 273#define HTOBE64(x) (x) = htobe64(x) 274#define BE64TOH(x) (x) = be64toh(x) 275 276EOF 277 fi 278fi 279 280cat >> "$1" << EOF 281/* Define the C99 standard length-specific integer types */ 282#include <_stdint.h> 283 284EOF 285 286case "${effective_target}" in 287 i[3456]86-*) 288 cat >> "$1" << EOF 289/* Here are some macros to create integers from a byte array */ 290/* These are used to get and put integers from/into a uint8_t array */ 291/* with a specific endianness. This is the most portable way to generate */ 292/* and read messages to a network or serial device. Each member of a */ 293/* packet structure must be handled separately. */ 294 295/* The i386 and compatibles can handle unaligned memory access, */ 296/* so use the optimized macros above to do this job */ 297#define be16atoh(x) be16toh(*(uint16_t*)(x)) 298#define be32atoh(x) be32toh(*(uint32_t*)(x)) 299#define be64atoh(x) be64toh(*(uint64_t*)(x)) 300#define le16atoh(x) le16toh(*(uint16_t*)(x)) 301#define le32atoh(x) le32toh(*(uint32_t*)(x)) 302#define le64atoh(x) le64toh(*(uint64_t*)(x)) 303 304#define htobe16a(a,x) *(uint16_t*)(a) = htobe16(x) 305#define htobe32a(a,x) *(uint32_t*)(a) = htobe32(x) 306#define htobe64a(a,x) *(uint64_t*)(a) = htobe64(x) 307#define htole16a(a,x) *(uint16_t*)(a) = htole16(x) 308#define htole32a(a,x) *(uint32_t*)(a) = htole32(x) 309#define htole64a(a,x) *(uint64_t*)(a) = htole64(x) 310 311EOF 312 ;; 313 314 *) 315 cat >> "$1" << EOF 316/* Here are some macros to create integers from a byte array */ 317/* These are used to get and put integers from/into a uint8_t array */ 318/* with a specific endianness. This is the most portable way to generate */ 319/* and read messages to a network or serial device. Each member of a */ 320/* packet structure must be handled separately. */ 321 322/* Non-optimized but portable macros */ 323#define be16atoh(x) ((uint16_t)(((x)[0]<<8)|(x)[1])) 324#define be32atoh(x) ((uint32_t)(((x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])) 325#define be64atoh(x) ((uint64_t)(((x)[0]<<56)|((x)[1]<<48)|((x)[2]<<40)| \\ 326 ((x)[3]<<32)|((x)[4]<<24)|((x)[5]<<16)|((x)[6]<<8)|(x)[7])) 327#define le16atoh(x) ((uint16_t)(((x)[1]<<8)|(x)[0])) 328#define le32atoh(x) ((uint32_t)(((x)[3]<<24)|((x)[2]<<16)|((x)[1]<<8)|(x)[0])) 329#define le64atoh(x) ((uint64_t)(((x)[7]<<56)|((x)[6]<<48)|((x)[5]<<40)| \\ 330 ((x)[4]<<32)|((x)[3]<<24)|((x)[2]<<16)|((x)[1]<<8)|(x)[0])) 331 332#define htobe16a(a,x) (a)[0]=(uint8_t)((x)>>8), (a)[1]=(uint8_t)(x) 333#define htobe32a(a,x) (a)[0]=(uint8_t)((x)>>24), (a)[1]=(uint8_t)((x)>>16), \\ 334 (a)[2]=(uint8_t)((x)>>8), (a)[3]=(uint8_t)(x) 335#define htobe64a(a,x) (a)[0]=(uint8_t)((x)>>56), (a)[1]=(uint8_t)((x)>>48), \\ 336 (a)[2]=(uint8_t)((x)>>40), (a)[3]=(uint8_t)((x)>>32), \\ 337 (a)[4]=(uint8_t)((x)>>24), (a)[5]=(uint8_t)((x)>>16), \\ 338 (a)[6]=(uint8_t)((x)>>8), (a)[7]=(uint8_t)(x) 339#define htole16a(a,x) (a)[1]=(uint8_t)((x)>>8), (a)[0]=(uint8_t)(x) 340#define htole32a(a,x) (a)[3]=(uint8_t)((x)>>24), (a)[2]=(uint8_t)((x)>>16), \\ 341 (a)[1]=(uint8_t)((x)>>8), (a)[0]=(uint8_t)(x) 342#define htole64a(a,x) (a)[7]=(uint8_t)((x)>>56), (a)[6]=(uint8_t)((x)>>48), \\ 343 (a)[5]=(uint8_t)((x)>>40), (a)[4]=(uint8_t)((x)>>32), \\ 344 (a)[3]=(uint8_t)((x)>>24), (a)[2]=(uint8_t)((x)>>16), \\ 345 (a)[1]=(uint8_t)((x)>>8), (a)[0]=(uint8_t)(x) 346 347EOF 348 ;; 349esac 350] 351 352cat >> "$1" << EOF 353#endif /*__BYTEORDER_H*/ 354EOF]) 355