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