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