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// This #define ensures that C99 and POSIX compliant stdio functions are 27// available with MinGW-w64 (both 32-bit and 64-bit). Modern MinGW-w64 adds 28// this automatically, for example, when the compiler is in C99 (or later) 29// mode when building against msvcrt.dll. It still doesn't hurt to be explicit 30// that we always want this and #define this unconditionally. 31// 32// With Universal CRT (UCRT) this is less important because UCRT contains 33// C99-compatible stdio functions. It's still nice to #define this as UCRT 34// doesn't support the POSIX thousand separator flag in printf (like "%'u"). 35#ifdef __MINGW32__ 36# define __USE_MINGW_ANSI_STDIO 1 37#endif 38 39// size_t and NULL 40#include <stddef.h> 41 42#ifdef HAVE_INTTYPES_H 43# include <inttypes.h> 44#endif 45 46// C99 says that inttypes.h always includes stdint.h, but some systems 47// don't do that, and require including stdint.h separately. 48#ifdef HAVE_STDINT_H 49# include <stdint.h> 50#endif 51 52// Some pre-C99 systems have SIZE_MAX in limits.h instead of stdint.h. The 53// limits are also used to figure out some macros missing from pre-C99 systems. 54#include <limits.h> 55 56// Be more compatible with systems that have non-conforming inttypes.h. 57// We assume that int is 32-bit and that long is either 32-bit or 64-bit. 58// Full Autoconf test could be more correct, but this should work well enough. 59// Note that this duplicates some code from lzma.h, but this is better since 60// we can work without inttypes.h thanks to Autoconf tests. 61#ifndef UINT32_C 62# if UINT_MAX != 4294967295U 63# error UINT32_C is not defined and unsigned int is not 32-bit. 64# endif 65# define UINT32_C(n) n ## U 66#endif 67#ifndef UINT32_MAX 68# define UINT32_MAX UINT32_C(4294967295) 69#endif 70#ifndef PRIu32 71# define PRIu32 "u" 72#endif 73#ifndef PRIx32 74# define PRIx32 "x" 75#endif 76#ifndef PRIX32 77# define PRIX32 "X" 78#endif 79 80#if ULONG_MAX == 4294967295UL 81# ifndef UINT64_C 82# define UINT64_C(n) n ## ULL 83# endif 84# ifndef PRIu64 85# define PRIu64 "llu" 86# endif 87# ifndef PRIx64 88# define PRIx64 "llx" 89# endif 90# ifndef PRIX64 91# define PRIX64 "llX" 92# endif 93#else 94# ifndef UINT64_C 95# define UINT64_C(n) n ## UL 96# endif 97# ifndef PRIu64 98# define PRIu64 "lu" 99# endif 100# ifndef PRIx64 101# define PRIx64 "lx" 102# endif 103# ifndef PRIX64 104# define PRIX64 "lX" 105# endif 106#endif 107#ifndef UINT64_MAX 108# define UINT64_MAX UINT64_C(18446744073709551615) 109#endif 110 111// Incorrect(?) SIZE_MAX: 112// - Interix headers typedef size_t to unsigned long, 113// but a few lines later define SIZE_MAX to INT32_MAX. 114// - SCO OpenServer (x86) headers typedef size_t to unsigned int 115// but define SIZE_MAX to INT32_MAX. 116#if defined(__INTERIX) || defined(_SCO_DS) 117# undef SIZE_MAX 118#endif 119 120// The code currently assumes that size_t is either 32-bit or 64-bit. 121#ifndef SIZE_MAX 122# if SIZEOF_SIZE_T == 4 123# define SIZE_MAX UINT32_MAX 124# elif SIZEOF_SIZE_T == 8 125# define SIZE_MAX UINT64_MAX 126# else 127# error size_t is not 32-bit or 64-bit 128# endif 129#endif 130#if SIZE_MAX != UINT32_MAX && SIZE_MAX != UINT64_MAX 131# error size_t is not 32-bit or 64-bit 132#endif 133 134#include <stdlib.h> 135#include <assert.h> 136 137// Pre-C99 systems lack stdbool.h. All the code in XZ Utils must be written 138// so that it works with fake bool type, for example: 139// 140// bool foo = (flags & 0x100) != 0; 141// bool bar = !!(flags & 0x100); 142// 143// This works with the real C99 bool but breaks with fake bool: 144// 145// bool baz = (flags & 0x100); 146// 147#ifdef HAVE_STDBOOL_H 148# include <stdbool.h> 149#else 150# if ! HAVE__BOOL 151typedef unsigned char _Bool; 152# endif 153# define bool _Bool 154# define false 0 155# define true 1 156# define __bool_true_false_are_defined 1 157#endif 158 159#include <string.h> 160 161// Visual Studio 2013 update 2 supports only __inline, not inline. 162// MSVC v19.0 / VS 2015 and newer support both. 163// 164// MSVC v19.27 (VS 2019 version 16.7) added support for restrict. 165// Older ones support only __restrict. 166#ifdef _MSC_VER 167# if _MSC_VER < 1900 && !defined(inline) 168# define inline __inline 169# endif 170# if _MSC_VER < 1927 && !defined(restrict) 171# define restrict __restrict 172# endif 173#endif 174 175//////////// 176// Macros // 177//////////// 178 179#undef memzero 180#define memzero(s, n) memset(s, 0, n) 181 182// NOTE: Avoid using MIN() and MAX(), because even conditionally defining 183// those macros can cause some portability trouble, since on some systems 184// the system headers insist defining their own versions. 185#define my_min(x, y) ((x) < (y) ? (x) : (y)) 186#define my_max(x, y) ((x) > (y) ? (x) : (y)) 187 188#ifndef ARRAY_SIZE 189# define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) 190#endif 191 192#if defined(__GNUC__) \ 193 && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4) 194# define lzma_attr_alloc_size(x) __attribute__((__alloc_size__(x))) 195#else 196# define lzma_attr_alloc_size(x) 197#endif 198 199#endif 200