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