xref: /freebsd/contrib/xz/src/common/sysdefs.h (revision 128836d304d93f2d00eb14069c27089ab46c38d4)
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