Browse code

- an attempt at portable endianness macros: __IS_LITTLE_ENDIAN, __IS_BIG_ENDIAN and runtime check/sanity functions

Andrei Pelinescu-Onciul authored on 13/06/2008 20:09:54
Showing 3 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,45 @@
0
+/* 
1
+ * $Id$
2
+ * 
3
+ * Copyright (C) 2008 iptelorg GmbH
4
+ *
5
+ * Permission to use, copy, modify, and distribute this software for any
6
+ * purpose with or without fee is hereby granted, provided that the above
7
+ * copyright notice and this permission notice appear in all copies.
8
+ *
9
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
+ */
17
+/*
18
+ *  endianness compile and runtime  tests
19
+ * 
20
+ * History:
21
+ * --------
22
+ *  2008-06-13  created by andrei
23
+ */
24
+
25
+#include "endianness.h"
26
+
27
+int _endian_test_int=1 /* used for the runtime endian tests */;
28
+
29
+
30
+/* return 0 on success, -1 on error (compile time detected endianness is
31
+ * different from run time)
32
+ */
33
+int endianness_sanity_check()
34
+{
35
+#ifdef __IS_LITTLE_ENDIAN
36
+	return is_little_endian()-1;
37
+#elif defined __IS_BIG_ENDIAN
38
+	return is_big_endian()-1;
39
+#else
40
+#warning BUG: endianness macro are not defined
41
+	return -1;
42
+#endif
43
+}
44
+
0 45
new file mode 100644
... ...
@@ -0,0 +1,140 @@
0
+/* 
1
+ * $Id$
2
+ * 
3
+ * Copyright (C) 2008 iptelorg GmbH
4
+ *
5
+ * Permission to use, copy, modify, and distribute this software for any
6
+ * purpose with or without fee is hereby granted, provided that the above
7
+ * copyright notice and this permission notice appear in all copies.
8
+ *
9
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
+ */
17
+/*
18
+ *  endianness compile and runtime  tests
19
+ * 
20
+ * History:
21
+ * --------
22
+ *  2008-06-13  created by andrei
23
+ */
24
+
25
+/*
26
+ * Defines:
27
+ *    __IS_LITTLE_ENDIAN if the system is little endian and
28
+ *    __IS_BIG_ENDIAN    if it's big endian
29
+ * Function/macros:
30
+ *     is_big_endian()  - runtime test for big endian
31
+ *     is_little_endian() - runtime test for little endian
32
+ *     endianness_sanity_check() - returns 0 if the compile time
33
+ *                                  detected endianness corresponds to
34
+ *                                  the runtime detected one and -1 on 
35
+ *                                  error (recommended action: bail out)
36
+ */
37
+/*
38
+ * Implementation notes:
39
+ * Endian macro names/tests for different OSes:
40
+ * linux:  __BYTE_ORDER == __LITTLE_ENDIAN | __BIG_ENDIAN
41
+ *           BYTE_ORDER == LITTLE_ENDIAN | BIG_ENDIAN
42
+ * bsd:     _BYTE_ORDER == _LITTLE_ENDIAN | _BIG_ENDIAN
43
+ *           BYTE_ORDER == LITTLE_ENDIAN | BIG_ENDIAN
44
+ * solaris: _LITTLE_ENDIAN | _BIG_ENDIAN
45
+ *
46
+ * Include file for the endian macros:
47
+ * linux: <endian.h> (glibc), <sys/param.h>
48
+ * bsd:   <sys/param.h>, <sys/endian.h>
49
+ * solaris: <sys/param.h>
50
+ *
51
+ * Note: BIG_ENDIAN, LITTLE_ENDIAN, _BIG_ENDIAN, _LITTLE_ENDIAN cannot be 
52
+ *       used always,  some OSes define both of them for BYTE_ORDER use
53
+ *       (e.g. linux defines both BIG_ENDIAN & LITTLE_ENDIAN, bsds define
54
+ *          _BIG_ENDIAN, _LITTLE_ENDIAN, BIG_ENDIAN, LITTLE_ENDIAN)
55
+ *
56
+ */
57
+
58
+
59
+#ifndef _endianness_h
60
+#define _endianness_h
61
+
62
+/* use bsd includes: they work everywhere */
63
+#include <sys/types.h>
64
+#include <sys/param.h>
65
+
66
+
67
+
68
+extern int _endian_test_int;
69
+
70
+/* returns 1 for little endian, 0 for big endian */
71
+#define endian_test()		(*(char*)&_endian_test_int==1)
72
+#define is_big_endian()		(!endian_test())
73
+#define is_little_endian()	endian_test()
74
+
75
+
76
+extern int endianness_sanity_check();
77
+
78
+/* detect compile time endianess */
79
+#if defined __BYTE_ORDER && defined __LITTLE_ENDIAN && defined __BIG_ENDIAN
80
+/* linux */
81
+#if __BYTE_ORDER == __LITTLE_ENDIAN && ! defined __IS_LITTLE_ENDIAN
82
+	#define __IS_LITTLE_ENDIAN 0x01020304
83
+#endif
84
+#if __BYTE_ORDER == __BIG_ENDIAN && ! defined __IS_BIG_ENDIAN
85
+	#define __IS_BIG_ENDIAN 0x01020304
86
+#endif
87
+#elif defined _BYTE_ORDER && defined _LITTLE_ENDIAN && defined _BIG_ENDIAN
88
+/* bsd */
89
+#if _BYTE_ORDER == _LITTLE_ENDIAN && ! defined __IS_LITTLE_ENDIAN
90
+	#define __IS_LITTLE_ENDIAN 0x01020304
91
+#endif
92
+#if _BYTE_ORDER == _BIG_ENDIAN && ! defined __IS_BIG_ENDIAN
93
+	#define __IS_BIG_ENDIAN 0x01020304
94
+#endif
95
+#elif defined BYTE_ORDER && defined LITTLE_ENDIAN && defined BIG_ENDIAN
96
+/* bsd old/deprecated */
97
+#if BYTE_ORDER == LITTLE_ENDIAN && ! defined __IS_LITTLE_ENDIAN
98
+	#define __IS_LITTLE_ENDIAN 0x01020304
99
+#endif
100
+#if BYTE_ORDER == BIG_ENDIAN && ! defined __IS_BIG_ENDIAN
101
+	#define __IS_BIG_ENDIAN 0x01020304
102
+#endif
103
+#elif !(defined _LITTLE_ENDIAN && defined _BIG_ENDIAN) && \
104
+		(defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)
105
+/* OSes that don't define BYTE_ORDER (sanity check above makes sure
106
+ *   little & big endian are not defined in the same time )*/
107
+/* solaris */
108
+#if defined _LITTLE_ENDIAN && !defined __IS_LITLE_ENDIAN
109
+	#define __IS_LITTLE_ENDIAN 0x01020304
110
+#endif
111
+#if defined _BIG_ENDIAN && !defined __IS_BIG_ENDIAN
112
+	#define __IS_BIG_ENDIAN 0x04030201
113
+#endif
114
+#elif !(defined LITTLE_ENDIAN && defined BIG_ENDIAN) && \
115
+		(defined LITTLE_ENDIAN || defined BIG_ENDIAN)
116
+/* OSes that don't define BYTE_ORDER (sanity check above makes sure
117
+ *   little & big endian are not defined in the same time )*/
118
+#if defined LITTLE_ENDIAN && !defined __IS_LITLE_ENDIAN
119
+	#define __IS_LITTLE_ENDIAN 0x01020304
120
+#endif
121
+#if defined BIG_ENDIAN && !defined __IS_BIG_ENDIAN
122
+	#define __IS_BIG_ENDIAN 0x04030201
123
+#endif
124
+
125
+#else
126
+#error could not detect endianess
127
+#endif
128
+
129
+#if !defined __IS_LITTLE_ENDIAN && !defined __IS_BIG_ENDIAN
130
+#error BUG: could not detect endianess
131
+#endif
132
+
133
+#if defined __IS_LITTLE_ENDIAN && defined __IS_BIG_ENDIAN
134
+#error BUG: both little & big endian detected in the same time
135
+#endif
136
+
137
+
138
+#endif /* _endianness_h */
139
+
0 140
new file mode 100644
... ...
@@ -0,0 +1,173 @@
0
+/* 
1
+ * $Id$
2
+ * 
3
+ * Copyright (C) 2008 iptelorg GmbH
4
+ *
5
+ * Permission to use, copy, modify, and distribute this software for any
6
+ * purpose with or without fee is hereby granted, provided that the above
7
+ * copyright notice and this permission notice appear in all copies.
8
+ *
9
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
+ */
17
+/*
18
+ *  endianness.h tests
19
+ *  compile/run with:
20
+ *  gcc  -Wall endian_test.c ../endianness.c  -o endian_test; ./endian_test
21
+ */
22
+/* 
23
+ * History:
24
+ * --------
25
+ *  2008-06-13  created by andrei
26
+ */
27
+
28
+/*
29
+ *
30
+ * Macro names:
31
+ * linux:  __BYTE_ORDER == __LITTLE_ENDIAN | __BIG_ENDIAN
32
+ *           BYTE_ORDER == LITTLE_ENDIAN | BIG_ENDIAN
33
+ * bsd:     _BYTE_ORDER == _LITTLE_ENDIAN | _BIG_ENDIAN
34
+ *           BYTE_ORDER == LITTLE_ENDIAN | BIG_ENDIAN
35
+ * solaris: _LITTLE_ENDIAN | _BIG_ENDIAN
36
+ *
37
+ * Note: BIG_ENDIAN, LITTLE_ENDIAN, _BIG_ENDIAN, _LITTLE_ENDIAN cannot be 
38
+ *       used always,  some OSes define both of them for BYTE_ORDER use
39
+ *       (e.g. linux defines both BIG_ENDIAN & LITTLE_ENDIAN, bsds define
40
+ *          _BIG_ENDIAN, _LITTLE_ENDIAN, BIG_ENDIAN, LITTLE_ENDIAN)
41
+ *
42
+ * is sys/param.h universal ?
43
+ */
44
+
45
+#include <stdio.h>
46
+#include "../endianness.h"
47
+/* 
48
+ * Tested:
49
+ * linux:   y
50
+ * freebsd: y
51
+ * openbsd:
52
+ * netbsd:
53
+ * solaris: y
54
+ * darwin: 
55
+ * cygwin:
56
+ *
57
+ * Header files:
58
+ * linux:  <endian.h> , <sys/param.h>
59
+ * bsd:    <sys/param.h> or <sys/endian.h>
60
+ * solaris: <sys/param.h>
61
+ * openbsd
62
+ * netbsd
63
+ * solaris
64
+ * cywin
65
+ */
66
+
67
+/*
68
+ *
69
+ * Macro names:
70
+ * linux:  __BYTE_ORDER == __LITTLE_ENDIAN | __BIG_ENDIAN
71
+ *           BYTE_ORDER == LITTLE_ENDIAN | BIG_ENDIAN
72
+ * bsd:     _BYTE_ORDER == _LITTLE_ENDIAN | _BIG_ENDIAN
73
+ *           BYTE_ORDER == LITTLE_ENDIAN | BIG_ENDIAN
74
+ * solaris: _LITTLE_ENDIAN | _BIG_ENDIAN
75
+ *
76
+ * Note: BIG_ENDIAN, LITTLE_ENDIAN, _BIG_ENDIAN, _LITTLE_ENDIAN cannot be 
77
+ *       used always,  some OSes define both of them for BYTE_ORDER use
78
+ *       (e.g. linux defines both BIG_ENDIAN & LITTLE_ENDIAN, bsds define
79
+ *          _BIG_ENDIAN, _LITTLE_ENDIAN, BIG_ENDIAN, LITTLE_ENDIAN)
80
+ *
81
+ * is sys/param.h universal ?
82
+ */
83
+
84
+/* test only */
85
+#if defined __BYTE_ORDER && defined __LITTLE_ENDIAN 
86
+#if	__BYTE_ORDER == __LITTLE_ENDIAN
87
+#warning little endian (via __BYTE_ORDER)
88
+#define __BYTE_ORDER_FOUND
89
+#endif
90
+#endif
91
+#if defined __BYTE_ORDER && defined __BIG_ENDIAN
92
+#if	__BYTE_ORDER == __BIG_ENDIAN
93
+#warning big endian (via __BYTE_ORDER)
94
+#define __BYTE_ORDER_FOUND
95
+#endif
96
+#endif
97
+#if defined __BYTE_ORDER && !defined __BYTE_ORDER_FOUND
98
+#error __BYTE_ORDER defined, but w/ a strange value
99
+#endif
100
+
101
+#if defined _BYTE_ORDER && defined _LITTLE_ENDIAN
102
+#if _BYTE_ORDER == _LITTLE_ENDIAN
103
+#warning little endian (via _BYTE_ORDER)
104
+#define _BYTE_ORDER_FOUND
105
+#endif
106
+#endif
107
+#if defined _BYTE_ORDER && defined _BIG_ENDIAN 
108
+#if _BYTE_ORDER == _BIG_ENDIAN
109
+#warning big endian (via _BYTE_ORDER)
110
+#define _BYTE_ORDER_FOUND
111
+#endif
112
+#endif
113
+#if defined _BYTE_ORDER && !defined _BYTE_ORDER_FOUND
114
+#error _BYTE_ORDER defined, but w/ a strange value
115
+#endif
116
+
117
+#if defined BYTE_ORDER && defined LITTLE_ENDIAN 
118
+#if BYTE_ORDER == LITTLE_ENDIAN
119
+#warning little endian (via BYTE_ORDER)
120
+#define BYTE_ORDER_FOUND
121
+#endif
122
+#endif
123
+#if defined BYTE_ORDER && defined BIG_ENDIAN 
124
+#if BYTE_ORDER == BIG_ENDIAN
125
+#warning big endian (via BYTE_ORDER)
126
+#define BYTE_ORDER_FOUND
127
+#endif
128
+#endif
129
+#if defined BYTE_ORDER && !defined BYTE_ORDER_FOUND
130
+#error BYTE_ORDER defined, but w/ a strange value
131
+#endif
132
+
133
+#if defined _LITTLE_ENDIAN
134
+#warning _LITTLE_ENDIAN defined
135
+#endif
136
+#if defined _BIG_ENDIAN
137
+#warning _BIG_ENDIAN defined
138
+#endif
139
+#if defined LITTLE_ENDIAN
140
+#warning LITTLE_ENDIAN defined
141
+#endif
142
+#if defined BIG_ENDIAN
143
+#warning BIG_ENDIAN defined
144
+#endif
145
+
146
+
147
+int main(int argc, char** argv)
148
+{
149
+	int ret;
150
+	
151
+	ret=0;
152
+	if (endianness_sanity_check()!=0){
153
+		printf("ERROR: sanity checks failed\n");
154
+		ret=-1;
155
+	}
156
+	if (is_little_endian()){
157
+#ifdef __IS_LITTLE_ENDIAN
158
+		printf("OK: little endian confirmed\n");
159
+#else 
160
+		printf("ERROR: macro claims BIG ENDIAN, but it's little\n");
161
+		return -1;
162
+#endif
163
+	}else{
164
+#ifdef __IS_BIG_ENDIAN
165
+		printf("OK: big endian confirmed\n");
166
+#else 
167
+		printf("ERROR: macro claims LITTLE ENDIAN, but it's big\n");
168
+		return -1;
169
+#endif
170
+	}
171
+	return ret;
172
+}