1 // SPDX-License-Identifier: 0BSD 2 3 /////////////////////////////////////////////////////////////////////////////// 4 // 5 /// \file sysdefs.h 6 /// \brief Common includes, definitions, system-specific things etc. 7 /// 8 /// This file is used also by the lzma command line tool, that's why this 9 /// file is separate from common.h. 10 // 11 // Author: Lasse Collin 12 // 13 /////////////////////////////////////////////////////////////////////////////// 14 15 #ifndef LZMA_SYSDEFS_H 16 #define LZMA_SYSDEFS_H 17 18 ////////////// 19 // Includes // 20 ////////////// 21 22 #ifdef HAVE_CONFIG_H 23 # include <config.h> 24 #endif 25 26 // Choose if MinGW-w64's stdio replacement functions should be used. 27 // The default has varied slightly in the past so it's clearest to always 28 // set it explicitly. 29 // 30 // Modern MinGW-w64 enables the replacement functions even with UCRT 31 // when _GNU_SOURCE is defined. That's good because UCRT doesn't support 32 // the POSIX thousand separator flag in printf (like "%'u"). Otherwise 33 // XZ Utils works with the UCRT stdio functions. 34 // 35 // The replacement functions add over 20 KiB to each executable. For 36 // size-optimized builds (HAVE_SMALL), disable the replacements. 37 // Then thousand separators aren't shown in xz's messages but this is 38 // a minor downside compare to the slower speed of the HAVE_SMALL builds. 39 // 40 // The legacy MSVCRT is pre-C99 and it's best to always use the stdio 41 // replacements functions from MinGW-w64. 42 #if defined(__MINGW32__) && !defined(__USE_MINGW_ANSI_STDIO) 43 # define __USE_MINGW_ANSI_STDIO 1 44 # include <_mingw.h> 45 # if defined(_UCRT) && defined(HAVE_SMALL) 46 # undef __USE_MINGW_ANSI_STDIO 47 # define __USE_MINGW_ANSI_STDIO 0 48 # endif 49 #endif 50 51 // size_t and NULL 52 #include <stddef.h> 53 54 #ifdef HAVE_INTTYPES_H 55 # include <inttypes.h> 56 #endif 57 58 // C99 says that inttypes.h always includes stdint.h, but some systems 59 // don't do that, and require including stdint.h separately. 60 #ifdef HAVE_STDINT_H 61 # include <stdint.h> 62 #endif 63 64 // Some pre-C99 systems have SIZE_MAX in limits.h instead of stdint.h. The 65 // limits are also used to figure out some macros missing from pre-C99 systems. 66 #include <limits.h> 67 68 // Be more compatible with systems that have non-conforming inttypes.h. 69 // We assume that int is 32-bit and that long is either 32-bit or 64-bit. 70 // Full Autoconf test could be more correct, but this should work well enough. 71 // Note that this duplicates some code from lzma.h, but this is better since 72 // we can work without inttypes.h thanks to Autoconf tests. 73 #ifndef UINT32_C 74 # if UINT_MAX != 4294967295U 75 # error UINT32_C is not defined and unsigned int is not 32-bit. 76 # endif 77 # define UINT32_C(n) n ## U 78 #endif 79 #ifndef UINT32_MAX 80 # define UINT32_MAX UINT32_C(4294967295) 81 #endif 82 #ifndef PRIu32 83 # define PRIu32 "u" 84 #endif 85 #ifndef PRIx32 86 # define PRIx32 "x" 87 #endif 88 #ifndef PRIX32 89 # define PRIX32 "X" 90 #endif 91 92 #if ULONG_MAX == 4294967295UL 93 # ifndef UINT64_C 94 # define UINT64_C(n) n ## ULL 95 # endif 96 # ifndef PRIu64 97 # define PRIu64 "llu" 98 # endif 99 # ifndef PRIx64 100 # define PRIx64 "llx" 101 # endif 102 # ifndef PRIX64 103 # define PRIX64 "llX" 104 # endif 105 #else 106 # ifndef UINT64_C 107 # define UINT64_C(n) n ## UL 108 # endif 109 # ifndef PRIu64 110 # define PRIu64 "lu" 111 # endif 112 # ifndef PRIx64 113 # define PRIx64 "lx" 114 # endif 115 # ifndef PRIX64 116 # define PRIX64 "lX" 117 # endif 118 #endif 119 #ifndef UINT64_MAX 120 # define UINT64_MAX UINT64_C(18446744073709551615) 121 #endif 122 123 // Incorrect(?) SIZE_MAX: 124 // - Interix headers typedef size_t to unsigned long, 125 // but a few lines later define SIZE_MAX to INT32_MAX. 126 // - SCO OpenServer (x86) headers typedef size_t to unsigned int 127 // but define SIZE_MAX to INT32_MAX. 128 #if defined(__INTERIX) || defined(_SCO_DS) 129 # undef SIZE_MAX 130 #endif 131 132 // The code currently assumes that size_t is either 32-bit or 64-bit. 133 #ifndef SIZE_MAX 134 # if SIZEOF_SIZE_T == 4 135 # define SIZE_MAX UINT32_MAX 136 # elif SIZEOF_SIZE_T == 8 137 # define SIZE_MAX UINT64_MAX 138 # else 139 # error size_t is not 32-bit or 64-bit 140 # endif 141 #endif 142 #if SIZE_MAX != UINT32_MAX && SIZE_MAX != UINT64_MAX 143 # error size_t is not 32-bit or 64-bit 144 #endif 145 146 #include <stdlib.h> 147 #include <assert.h> 148 149 // Pre-C99 systems lack stdbool.h. All the code in XZ Utils must be written 150 // so that it works with fake bool type, for example: 151 // 152 // bool foo = (flags & 0x100) != 0; 153 // bool bar = !!(flags & 0x100); 154 // 155 // This works with the real C99 bool but breaks with fake bool: 156 // 157 // bool baz = (flags & 0x100); 158 // 159 #ifdef HAVE_STDBOOL_H 160 # include <stdbool.h> 161 #else 162 # if ! HAVE__BOOL 163 typedef unsigned char _Bool; 164 # endif 165 # define bool _Bool 166 # define false 0 167 # define true 1 168 # define __bool_true_false_are_defined 1 169 #endif 170 171 // We may need alignas from C11/C17/C23. 172 #if __STDC_VERSION__ >= 202311 173 // alignas is a keyword in C23. Do nothing. 174 #elif __STDC_VERSION__ >= 201112 175 // Oracle Developer Studio 12.6 lacks <stdalign.h>. 176 // For simplicity, avoid the header with all C11/C17 compilers. 177 # define alignas _Alignas 178 #elif defined(__GNUC__) || defined(__clang__) 179 # define alignas(n) __attribute__((__aligned__(n))) 180 #else 181 # define alignas(n) 182 #endif 183 184 #include <string.h> 185 186 // MSVC v19.00 (VS 2015 version 14.0) and later should work. 187 // 188 // MSVC v19.27 (VS 2019 version 16.7) added support for restrict. 189 // Older ones support only __restrict. 190 #ifdef _MSC_VER 191 # if _MSC_VER < 1927 && !defined(restrict) 192 # define restrict __restrict 193 # endif 194 #endif 195 196 //////////// 197 // Macros // 198 //////////// 199 200 #undef memzero 201 #define memzero(s, n) memset(s, 0, n) 202 203 // NOTE: Avoid using MIN() and MAX(), because even conditionally defining 204 // those macros can cause some portability trouble, since on some systems 205 // the system headers insist defining their own versions. 206 #define my_min(x, y) ((x) < (y) ? (x) : (y)) 207 #define my_max(x, y) ((x) > (y) ? (x) : (y)) 208 209 #ifndef ARRAY_SIZE 210 # define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) 211 #endif 212 213 #if defined(__GNUC__) \ 214 && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4) 215 # define lzma_attr_alloc_size(x) __attribute__((__alloc_size__(x))) 216 #else 217 # define lzma_attr_alloc_size(x) 218 #endif 219 220 #if __STDC_VERSION__ >= 202311 221 # define FALLTHROUGH [[__fallthrough__]] 222 #elif (defined(__GNUC__) && __GNUC__ >= 7) \ 223 || (defined(__clang_major__) && __clang_major__ >= 10) 224 # define FALLTHROUGH __attribute__((__fallthrough__)) 225 #else 226 # define FALLTHROUGH ((void)0) 227 #endif 228 229 #endif 230