This repository has been archived by the owner on Jan 24, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 88
/
Copy pathtypes.h
160 lines (152 loc) · 5.57 KB
/
types.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/*
* Copyright (C) 2017 - This file is part of libecc project
*
* Authors:
* Ryad BENADJILA <[email protected]>
* Arnaud EBALARD <[email protected]>
* Jean-Pierre FLORI <[email protected]>
*
* Contributors:
* Nicolas VIVET <[email protected]>
* Karim KHALFALLAH <[email protected]>
*
* This software is licensed under a dual BSD and GPL v2 license.
* See LICENSE file at the root folder of the project.
*/
#ifndef __TYPES_H__
#define __TYPES_H__
/*** Handling the target compiler and its specificities ***/
#ifdef __GNUC__
/* gcc and clang */
#define ATTRIBUTE_UNUSED __attribute__((unused))
#define ATTRIBUTE_USED __attribute__((used))
#define ATTRIBUTE_PACKED __attribute__((packed))
#define ATTRIBUTE_SECTION(a) __attribute__((__section__((a))))
#ifdef USE_WARN_UNUSED_RET
#define ATTRIBUTE_WARN_UNUSED_RET __attribute__((warn_unused_result))
static inline void ignore_result(int unused_result) {
(void) unused_result;
}
/* NOTE: this trick using a dummy function call is here
* to explicitly avoid "unused return values" when we know
* what we are doing!
*/
#define IGNORE_RET_VAL(a) ignore_result((int)(a))
#else
#define ATTRIBUTE_WARN_UNUSED_RET
#define IGNORE_RET_VAL(a) (a)
#endif /* USE_WARN_UNUSED_RET */
#else
#define ATTRIBUTE_UNUSED
#define ATTRIBUTE_USED
#define ATTRIBUTE_PACKED
#define ATTRIBUTE_SECTION(a)
#define ATTRIBUTE_WARN_UNUSED_RET
#define IGNORE_RET_VAL(a) (a)
#endif
/* Macro to trick the compiler of thinking a variable is used.
* Although this should not happen, sometimes because of #define
* oddities we might force this.
*/
#define FORCE_USED_VAR(a) ((void)(a))
/*** Handling the types ****/
#ifdef WITH_STDLIB
/*
* User explicitly needs to build w/ stdlib. Let's include the headers
* we need to get basic types: (uint*_t), NULL, etc. You can see below
* (i.e. under #else) what is precisely needed.
*/
#include <stdint.h>
#include <stddef.h>
#else /* WITH_STDLIB */
/*
* User does not want to build w/ stdlib. Let's define basic types:
* (uint*_t), NULL, etc.
*/
#define NULL ((void *)0)
typedef unsigned int size_t;
typedef int ssize_t;
/* Here is the big picture of the main programming models
* and their primitive types sizes in bits:
* (see http://www.unix.org/whitepapers/64bit.html)
*
* | LP32 | ILP32 | LLP64 | ILP64 | LP64 |
* ---------------------------------------
* char | 8 | 8 | 8 | 8 | 8 |
* short | 16 | 16 | 16 | 16 | 16 |
* int | 16 | 32 | 32 | 64 | 32 |
* long | 32 | 32 | 32 | 64 | 64 |
* long long| 64 | 64 | 64 | 64 | 64 |
* --------------------------------------
* (long long type existence depends on the C compiler
* but should be *mandatory* in C99 compliant ones)
*
* This means that:
* 1) We are sure that long long are 64-bit, short are 16-bit,
* and char are 8-bit (on the vast majority of platforms).
* 2) The two types that are not consistent across platforms are
* the int and long types (e.g., int is 16 bits and long is 32 bits
* on msp430-gcc LP32, while int is 32 bits and long is 32 bits
* on x86_64 Linux platforms LLP64, and long becomes 64 bits on
* x86_64 Windows platforms LP64).
*
* Hence, we take a wild guess for uint32_t mapping on a primitive type
* and check this at compilation time using the check_data_types 'union'
* defined below.
* Our guess depends on the WORDSIZE the user provides us, since we assume
* this corresponds to a 'native' word size of the platform (8-bit platforms
* such as AVR and 16-bit platforms such as MSP430 are either LP32 and ILP32,
* which means that a 'long' type will be mapped to a 32 bits native type).
* Consequently, when the user provides us a WORDSIZE=16, we infer that
* uint32_t is mapped on a long type.
*
*/
typedef unsigned long long uint64_t;
/* GCC defines the size of an int, use this information
* if it is provided
*/
#ifdef __SIZEOF_INT__
#if(__SIZEOF_INT__ == 2)
typedef unsigned long uint32_t;
#else
typedef unsigned int uint32_t;
#endif /* (__SIZEOF_INT__ == 2) */
#else
#if(WORDSIZE == 16)
/* The user has provided WORDSIZE=16, so we guess that
* we have LP32 or ILP32: a long type would be 32-bit.
*/
typedef unsigned long uint32_t;
#else
/* Wild guess for uint32_t mapping */
typedef unsigned int uint32_t;
#endif /* (WORDSIZE == 16) */
#endif /* __SIZEOF_INT__ */
typedef unsigned short uint16_t;
typedef unsigned char uint8_t;
/* Useful macros for our new defined types */
#define UINT8_MAX (0xff)
#define UINT16_MAX (0xffff)
#define UINT32_MAX (0xffffffff)
#define UINT64_MAX (0xffffffffffffffffULL)
#define UINT8_C(c) ((uint8_t)(c ## UL))
#define UINT16_C(c) ((uint16_t)(c ## UL))
#define UINT32_C(c) ((uint32_t)(c ## UL))
#define UINT64_C(c) (c ## ULL)
/* Sanity check on our guess for primitive types sizes.
* See https://barrgroup.com/Embedded-Systems/How-To/C-Fixed-Width-Integers-C99
*
* TODO: if you get a compilation error at this point, this means that we failed
* at guessing the C primitive types sizes for the current platform. You should
* try to adapt the uint8_t/uint16_t/uint32_t/uint64_t types definitions in this
* file, or find the C99 compliant stdint headers for your compiler/platform
* and include it.
*/
typedef union {
char uint8_t_incorrect[sizeof(uint8_t) == 1 ? 1 : -1];
char uint16_t_incorrect[sizeof(uint16_t) == 2 ? 1 : -1];
char uint32_t_incorrect[sizeof(uint32_t) == 4 ? 1 : -1];
char uint64_t_incorrect[sizeof(uint64_t) == 8 ? 1 : -1];
} check_data_types;
#endif /* WITH_STDLIB */
#endif /* __TYPES_H__ */