1dnl AC_NEED_BYTEORDER_H ( HEADER-TO-GENERATE ) 2dnl Originally written by Dan Fandrich <dan@coneharvesters.com> 3dnl My contribution is hereby placed into the public domain. 4dnl No warranty 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#define __HAVE_NTOHL 77 78EOF], 79 80 [AC_HAVE_SYMBOL(ntohl,netinet/in.h, 81 [cat >> "$1" << EOF 82/* ntohl and relatives live here */ 83#include <netinet/in.h> 84#define __HAVE_NTOHL 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/* on windows we might not have ntohs / ntohl without including winsock.dll, 181 * so use generic macros */ 182#ifdef __HAVE_NTOHL 183# define swap16(x) htons(x) 184# define swap32(x) htonl(x) 185#else 186# define swap16(x) ((uint16_t)(((x) << 8) | ((uint16_t)(x) >> 8))) 187# define swap32(x) ((uint32_t)((((uint32_t)(x) << 24) & 0xff000000UL) | \\ 188 (((uint32_t)(x) << 8) & 0x00ff0000UL) | \\ 189 (((x) >> 8) & 0x0000ff00UL) | \\ 190 (((x) >> 24) & 0x000000ffUL))) 191#endif 192/* No optimized 64 bit byte swapping macro is available */ 193#define swap64(x) ((uint64_t)((((uint64_t)(x) << 56) & 0xff00000000000000ULL) | \\ 194 (((uint64_t)(x) << 40) & 0x00ff000000000000ULL) | \\ 195 (((uint64_t)(x) << 24) & 0x0000ff0000000000ULL) | \\ 196 (((uint64_t)(x) << 8) & 0x000000ff00000000ULL) | \\ 197 (((x) >> 8) & 0x00000000ff000000ULL) | \\ 198 (((x) >> 24) & 0x0000000000ff0000ULL) | \\ 199 (((x) >> 40) & 0x000000000000ff00ULL) | \\ 200 (((x) >> 56) & 0x00000000000000ffULL))) 201 202EOF 203 fi 204]) 205 ]) 206 ]) 207 ]) 208]) 209 210 211[ 212if test "$HAVE_LE32TOH" != "1"; then 213 cat >> "$1" << EOF 214/* The byte swapping macros have the form: */ 215/* EENN[a]toh or htoEENN[a] where EE is be (big endian) or */ 216/* le (little-endian), NN is 16 or 32 (number of bits) and a, */ 217/* if present, indicates that the endian side is a pointer to an */ 218/* array of uint8_t bytes instead of an integer of the specified length. */ 219/* h refers to the host's ordering method. */ 220 221/* So, to convert a 32-bit integer stored in a buffer in little-endian */ 222/* format into a uint32_t usable on this machine, you could use: */ 223/* uint32_t value = le32atoh(&buf[3]); */ 224/* To put that value back into the buffer, you could use: */ 225/* htole32a(&buf[3], value); */ 226 227/* Define aliases for the standard byte swapping macros */ 228/* Arguments to these macros must be properly aligned on natural word */ 229/* boundaries in order to work properly on all architectures */ 230#ifndef htobe16 231# ifdef __HAVE_NTOHL 232# define htobe16(x) htons(x) 233# else 234# ifdef WORDS_BIGENDIAN 235# define htobe16(x) (x) 236# else 237# define htobe16(x) swap16(x) 238# endif 239# endif 240#endif 241#ifndef htobe32 242# ifdef __HAVE_NTOHL 243# define htobe32(x) htonl(x) 244# else 245# ifdef WORDS_BIGENDIAN 246# define htobe32(x) (x) 247# else 248# define htobe32(x) swap32(x) 249# endif 250# endif 251#endif 252#ifndef be16toh 253# define be16toh(x) htobe16(x) 254#endif 255#ifndef be32toh 256# define be32toh(x) htobe32(x) 257#endif 258 259#define HTOBE16(x) (x) = htobe16(x) 260#define HTOBE32(x) (x) = htobe32(x) 261#define BE32TOH(x) (x) = be32toh(x) 262#define BE16TOH(x) (x) = be16toh(x) 263 264EOF 265 266 if test $ac_cv_c_bigendian = yes; then 267 cat >> "$1" << EOF 268/* Define our own extended byte swapping macros for big-endian machines */ 269#ifndef htole16 270# define htole16(x) swap16(x) 271#endif 272#ifndef htole32 273# define htole32(x) swap32(x) 274#endif 275#ifndef htole64 276# define htole64(x) swap64(x) 277#endif 278#ifndef le16toh 279# define le16toh(x) swap16(x) 280#endif 281#ifndef le32toh 282# define le32toh(x) swap32(x) 283#endif 284#ifndef le64toh 285# define le64toh(x) swap64(x) 286#endif 287 288#ifndef htobe64 289# define htobe64(x) (x) 290#endif 291#ifndef be64toh 292# define be64toh(x) (x) 293#endif 294 295#define HTOLE16(x) (x) = htole16(x) 296#define HTOLE32(x) (x) = htole32(x) 297#define HTOLE64(x) (x) = htole64(x) 298#define LE16TOH(x) (x) = le16toh(x) 299#define LE32TOH(x) (x) = le32toh(x) 300#define LE64TOH(x) (x) = le64toh(x) 301 302#define HTOBE64(x) (void) (x) 303#define BE64TOH(x) (void) (x) 304 305EOF 306 else 307 cat >> "$1" << EOF 308/* On little endian machines, these macros are null */ 309#ifndef htole16 310# define htole16(x) (x) 311#endif 312#ifndef htole32 313# define htole32(x) (x) 314#endif 315#ifndef htole64 316# define htole64(x) (x) 317#endif 318#ifndef le16toh 319# define le16toh(x) (x) 320#endif 321#ifndef le32toh 322# define le32toh(x) (x) 323#endif 324#ifndef le64toh 325# define le64toh(x) (x) 326#endif 327 328#define HTOLE16(x) (void) (x) 329#define HTOLE32(x) (void) (x) 330#define HTOLE64(x) (void) (x) 331#define LE16TOH(x) (void) (x) 332#define LE32TOH(x) (void) (x) 333#define LE64TOH(x) (void) (x) 334 335/* These don't have standard aliases */ 336#ifndef htobe64 337# define htobe64(x) swap64(x) 338#endif 339#ifndef be64toh 340# define be64toh(x) swap64(x) 341#endif 342 343#define HTOBE64(x) (x) = htobe64(x) 344#define BE64TOH(x) (x) = be64toh(x) 345 346EOF 347 fi 348fi 349 350cat >> "$1" << EOF 351/* Define the C99 standard length-specific integer types */ 352#include <_stdint.h> 353 354EOF 355 356case "${effective_target}" in 357 i[3456]86-*) 358 cat >> "$1" << EOF 359/* Here are some macros to create integers from a byte array */ 360/* These are used to get and put integers from/into a uint8_t array */ 361/* with a specific endianness. This is the most portable way to generate */ 362/* and read messages to a network or serial device. Each member of a */ 363/* packet structure must be handled separately. */ 364 365/* The i386 and compatibles can handle unaligned memory access, */ 366/* so use the optimized macros above to do this job */ 367#ifndef be16atoh 368# define be16atoh(x) be16toh(*(uint16_t*)(x)) 369#endif 370#ifndef be32atoh 371# define be32atoh(x) be32toh(*(uint32_t*)(x)) 372#endif 373#ifndef be64atoh 374# define be64atoh(x) be64toh(*(uint64_t*)(x)) 375#endif 376#ifndef le16atoh 377# define le16atoh(x) le16toh(*(uint16_t*)(x)) 378#endif 379#ifndef le32atoh 380# define le32atoh(x) le32toh(*(uint32_t*)(x)) 381#endif 382#ifndef le64atoh 383# define le64atoh(x) le64toh(*(uint64_t*)(x)) 384#endif 385 386#ifndef htob16a 387# define htobe16a(a,x) *(uint16_t*)(a) = htobe16(x) 388#endif 389#ifndef htobe32a 390# define htobe32a(a,x) *(uint32_t*)(a) = htobe32(x) 391#endif 392#ifndef htobe64a 393# define htobe64a(a,x) *(uint64_t*)(a) = htobe64(x) 394#endif 395#ifndef htole16a 396# define htole16a(a,x) *(uint16_t*)(a) = htole16(x) 397#endif 398#ifndef htole32a 399# define htole32a(a,x) *(uint32_t*)(a) = htole32(x) 400#endif 401#ifndef htole64a 402# define htole64a(a,x) *(uint64_t*)(a) = htole64(x) 403#endif 404 405EOF 406 ;; 407 408 *) 409 cat >> "$1" << EOF 410/* Here are some macros to create integers from a byte array */ 411/* These are used to get and put integers from/into a uint8_t array */ 412/* with a specific endianness. This is the most portable way to generate */ 413/* and read messages to a network or serial device. Each member of a */ 414/* packet structure must be handled separately. */ 415 416/* Non-optimized but portable macros */ 417#define be16atoh(x) ((uint16_t)(((x)[0]<<8)|(x)[1])) 418#define be32atoh(x) ((uint32_t)(((x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])) 419#define be64atoh_x(x,off,shift) (((uint64_t)((x)[off]))<<shift) 420#define be64atoh(x) ((uint64_t)(be64atoh_x(x,0,56)|be64atoh_x(x,1,48)|be64atoh_x(x,2,40)| \\ 421 be64atoh_x(x,3,32)|be64atoh_x(x,4,24)|be64atoh_x(x,5,16)|be64atoh_x(x,6,8)|((x)[7]))) 422#define le16atoh(x) ((uint16_t)(((x)[1]<<8)|(x)[0])) 423#define le32atoh(x) ((uint32_t)(((x)[3]<<24)|((x)[2]<<16)|((x)[1]<<8)|(x)[0])) 424#define le64atoh_x(x,off,shift) (((uint64_t)(x)[off])<<shift) 425#define le64atoh(x) ((uint64_t)(le64atoh_x(x,7,56)|le64atoh_x(x,6,48)|le64atoh_x(x,5,40)| \\ 426 le64atoh_x(x,4,32)|le64atoh_x(x,3,24)|le64atoh_x(x,2,16)|le64atoh_x(x,1,8)|((x)[0]))) 427 428#define htobe16a(a,x) (a)[0]=(uint8_t)((x)>>8), (a)[1]=(uint8_t)(x) 429#define htobe32a(a,x) (a)[0]=(uint8_t)((x)>>24), (a)[1]=(uint8_t)((x)>>16), \\ 430 (a)[2]=(uint8_t)((x)>>8), (a)[3]=(uint8_t)(x) 431#define htobe64a(a,x) (a)[0]=(uint8_t)((x)>>56), (a)[1]=(uint8_t)((x)>>48), \\ 432 (a)[2]=(uint8_t)((x)>>40), (a)[3]=(uint8_t)((x)>>32), \\ 433 (a)[4]=(uint8_t)((x)>>24), (a)[5]=(uint8_t)((x)>>16), \\ 434 (a)[6]=(uint8_t)((x)>>8), (a)[7]=(uint8_t)(x) 435#define htole16a(a,x) (a)[1]=(uint8_t)((x)>>8), (a)[0]=(uint8_t)(x) 436#define htole32a(a,x) (a)[3]=(uint8_t)((x)>>24), (a)[2]=(uint8_t)((x)>>16), \\ 437 (a)[1]=(uint8_t)((x)>>8), (a)[0]=(uint8_t)(x) 438#define htole64a(a,x) (a)[7]=(uint8_t)((x)>>56), (a)[6]=(uint8_t)((x)>>48), \\ 439 (a)[5]=(uint8_t)((x)>>40), (a)[4]=(uint8_t)((x)>>32), \\ 440 (a)[3]=(uint8_t)((x)>>24), (a)[2]=(uint8_t)((x)>>16), \\ 441 (a)[1]=(uint8_t)((x)>>8), (a)[0]=(uint8_t)(x) 442 443EOF 444 ;; 445esac 446] 447 448cat >> "$1" << EOF 449#endif /*__BYTEORDER_H*/ 450EOF]) 451