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