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[
35changequote(, )dnl
36ac_dir=`echo $1|sed 's%/[^/][^/]*$%%'`
37changequote([, ])dnl
38if test "$ac_dir" != "$1" && test "$ac_dir" != .; then
39  # The file is in a subdirectory.
40  test ! -d "$ac_dir" && mkdir "$ac_dir"
41fi
42
43# We're only interested in the target CPU, but it's not always set
44effective_target="$target"
45if test "x$effective_target" = xNONE -o "x$effective_target" = x ; then
46	effective_target="$host"
47fi
48AC_SUBST(effective_target)
49
50cat > "$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
57EOF
58
59dnl First, do an endian check
60AC_C_BIGENDIAN
61
62dnl Look for NetBSD-style extended byte swapping macros
63AC_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
69EOF],
70
71[
72
73dnl Look for standard byte swapping macros
74AC_HAVE_SYMBOL(ntohl,arpa/inet.h,
75 [cat >> "$1" << EOF
76/* ntohl and relatives live here */
77#include <arpa/inet.h>
78
79EOF],
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
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#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
192EOF
193	fi
194])
195  	  ])
196    ])
197  ])
198])
199
200
201[
202if 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
230EOF
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
251EOF
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
276EOF
277 fi
278fi
279
280cat >> "$1" << EOF
281/* Define the C99 standard length-specific integer types */
282#include <_stdint.h>
283
284EOF
285
286case "${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
311EOF
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
347EOF
348  ;;
349esac
350]
351
352cat >> "$1" << EOF
353#endif /*__BYTEORDER_H*/
354EOF])
355