Home | History | Annotate | Line # | Download | only in common
      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