blob: e342be5d0c7a53cbd7d1badd64ca102092f3445c [file] [log] [blame]
Linus Walleijb9256fd2006-02-15 09:40:43 +00001dnl AC_NEED_BYTEORDER_H ( HEADER-TO-GENERATE )
Linus Walleijb9256fd2006-02-15 09:40:43 +00002dnl 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[
Linus Walleij960ebb62007-08-03 21:38:34 +000035ac_dir=`AS_DIRNAME(["$1"])`
Linus Walleijb9256fd2006-02-15 09:40:43 +000036if test "$ac_dir" != "$1" && test "$ac_dir" != .; then
37 # The file is in a subdirectory.
Linus Walleij09342b62011-10-22 00:25:49 +020038 test ! -d "$ac_dir" && (AS_MKDIR_P(["$ac_dir"]))
Linus Walleijb9256fd2006-02-15 09:40:43 +000039fi
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
77EOF],
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
84EOF],true)])
85])
86
87dnl Look for generic byte swapping macros
88
89dnl OpenBSD
90AC_HAVE_SYMBOL(swap32,machine/endian.h,
91 [cat >> "$1" << EOF
92/* swap32 and swap16 are defined in machine/endian.h */
93
94EOF],
95
96 [
97dnl 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
106EOF],
107
108 [
109dnl 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 */
114EOF
115 if test "$HAVE_LE32TOH" != "1"; then
116 echo '#include <machine/endian.h>'>> "$1"
117 fi
118cat >> "$1" << EOF
119#define swap16(x) bswap16(x)
120#define swap32(x) bswap32(x)
121#define swap64(x) bswap64(x)
122
123EOF],
124
125 [
126dnl 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
143EOF],
144
145 [
146dnl 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
155EOF],
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
174EOF
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
190EOF
191 fi
192])
193 ])
194 ])
195 ])
196])
197
198
199[
200if 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 */
Linus Walleij2a84ca42008-12-14 00:00:23 +0000218#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
Linus Walleijb9256fd2006-02-15 09:40:43 +0000230
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
236EOF
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 */
Linus Walleij2a84ca42008-12-14 00:00:23 +0000241#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
Linus Walleijb9256fd2006-02-15 09:40:43 +0000256
Linus Walleij2a84ca42008-12-14 00:00:23 +0000257#ifndef htobe64
258# define htobe64(x) (x)
259#endif
260#ifndef be64toh
261# define be64toh(x) (x)
262#endif
Linus Walleijb9256fd2006-02-15 09:40:43 +0000263
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)
Linus Walleij960ebb62007-08-03 21:38:34 +0000268#define LE64TOH(x) (x) = le64toh(x)
Linus Walleijb9256fd2006-02-15 09:40:43 +0000269
270#define HTOBE64(x) (void) (x)
271#define BE64TOH(x) (void) (x)
272
273EOF
274 else
275 cat >> "$1" << EOF
276/* On little endian machines, these macros are null */
Linus Walleij2a84ca42008-12-14 00:00:23 +0000277#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
Linus Walleijb9256fd2006-02-15 09:40:43 +0000295
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 */
Linus Walleij2a84ca42008-12-14 00:00:23 +0000304#ifndef htobe64
305# define htobe64(x) swap64(x)
306#endif
307#ifndef be64toh
308# define be64toh(x) swap64(x)
309#endif
Linus Walleijb9256fd2006-02-15 09:40:43 +0000310
311#define HTOBE64(x) (x) = htobe64(x)
312#define BE64TOH(x) (x) = be64toh(x)
313
314EOF
315 fi
316fi
317
318cat >> "$1" << EOF
319/* Define the C99 standard length-specific integer types */
Linus Walleij2a84ca42008-12-14 00:00:23 +0000320#include <_stdint.h>
Linus Walleijb9256fd2006-02-15 09:40:43 +0000321
322EOF
323
324case "${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 */
Linus Walleij2a84ca42008-12-14 00:00:23 +0000335#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
Linus Walleijb9256fd2006-02-15 09:40:43 +0000353
Linus Walleij2a84ca42008-12-14 00:00:23 +0000354#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
Linus Walleijb9256fd2006-02-15 09:40:43 +0000372
373EOF
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]))
Linus Walleij960ebb62007-08-03 21:38:34 +0000387#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])))
Linus Walleijb9256fd2006-02-15 09:40:43 +0000390#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]))
Linus Walleij960ebb62007-08-03 21:38:34 +0000392#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])))
Linus Walleijb9256fd2006-02-15 09:40:43 +0000395
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
411EOF
412 ;;
413esac
414]
415
416cat >> "$1" << EOF
417#endif /*__BYTEORDER_H*/
418EOF])