Home | History | Annotate | Download | only in m4
      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 ac_dir=`AS_DIRNAME(["$1"])`
     36 if 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"])
     39 fi
     40 
     41 # We're only interested in the target CPU, but it's not always set
     42 effective_target="$target"
     43 if test "x$effective_target" = xNONE -o "x$effective_target" = x ; then
     44 	effective_target="$host"
     45 fi
     46 AC_SUBST(effective_target)
     47 
     48 cat > "$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 
     55 EOF
     56 
     57 dnl First, do an endian check
     58 AC_C_BIGENDIAN
     59 
     60 dnl Look for NetBSD-style extended byte swapping macros
     61 AC_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 
     67 EOF],
     68 
     69 [
     70 
     71 dnl Look for standard byte swapping macros
     72 AC_HAVE_SYMBOL(ntohl,arpa/inet.h,
     73  [cat >> "$1" << EOF
     74 /* ntohl and relatives live here */
     75 #include <arpa/inet.h>
     76 
     77 EOF],
     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 
     84 EOF],true)])
     85 ])
     86 
     87 dnl Look for generic byte swapping macros
     88 
     89 dnl OpenBSD
     90 AC_HAVE_SYMBOL(swap32,machine/endian.h,
     91  [cat >> "$1" << EOF
     92 /* swap32 and swap16 are defined in machine/endian.h */
     93 
     94 EOF],
     95 
     96  [
     97 dnl 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 
    106 EOF],
    107 
    108    [
    109 dnl 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 */
    114 EOF
    115 	if test "$HAVE_LE32TOH" != "1"; then
    116 		echo '#include <machine/endian.h>'>> "$1"
    117 	fi
    118 cat >> "$1" << EOF
    119 #define swap16(x) bswap16(x)
    120 #define swap32(x) bswap32(x)
    121 #define swap64(x) bswap64(x)
    122 
    123 EOF],
    124 
    125    [
    126 dnl 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 
    143 EOF],
    144 
    145   	 [
    146 dnl 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 
    155 EOF],
    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 
    174 EOF
    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 
    190 EOF
    191 	fi
    192 ])
    193   	  ])
    194     ])
    195   ])
    196 ])
    197 
    198 
    199 [
    200 if 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 
    236 EOF
    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 
    273 EOF
    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 
    314 EOF
    315  fi
    316 fi
    317 
    318 cat >> "$1" << EOF
    319 /* Define the C99 standard length-specific integer types */
    320 #include <_stdint.h>
    321 
    322 EOF
    323 
    324 case "${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 
    373 EOF
    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 
    411 EOF
    412   ;;
    413 esac
    414 ]
    415 
    416 cat >> "$1" << EOF
    417 #endif /*__BYTEORDER_H*/
    418 EOF])
    419