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