1 dnl AC_NEED_BYTEORDER_H ( HEADER-TO-GENERATE ) 2 dnl Copyright 2001-2002 by Dan Fandrich <dan (a] coneharvesters.com> 3 dnl This file may be copied and used freely without restrictions. No warranty 4 dnl is expressed or implied. 5 dnl 6 dnl Create a header file that guarantees that byte swapping macros of the 7 dnl ntohl variety as well as the extended types included in OpenBSD and 8 dnl NetBSD such as le32toh are defined. If possible, the standard ntohl 9 dnl are overloaded as they are optimized for the given platform, but when 10 dnl this is not possible (e.g. on a big-endian machine) they are defined 11 dnl in this file. 12 13 dnl Look for a symbol in a header file 14 dnl AC_HAVE_SYMBOL ( IDENTIFIER, HEADER-FILE, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND ) 15 AC_DEFUN([AC_HAVE_SYMBOL], 16 [ 17 AC_MSG_CHECKING(for $1 in $2) 18 AC_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 32 dnl Create a header file that defines extended byte swapping macros 33 AC_DEFUN([AC_NEED_BYTEORDER_H], 34 [ 35 changequote(, )dnl 36 ac_dir=`echo $1|sed 's%/[^/][^/]*$%%'` 37 changequote([, ])dnl 38 if test "$ac_dir" != "$1" && test "$ac_dir" != .; then 39 # The file is in a subdirectory. 40 test ! -d "$ac_dir" && mkdir "$ac_dir" 41 fi 42 43 # We're only interested in the target CPU, but it's not always set 44 effective_target="$target" 45 if test "x$effective_target" = xNONE -o "x$effective_target" = x ; then 46 effective_target="$host" 47 fi 48 AC_SUBST(effective_target) 49 50 cat > "$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 57 EOF 58 59 dnl First, do an endian check 60 AC_C_BIGENDIAN 61 62 dnl Look for NetBSD-style extended byte swapping macros 63 AC_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 69 EOF], 70 71 [ 72 73 dnl Look for standard byte swapping macros 74 AC_HAVE_SYMBOL(ntohl,arpa/inet.h, 75 [cat >> "$1" << EOF 76 /* ntohl and relatives live here */ 77 #include <arpa/inet.h> 78 79 EOF], 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 86 EOF],true)]) 87 ]) 88 89 dnl Look for generic byte swapping macros 90 91 dnl OpenBSD 92 AC_HAVE_SYMBOL(swap32,machine/endian.h, 93 [cat >> "$1" << EOF 94 /* swap32 and swap16 are defined in machine/endian.h */ 95 96 EOF], 97 98 [ 99 dnl 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 108 EOF], 109 110 [ 111 dnl 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 */ 116 EOF 117 if test "$HAVE_LE32TOH" != "1"; then 118 echo '#include <machine/endian.h>'>> "$1" 119 fi 120 cat >> "$1" << EOF 121 #define swap16(x) bswap16(x) 122 #define swap32(x) bswap32(x) 123 #define swap64(x) bswap64(x) 124 125 EOF], 126 127 [ 128 dnl 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 145 EOF], 146 147 [ 148 dnl 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 157 EOF], 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 176 EOF 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 192 EOF 193 fi 194 ]) 195 ]) 196 ]) 197 ]) 198 ]) 199 200 201 [ 202 if 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 230 EOF 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 251 EOF 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 276 EOF 277 fi 278 fi 279 280 cat >> "$1" << EOF 281 /* Define the C99 standard length-specific integer types */ 282 #include <_stdint.h> 283 284 EOF 285 286 case "${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 311 EOF 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 347 EOF 348 ;; 349 esac 350 ] 351 352 cat >> "$1" << EOF 353 #endif /*__BYTEORDER_H*/ 354 EOF]) 355