Subversion Repositories eduke32

Rev

Rev 8648 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5 Plagman 1
// Compatibility declarations for things which might not be present in
2
// certain build environments. It also levels the playing field caused
3
// by different platforms.
4
 
4747 terminx 5
#ifndef compat_h_
6
#define compat_h_
5 Plagman 7
 
6072 hendricks2 8
#pragma once
9
 
6840 terminx 10
#ifdef _WIN32
11
# include "windows_inc.h"
12
#endif
6072 hendricks2 13
 
14
////////// Compiler detection //////////
15
 
4685 hendricks2 16
#ifdef __GNUC__
4762 hendricks2 17
# define EDUKE32_GCC_PREREQ(major, minor) (major < __GNUC__ || (major == __GNUC__ && minor <= __GNUC_MINOR__))
4685 hendricks2 18
#else
19
# define EDUKE32_GCC_PREREQ(major, minor) 0
20
#endif
21
 
22
#ifdef __clang__
4762 hendricks2 23
# define EDUKE32_CLANG_PREREQ(major, minor) (major < __clang_major__ || (major == __clang_major__ && minor <= __clang_minor__))
4685 hendricks2 24
#else
25
# define EDUKE32_CLANG_PREREQ(major, minor) 0
26
#endif
27
#ifndef __has_builtin
28
# define __has_builtin(x) 0  // Compatibility with non-clang compilers.
29
#endif
30
#ifndef __has_feature
31
# define __has_feature(x) 0  // Compatibility with non-clang compilers.
32
#endif
33
#ifndef __has_extension
34
# define __has_extension __has_feature // Compatibility with pre-3.0 compilers.
35
#endif
6353 hendricks2 36
#ifndef __has_cpp_attribute
37
# define __has_cpp_attribute(x) 0
38
#endif
4685 hendricks2 39
 
6141 hendricks2 40
#ifdef _MSC_VER
41
# define EDUKE32_MSVC_PREREQ(major) ((major) <= (_MSC_VER))
6469 hendricks2 42
# ifdef __cplusplus
43
#  define EDUKE32_MSVC_CXX_PREREQ(major) ((major) <= (_MSC_VER))
44
# else
45
#  define EDUKE32_MSVC_CXX_PREREQ(major) 0
46
# endif
6141 hendricks2 47
#else
48
# define EDUKE32_MSVC_PREREQ(major) 0
6469 hendricks2 49
# define EDUKE32_MSVC_CXX_PREREQ(major) 0
6141 hendricks2 50
#endif
6072 hendricks2 51
 
6141 hendricks2 52
 
6114 hendricks2 53
////////// Language detection //////////
54
 
55
#if defined __STDC__
56
# if defined __STDC_VERSION__ && __STDC_VERSION__ >= 201112L
57
#  define CSTD 2011
58
# elif defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
59
#  define CSTD 1999
60
# elif defined __STDC_VERSION__ && __STDC_VERSION__ >= 199409L
61
#  define CSTD 1994
62
# else
63
#  define CSTD 1989
64
# endif
65
#else
66
# define CSTD 0
67
#endif
68
 
6468 hendricks2 69
#if defined __cplusplus && __cplusplus >= 201703L
70
# define CXXSTD 2017
71
#elif defined __cplusplus && __cplusplus >= 201402L
6114 hendricks2 72
# define CXXSTD 2014
73
#elif defined __cplusplus && __cplusplus >= 201103L
74
# define CXXSTD 2011
75
#elif defined __cplusplus && __cplusplus >= 199711L
76
# define CXXSTD 1998
77
#else
78
# define CXXSTD 0
79
#endif
80
 
81
 
6072 hendricks2 82
////////// Language and compiler feature polyfills //////////
83
 
84
#ifdef __cplusplus
85
# define EXTERNC extern "C"
86
#else
87
# define EXTERNC
88
#endif
89
 
6071 hendricks2 90
#ifndef UNREFERENCED_PARAMETER
91
# define UNREFERENCED_PARAMETER(x) (x) = (x)
654 terminx 92
#endif
93
 
6297 terminx 94
#ifndef UNREFERENCED_CONST_PARAMETER
95
# ifdef _MSC_VER
6401 hendricks2 96
#  define UNREFERENCED_CONST_PARAMETER(x) ((void)(x))
6297 terminx 97
# else
98
#  define UNREFERENCED_CONST_PARAMETER(x)
99
# endif
100
#endif
101
 
5197 hendricks2 102
#ifdef __GNUC__
103
# define UNUSED(x) UNUSED_ ## x __attribute__((unused))
104
# define PRINTF_FORMAT(stringindex, firstargindex) __attribute__((format (printf, stringindex, firstargindex)))
105
#else
106
# define UNUSED(x) x
107
# define PRINTF_FORMAT(stringindex, firstargindex)
108
#endif
109
 
1743 helixhorne 110
#if defined __GNUC__ || defined __clang__
111
# define ATTRIBUTE(attrlist) __attribute__(attrlist)
112
#else
113
# define ATTRIBUTE(attrlist)
114
#endif
115
 
3341 helixhorne 116
#if !defined __clang__ && !defined USING_LTO
117
# define ATTRIBUTE_OPTIMIZE(str) ATTRIBUTE((optimize(str)))
118
#else
119
# define ATTRIBUTE_OPTIMIZE(str)
120
#endif
121
 
6072 hendricks2 122
#if EDUKE32_GCC_PREREQ(4,0)
123
# define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
4685 hendricks2 124
#else
6072 hendricks2 125
# define WARN_UNUSED_RESULT
4685 hendricks2 126
#endif
127
 
6072 hendricks2 128
#if defined _MSC_VER && _MSC_VER < 1800
129
# define inline __inline
4680 terminx 130
#endif
131
 
7299 terminx 132
#ifndef MAY_ALIAS
133
# ifdef _MSC_VER
134
#  define MAY_ALIAS
135
# else
136
#  define MAY_ALIAS __attribute__((may_alias))
137
# endif
138
#endif
139
 
6072 hendricks2 140
#ifndef FORCE_INLINE
6076 hendricks2 141
# ifdef _MSC_VER
142
#  define FORCE_INLINE __forceinline
4942 hendricks2 143
# else
6072 hendricks2 144
#  ifdef __GNUC__
6076 hendricks2 145
#    define FORCE_INLINE inline __attribute__((always_inline))
6072 hendricks2 146
#  else
6076 hendricks2 147
#    define FORCE_INLINE inline
4762 hendricks2 148
#  endif
149
# endif
150
#endif
151
 
1435 terminx 152
#ifndef _MSC_VER
3278 hendricks2 153
#  ifndef __fastcall
154
#    if defined(__GNUC__) && defined(__i386__)
2992 helixhorne 155
#      define __fastcall __attribute__((fastcall))
3278 hendricks2 156
#    else
157
#      define __fastcall
2992 helixhorne 158
#    endif
159
#  endif
1435 terminx 160
#endif
161
 
6072 hendricks2 162
#ifndef DISABLE_INLINING
163
# define EXTERN_INLINE static inline
164
# define EXTERN_INLINE_HEADER static inline
165
#else
166
# define EXTERN_INLINE __fastcall
167
# define EXTERN_INLINE_HEADER extern __fastcall
1346 terminx 168
#endif
169
 
8553 terminx 170
#if 0 && defined(__OPTIMIZE__) && (defined __GNUC__ || __has_builtin(__builtin_expect))
6072 hendricks2 171
#define EDUKE32_PREDICT_TRUE(x)       __builtin_expect(!!(x),1)
172
#define EDUKE32_PREDICT_FALSE(x)     __builtin_expect(!!(x),0)
173
#else
174
#define EDUKE32_PREDICT_TRUE(x) (x)
175
#define EDUKE32_PREDICT_FALSE(x) (x)
1346 terminx 176
#endif
177
 
6072 hendricks2 178
#if EDUKE32_GCC_PREREQ(4,5)  || __has_builtin(__builtin_unreachable)
179
#define EDUKE32_UNREACHABLE_SECTION(...)   __builtin_unreachable()
180
#elif _MSC_VER
181
#define EDUKE32_UNREACHABLE_SECTION(...)   __assume(0)
182
#else
183
#define EDUKE32_UNREACHABLE_SECTION(...) __VA_ARGS__
184
#endif
1592 terminx 185
 
6077 hendricks2 186
#if EDUKE32_GCC_PREREQ(2,0) || defined _MSC_VER
187
# define EDUKE32_FUNCTION __FUNCTION__
6114 hendricks2 188
#elif CSTD >= 1999 || CXXSTD >= 2011
6072 hendricks2 189
# define EDUKE32_FUNCTION __func__
190
#else
191
# define EDUKE32_FUNCTION "???"
192
#endif
4658 terminx 193
 
6077 hendricks2 194
#ifdef _MSC_VER
195
# define EDUKE32_PRETTY_FUNCTION __FUNCSIG__
196
#elif EDUKE32_GCC_PREREQ(2,0)
197
# define EDUKE32_PRETTY_FUNCTION __PRETTY_FUNCTION__
198
#else
199
# define EDUKE32_PRETTY_FUNCTION EDUKE32_FUNCTION
200
#endif
201
 
6072 hendricks2 202
#ifdef __COUNTER__
6472 hendricks2 203
# define EDUKE32_UNIQUE_SRC_ID __COUNTER__
6070 hendricks2 204
#else
6472 hendricks2 205
# define EDUKE32_UNIQUE_SRC_ID __LINE__
206
#endif
207
 
208
#if CXXSTD >= 2017
209
# define EDUKE32_STATIC_ASSERT(cond) static_assert(cond)
210
#elif CXXSTD >= 2011 || CSTD >= 2011 || EDUKE32_MSVC_CXX_PREREQ(1600)
211
# define EDUKE32_STATIC_ASSERT(cond) static_assert(cond, "")
212
#else
213
/* C99 / C++03 static assertions based on source found in LuaJIT's src/lj_def.h. */
214
# define EDUKE32_ASSERT_NAME2(name, line) name ## line
215
# define EDUKE32_ASSERT_NAME(line) EDUKE32_ASSERT_NAME2(eduke32_assert_, line)
6072 hendricks2 216
# define EDUKE32_STATIC_ASSERT(cond) \
6472 hendricks2 217
    extern void EDUKE32_ASSERT_NAME(EDUKE32_UNIQUE_SRC_ID)(int STATIC_ASSERTION_FAILED[(cond)?1:-1])
5 Plagman 218
#endif
219
 
6072 hendricks2 220
#ifdef _MSC_VER
5 Plagman 221
# define longlong(x) x##i64
222
#else
223
# define longlong(x) x##ll
224
#endif
225
 
6072 hendricks2 226
#ifndef FP_OFF
227
# define FP_OFF(__p) ((uintptr_t)(__p))
4606 terminx 228
#endif
229
 
6072 hendricks2 230
#ifdef UNDERSCORES
231
# define ASMSYM(x) "_" x
232
#else
233
# define ASMSYM(x) x
5 Plagman 234
#endif
235
 
7526 hendricks2 236
#if defined __cplusplus
237
# define STATIC_CAST_OP(t) static_cast<t>
238
# define REINTERPRET_CAST_OP(t) reinterpret_cast<t>
239
#else
240
# define STATIC_CAST_OP(t) (t)
241
# define REINTERPRET_CAST_OP(t) (t)
242
#endif
243
#define STATIC_CAST(t, v) (STATIC_CAST_OP(t)(v))
244
#define REINTERPRET_CAST(t, v) (REINTERPRET_CAST_OP(t)(v))
245
 
6141 hendricks2 246
#if defined __cplusplus && (__cplusplus >= 201103L || __has_feature(cxx_constexpr) || EDUKE32_MSVC_PREREQ(1900))
6115 hendricks2 247
# define HAVE_CONSTEXPR
248
# define CONSTEXPR constexpr
249
#else
250
# define CONSTEXPR
251
#endif
2270 helixhorne 252
 
6141 hendricks2 253
#if CXXSTD >= 2011 || EDUKE32_MSVC_PREREQ(1700)
6117 hendricks2 254
# define FINAL final
255
#else
256
# define FINAL
257
#endif
258
 
6115 hendricks2 259
#if CXXSTD >= 2014
260
# define CONSTEXPR_CXX14 CONSTEXPR
261
#else
262
# define CONSTEXPR_CXX14
263
#endif
264
 
6471 hendricks2 265
#if CXXSTD >= 2011
6447 hendricks2 266
# if __has_cpp_attribute(fallthrough)
267
#  define fallthrough__ [[fallthrough]]
268
# elif __has_cpp_attribute(clang::fallthrough)
269
#  define fallthrough__ [[clang::fallthrough]]
270
# elif __has_cpp_attribute(gnu::fallthrough)
271
#  define fallthrough__ [[gnu::fallthrough]]
272
# endif
6353 hendricks2 273
#endif
6447 hendricks2 274
#ifndef fallthrough__
275
# if !defined __clang__ && EDUKE32_GCC_PREREQ(7,0)
276
#  define fallthrough__ __attribute__((fallthrough))
277
# elif defined _MSC_VER
278
#  define fallthrough__ __fallthrough
279
# else
280
#  define fallthrough__
281
# endif
282
#endif
6353 hendricks2 283
 
284
 
6072 hendricks2 285
////////// Platform detection //////////
286
 
287
#if defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ || defined __bsdi__ || defined __DragonFly__
288
# define EDUKE32_BSD
3116 hendricks2 289
#endif
290
 
6072 hendricks2 291
#ifdef __APPLE__
292
# include <TargetConditionals.h>
293
# if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
294
#  define EDUKE32_IOS
4937 helixhorne 295
# else
6072 hendricks2 296
#  define EDUKE32_OSX
4937 helixhorne 297
# endif
298
#endif
299
 
6072 hendricks2 300
 
301
////////// Architecture detection //////////
302
 
8273 hendricks2 303
#if defined __arm__ || defined __aarch64__
304
# define EDUKE32_CPU_ARM
305
#elif defined __i386 || defined __i386__ || defined _M_IX86 || defined _M_X64 || defined __x86_64__
306
# define EDUKE32_CPU_X86
307
#elif defined _M_PPC || defined __powerpc__ || defined __powerpc64__
308
# define EDUKE32_CPU_PPC
309
#elif defined __MIPSEL__ || defined __mips_isa_rev
310
# define EDUKE32_CPU_MIPS
311
#endif
312
 
6072 hendricks2 313
#if defined _LP64 || defined __LP64__ || defined __64BIT__ || _ADDR64 || defined _WIN64 || defined __arch64__ ||       \
314
__WORDSIZE == 64 || (defined __sparc && defined __sparcv9) || defined __x86_64 || defined __amd64 ||                   \
315
defined __x86_64__ || defined __amd64__ || defined _M_X64 || defined _M_IA64 || defined __ia64 || defined __IA64__
316
 
317
# define BITNESS64
318
 
2495 hendricks2 319
#endif
320
 
5 Plagman 321
#if defined(__linux)
322
# include <endian.h>
323
# if __BYTE_ORDER == __LITTLE_ENDIAN
324
#  define B_LITTLE_ENDIAN 1
325
#  define B_BIG_ENDIAN    0
326
# elif __BYTE_ORDER == __BIG_ENDIAN
327
#  define B_LITTLE_ENDIAN 0
328
#  define B_BIG_ENDIAN    1
329
# endif
330
 
2916 terminx 331
#elif defined(GEKKO) || defined(__ANDROID__)
2630 helixhorne 332
# define B_LITTLE_ENDIAN 0
333
# define B_BIG_ENDIAN 1
334
 
2916 terminx 335
#elif defined(__OpenBSD__)
336
# include <machine/endian.h>
337
# if _BYTE_ORDER == _LITTLE_ENDIAN
338
#  define B_LITTLE_ENDIAN 1
339
#  define B_BIG_ENDIAN    0
340
# elif _BYTE_ORDER == _BIG_ENDIAN
341
#  define B_LITTLE_ENDIAN 0
342
#  define B_BIG_ENDIAN    1
343
# endif
344
 
5037 hendricks2 345
#elif defined EDUKE32_BSD
5 Plagman 346
# include <sys/endian.h>
347
# if _BYTE_ORDER == _LITTLE_ENDIAN
348
#  define B_LITTLE_ENDIAN 1
349
#  define B_BIG_ENDIAN    0
350
# elif _BYTE_ORDER == _BIG_ENDIAN
351
#  define B_LITTLE_ENDIAN 0
352
#  define B_BIG_ENDIAN    1
353
# endif
354
 
355
#elif defined(__APPLE__)
356
# if defined(__LITTLE_ENDIAN__)
357
#  define B_LITTLE_ENDIAN 1
358
#  define B_BIG_ENDIAN    0
359
# elif defined(__BIG_ENDIAN__)
360
#  define B_LITTLE_ENDIAN 0
361
#  define B_BIG_ENDIAN    1
362
# endif
363
# include <libkern/OSByteOrder.h>
364
 
365
#elif defined(__BEOS__)
366
# include <posix/endian.h>
367
# if LITTLE_ENDIAN != 0
368
#  define B_LITTLE_ENDIAN 1
369
#  define B_BIG_ENDIAN    0
370
# elif BIG_ENDIAN != 0
371
#  define B_LITTLE_ENDIAN 0
372
#  define B_BIG_ENDIAN    1
373
# endif
374
 
375
#elif defined(__QNX__)
376
# if defined __LITTLEENDIAN__
377
#  define B_LITTLE_ENDIAN 1
378
#  define B_BIG_ENDIAN    0
379
# elif defined __BIGENDIAN__
380
#  define B_LITTLE_ENDIAN 0
381
#  define B_BIG_ENDIAN    1
382
# endif
383
 
384
#elif defined(__sun)
385
# if defined _LITTLE_ENDIAN
386
#  define B_LITTLE_ENDIAN 1
387
#  define B_BIG_ENDIAN    0
388
# elif defined _BIG_ENDIAN
389
#  define B_LITTLE_ENDIAN 0
390
#  define B_BIG_ENDIAN    1
391
# endif
392
 
393
#elif defined(_WIN32) || defined(SKYOS) || defined(__SYLLABLE__)
394
# define B_LITTLE_ENDIAN 1
395
# define B_BIG_ENDIAN    0
396
#endif
397
 
398
#if !defined(B_LITTLE_ENDIAN) || !defined(B_BIG_ENDIAN)
399
# error Unknown endianness
400
#endif
401
 
4893 terminx 402
 
6072 hendricks2 403
////////// Standard library headers //////////
4893 terminx 404
 
6072 hendricks2 405
#undef __USE_MINGW_ANSI_STDIO // Workaround for MinGW-w64.
406
 
407
#ifndef __STDC_FORMAT_MACROS
408
# define __STDC_FORMAT_MACROS
4274 hendricks2 409
#endif
6072 hendricks2 410
#ifndef __STDC_LIMIT_MACROS
411
# define __STDC_LIMIT_MACROS
412
#endif
6073 hendricks2 413
 
6770 hendricks2 414
#ifndef _USE_MATH_DEFINES
415
# define _USE_MATH_DEFINES
416
#endif
417
 
7589 terminx 418
#include <inttypes.h>
419
#include <stdint.h>
285 terminx 420
 
6074 hendricks2 421
#include <limits.h>
7186 terminx 422
#include <stdarg.h>
6072 hendricks2 423
#include <stddef.h>
7359 hendricks2 424
#ifndef USE_PHYSFS
7186 terminx 425
#include <stdio.h>
7359 hendricks2 426
#endif
6072 hendricks2 427
#include <stdlib.h>
428
#include <string.h>
429
 
7799 hendricks2 430
#if !(defined _WIN32 && defined __clang__)
7186 terminx 431
#include <float.h>
7799 hendricks2 432
#endif
6072 hendricks2 433
#include <math.h>
434
 
435
#include <ctype.h>
436
#include <errno.h>
7186 terminx 437
#include <time.h>
6072 hendricks2 438
 
439
#include <assert.h>
440
 
6117 hendricks2 441
#ifdef __cplusplus
7799 hendricks2 442
# include <limits>
6141 hendricks2 443
# if CXXSTD >= 2011 || EDUKE32_MSVC_PREREQ(1800)
7078 terminx 444
#  include <algorithm>
445
#  include <functional>
6117 hendricks2 446
#  include <type_traits>
7557 hendricks2 447
// we need this because MSVC does not properly identify C++11 support
448
#  define HAVE_CXX11_HEADERS
6117 hendricks2 449
# endif
450
#endif
6072 hendricks2 451
 
452
////////// Platform headers //////////
453
 
454
#if !defined __APPLE__ && (!defined EDUKE32_BSD || !__STDC__)
455
# include <malloc.h>
456
#endif
457
 
7359 hendricks2 458
#ifndef USE_PHYSFS
6072 hendricks2 459
#include <fcntl.h>
7186 terminx 460
#include <sys/stat.h>
6072 hendricks2 461
#include <sys/types.h>
462
 
463
#if defined(_WIN32)
7186 terminx 464
# include <direct.h>
6072 hendricks2 465
# include <io.h>
466
#else
467
# include <unistd.h>
468
#endif
7359 hendricks2 469
#endif
6072 hendricks2 470
 
471
 
472
////////// DEPRECATED: Standard library prefixing //////////
473
 
474
#ifdef _MSC_VER
6375 hendricks2 475
# if defined _M_AMD64 || defined _M_ARM64 || defined _M_X64 || defined _WIN64
476
// should be int64_t, if not for a suspected VS compiler bug
6272 terminx 477
typedef int32_t ssize_t;
6375 hendricks2 478
# else
479
typedef int32_t ssize_t;
480
# endif
6072 hendricks2 481
#endif
6272 terminx 482
 
6072 hendricks2 483
typedef size_t bsize_t;
484
typedef ssize_t bssize_t;
485
 
486
typedef FILE BFILE;
487
 
488
#define BO_BINARY O_BINARY
489
#define BO_TEXT   O_TEXT
490
#define BO_RDONLY O_RDONLY
491
#define BO_WRONLY O_WRONLY
492
#define BO_RDWR   O_RDWR
493
#define BO_APPEND O_APPEND
494
#define BO_CREAT  O_CREAT
495
#define BO_TRUNC  O_TRUNC
496
#define BS_IRGRP  S_IRGRP
497
#define BS_IWGRP  S_IWGRP
498
#define BS_IEXEC  S_IEXEC
499
#define BS_IFIFO  S_IFIFO
500
#define BS_IFCHR  S_IFCHR
501
#define BS_IFBLK  S_IFBLK
502
#define BS_IFDIR  S_IFDIR
503
#define BS_IFREG  S_IFREG
504
#define BSEEK_SET SEEK_SET
505
#define BSEEK_CUR SEEK_CUR
506
#define BSEEK_END SEEK_END
507
 
508
#define BMAX_PATH 256
509
 
510
#define Bassert assert
511
#define Brand rand
512
#define Bmalloc malloc
513
#define Bcalloc calloc
514
#define Brealloc realloc
515
#define Bfree free
516
#define Bopen open
517
#define Bclose close
518
#define Bwrite write
519
#define Bread read
520
#define Blseek lseek
521
#define Bstat stat
522
#define Bfstat fstat
523
#define Bfileno fileno
524
#define Bferror ferror
525
#define Bfopen fopen
526
#define Bfclose fclose
527
#define Bfflush fflush
528
#define Bfeof feof
529
#define Bfgetc fgetc
530
#define Brewind rewind
531
#define Bfgets fgets
532
#define Bfputc fputc
533
#define Bfputs fputs
534
#define Bfread fread
535
#define Bfwrite fwrite
536
#define Bfprintf fprintf
537
#define Bfscanf fscanf
538
#define Bfseek fseek
539
#define Bftell ftell
540
#define Bputs puts
541
#define Bstrcpy strcpy
542
#define Bstrncpy strncpy
543
#define Bstrcmp strcmp
544
#define Bstrncmp strncmp
545
#define Bstrcat strcat
546
#define Bstrncat strncat
547
#define Bstrlen strlen
548
#define Bstrchr strchr
549
#define Bstrrchr strrchr
550
#define Bstrtol strtol
551
#define Bstrtoul strtoul
552
#define Bstrtod strtod
553
#define Bstrstr strstr
554
#define Bislower islower
555
#define Bisupper isupper
556
#define Bisdigit isdigit
557
#define Btoupper toupper
558
#define Btolower tolower
559
#define Bmemcpy memcpy
560
#define Bmemmove memmove
561
#define Bmemchr memchr
562
#define Bmemset memset
563
#define Bmemcmp memcmp
564
#define Bscanf scanf
565
#define Bprintf printf
566
#define Bsscanf sscanf
567
#define Bsprintf sprintf
568
#define Bvfprintf vfprintf
569
#define Bgetenv getenv
570
#define Butime utime
571
 
572
 
573
////////// Standard library wrappers //////////
574
 
575
#ifdef __ANDROID__
576
# define BS_IWRITE S_IWUSR
577
# define BS_IREAD  S_IRUSR
578
#else
579
# define BS_IWRITE S_IWRITE
580
# define BS_IREAD  S_IREAD
581
#endif
582
 
583
#if defined(__cplusplus) && defined(_MSC_VER)
584
# define Bstrdup _strdup
585
# define Bchdir _chdir
586
# define Bgetcwd _getcwd
587
#else
588
# define Bstrdup strdup
589
# define Bchdir chdir
590
# define Bgetcwd getcwd
591
#endif
592
 
593
#if defined(__GNUC__)
594
# define Btell(h) lseek(h,0,SEEK_CUR)
595
#else
596
# define Btell tell
597
#endif
598
 
599
#if defined(_MSC_VER)
600
# define Bstrcasecmp _stricmp
601
# define Bstrncasecmp _strnicmp
602
#elif defined(__QNX__)
603
# define Bstrcasecmp stricmp
604
# define Bstrncasecmp strnicmp
605
#else
606
# define Bstrcasecmp strcasecmp
607
# define Bstrncasecmp strncasecmp
608
#endif
609
 
8762 terminx 610
#ifdef _WIN32
6072 hendricks2 611
# define Bsnprintf _snprintf
612
# define Bvsnprintf _vsnprintf
613
#else
614
# define Bsnprintf snprintf
615
# define Bvsnprintf vsnprintf
616
#endif
617
 
8648 hendricks2 618
#ifdef _MSC_VER
619
# define Balloca _alloca
620
#elif defined __GNUC__
621
# define Balloca __builtin_alloca
622
#else
623
# define Balloca alloca
624
#endif
625
 
626
#ifdef _MSC_VER
627
# define Bmalloca _malloca
628
# define Bfreea _freea
629
#else
630
# define Bmalloca alloca
631
# define Bfreea(ptr) do { } while (0)
632
#endif
633
 
6072 hendricks2 634
#define Btime() time(NULL)
635
 
636
#if defined(_WIN32)
637
# define Bmkdir(s,x) mkdir(s)
638
#else
639
# define Bmkdir mkdir
640
#endif
641
 
642
// XXX: different across 32- and 64-bit archs (e.g.
643
// parsing the decimal representation of 0xffffffff,
644
// 4294967295 -- long is signed, so strtol would
645
// return LONG_MAX (== 0x7fffffff on 32-bit archs))
8374 terminx 646
 
647
static FORCE_INLINE int32_t atoi_safe(const char *str) { return (int32_t)Bstrtol(str, NULL, 10); }
648
 
649
#define Batoi(x) atoi_safe(x)
6072 hendricks2 650
#define Batol(str) (strtol(str, NULL, 10))
651
#define Batof(str) (strtod(str, NULL))
652
 
653
#if defined BITNESS64 && (defined __SSE2__ || defined _MSC_VER)
654
#include <emmintrin.h>
6076 hendricks2 655
static FORCE_INLINE int32_t Blrintf(const float x)
6072 hendricks2 656
{
657
    __m128 xx = _mm_load_ss(&x);
658
    return _mm_cvtss_si32(xx);
659
}
660
#elif defined (_MSC_VER)
6076 hendricks2 661
static FORCE_INLINE int32_t Blrintf(const float x)
6072 hendricks2 662
{
663
    int n;
664
    __asm fld x;
665
    __asm fistp n;
666
    return n;
667
}
668
#else
6651 hendricks2 669
#define Blrintf(x) ((int32_t)lrintf(x))
6072 hendricks2 670
#endif
671
 
672
#if defined(__arm__)
673
# define Bsqrt __builtin_sqrt
674
# define Bsqrtf __builtin_sqrtf
675
#else
676
# define Bsqrt sqrt
677
# define Bsqrtf sqrtf
678
#endif
679
 
680
// redefined for apple/ppc, which chokes on stderr when linking...
681
#if defined EDUKE32_OSX && defined __BIG_ENDIAN__
682
# define ERRprintf(fmt, ...) printf(fmt, ## __VA_ARGS__)
683
#else
684
# define ERRprintf(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__)
685
#endif
686
 
8274 hendricks2 687
// Bexit is ONLY for errors!
6072 hendricks2 688
#ifdef DEBUGGINGAIDS
689
# define Bexit(status) do { initprintf("exit(%d) at %s:%d in %s()\n", status, __FILE__, __LINE__, EDUKE32_FUNCTION); exit(status); } while (0)
690
#else
691
# define Bexit exit
692
#endif
693
 
8191 terminx 694
#ifdef _WIN32
695
#define fatal_exit__(x) FatalAppExitA(0, x)
696
#else
697
#define fatal_exit__(x) do { wm_msgbox("Fatal Error", "%s", x); exit(EXIT_FAILURE); } while(0)
698
#endif
6072 hendricks2 699
 
8191 terminx 700
#define fatal_exit(status) do { initprintf("fatal_exit(%s) at %s:%d in %s()\n", status, __FILE__, __LINE__, EDUKE32_FUNCTION); fatal_exit__(status); } while (0)
701
 
6072 hendricks2 702
////////// Standard library monkey patching //////////
703
 
704
#ifndef NULL
705
# define NULL ((void *)0)
706
#endif
707
 
708
#ifdef _MSC_VER
709
# define strtoll _strtoi64
710
#endif
711
 
6091 hendricks2 712
#ifndef O_BINARY
713
# define O_BINARY 0
714
#endif
715
#ifndef O_TEXT
716
# define O_TEXT 0
717
#endif
718
 
719
#ifndef F_OK
720
# define F_OK 0
721
#endif
722
 
6072 hendricks2 723
#ifdef GEKKO
724
# undef PRIdPTR
725
# define PRIdPTR "d"
726
# undef PRIxPTR
727
# define PRIxPTR "x"
728
# undef SCNx32
729
# define SCNx32 "x"
730
#endif
731
 
732
#if defined EDUKE32_OSX
733
# if !defined __x86_64__ && defined __GNUC__
734
// PK 20110617: is*() crashes for me in x86 code compiled from 64-bit, and gives link errors on ppc
735
//              This hack patches all occurences.
736
#  define isdigit(ch) ({ int32_t c__dontuse_=ch; c__dontuse_>='0' && c__dontuse_<='9'; })
737
#  define isalpha(ch) ({ int32_t c__dontuse2_=ch; (c__dontuse2_>='A' && c__dontuse2_<='Z') || (c__dontuse2_>='a' && c__dontuse2_<='z'); })
738
#  define isalnum(ch2)  ({ int32_t c2__dontuse_=ch2; isalpha(c2__dontuse_) || isdigit(c2__dontuse_); })
739
#  if defined __BIG_ENDIAN__
740
#   define isspace(ch)  ({ int32_t c__dontuse_=ch; (c__dontuse_==' ' || c__dontuse_=='\t' || c__dontuse_=='\n' || c__dontuse_=='\v' || c__dontuse_=='\f' || c__dontuse_=='\r'); })
741
#   define isprint(ch)  ({ int32_t c__dontuse_=ch; (c__dontuse_>=0x20 && c__dontuse_<0x7f); })
742
#  endif
285 terminx 743
# endif
6072 hendricks2 744
#endif
285 terminx 745
 
6072 hendricks2 746
#ifdef __ANDROID__
747
void eduke32_exit_return(int) ATTRIBUTE((noreturn));
748
# define exit(x) eduke32_exit_return(x)
5 Plagman 749
#endif
750
 
6072 hendricks2 751
 
6117 hendricks2 752
////////// Metaprogramming structs //////////
753
 
754
#ifdef __cplusplus
755
 
7557 hendricks2 756
# ifdef HAVE_CXX11_HEADERS
6117 hendricks2 757
using std::is_integral;
6577 hendricks2 758
template <typename T>
759
struct is_signed
760
{
761
    static constexpr bool value = std::is_signed<T>::value;
762
};
763
template <typename T>
764
struct is_unsigned
765
{
766
    static constexpr bool value = std::is_unsigned<T>::value;
767
};
6117 hendricks2 768
# endif
769
 
770
# if CXXSTD >= 2014
771
using std::enable_if_t;
772
using std::conditional_t;
6138 hendricks2 773
using std::make_signed_t;
774
using std::make_unsigned_t;
7719 terminx 775
using std::remove_pointer_t;
7557 hendricks2 776
# elif defined HAVE_CXX11_HEADERS
6117 hendricks2 777
template <bool B, class T = void>
778
using enable_if_t = typename std::enable_if<B, T>::type;
779
template<bool B, class T, class F>
780
using conditional_t = typename std::conditional<B, T, F>::type;
6138 hendricks2 781
template <typename T>
782
using make_signed_t = typename std::make_signed<T>::type;
783
template <typename T>
784
using make_unsigned_t = typename std::make_unsigned<T>::type;
7719 terminx 785
template <class T>
786
using remove_pointer_t = typename std::remove_pointer<T>::type;
6117 hendricks2 787
# endif
788
 
7559 hendricks2 789
# ifdef HAVE_CXX11_HEADERS
790
template <typename type, typename other_type_with_sign>
791
using take_sign_t = conditional_t< is_signed<other_type_with_sign>::value, make_signed_t<type>, make_unsigned_t<type> >;
792
# endif
793
 
6118 hendricks2 794
template <size_t size>
795
struct integers_of_size { };
796
template <>
797
struct integers_of_size<sizeof(int8_t)>
798
{
799
    typedef int8_t i;
800
    typedef uint8_t u;
801
};
802
template <>
803
struct integers_of_size<sizeof(int16_t)>
804
{
805
    typedef int16_t i;
806
    typedef uint16_t u;
807
};
808
template <>
809
struct integers_of_size<sizeof(int32_t)>
810
{
811
    typedef int32_t i;
812
    typedef uint32_t u;
813
};
814
template <>
815
struct integers_of_size<sizeof(int64_t)>
816
{
817
    typedef int64_t i;
818
    typedef uint64_t u;
819
};
820
 
6117 hendricks2 821
#endif
822
 
823
 
6072 hendricks2 824
////////// Typedefs //////////
825
 
6117 hendricks2 826
#ifdef __cplusplus
827
// for use in SFINAE constructs in place of the pointer trick (to which 0 can unintentionally be implicitly cast)
828
struct Dummy FINAL
829
{
830
    FORCE_INLINE CONSTEXPR Dummy() : dummy(0) { }
831
    char dummy;
832
};
833
#endif
834
 
6374 hendricks2 835
#if defined(__x86_64__)
836
// for 32-bit pointers in x86_64 code, such as `gcc -mx32`
837
typedef uint64_t reg_t;
838
typedef int64_t sreg_t;
839
#else
840
typedef size_t reg_t;
6384 terminx 841
typedef ssize_t sreg_t;
6374 hendricks2 842
#endif
843
 
7557 hendricks2 844
#ifdef HAVE_CXX11_HEADERS
6374 hendricks2 845
using  native_t = typename integers_of_size<sizeof(reg_t)>::i;
846
using unative_t = typename integers_of_size<sizeof(reg_t)>::u;
6118 hendricks2 847
#else
6374 hendricks2 848
typedef sreg_t native_t;
849
typedef reg_t unative_t;
6118 hendricks2 850
#endif
851
EDUKE32_STATIC_ASSERT(sizeof(native_t) == sizeof(unative_t));
852
 
7299 terminx 853
typedef struct MAY_ALIAS {
6072 hendricks2 854
    int32_t x, y;
855
} vec2_t;
856
 
7693 terminx 857
typedef struct MAY_ALIAS {
6263 hendricks2 858
    int16_t x, y;
7693 terminx 859
} vec2_16_t;
6263 hendricks2 860
 
861
typedef struct {
6072 hendricks2 862
    uint32_t x, y;
863
} vec2u_t;
864
 
865
typedef struct {
866
    float x, y;
867
} vec2f_t;
868
 
869
typedef struct {
7374 terminx 870
    double x, y;
871
} vec2d_t;
872
 
7693 terminx 873
typedef struct MAY_ALIAS {
7830 terminx 874
    union {
875
        struct { int32_t x, y, z; };
876
        vec2_t  vec2;
877
    };
7693 terminx 878
} vec3_t;
879
 
880
typedef struct MAY_ALIAS {
7830 terminx 881
    union {
882
        struct { int16_t x, y, z; };
883
        vec2_16_t vec2;
884
    };
7693 terminx 885
} vec3_16_t;
886
 
7374 terminx 887
typedef struct {
7830 terminx 888
    union {
889
        struct {
890
            union { float x, d; };
891
            union { float y, u; };
892
            union { float z, v; };
893
        };
894
        vec2f_t vec2;
895
    };
6072 hendricks2 896
} vec3f_t;
897
 
898
EDUKE32_STATIC_ASSERT(sizeof(vec3f_t) == sizeof(float) * 3);
899
 
900
typedef struct {
901
    union { double x; double d; };
902
    union { double y; double u; };
903
    union { double z; double v; };
904
} vec3d_t;
905
 
906
EDUKE32_STATIC_ASSERT(sizeof(vec3d_t) == sizeof(double) * 3);
907
 
6883 pogokeen 908
typedef struct {
909
    float x, y, z, w;
910
} vec4f_t;
6072 hendricks2 911
 
6883 pogokeen 912
typedef struct {
913
    float x, y, z, w;
914
} vec4d_t;
915
 
916
 
6078 hendricks2 917
////////// Language tricks that depend on size_t //////////
918
 
919
#if defined _MSC_VER
920
# define ARRAY_SIZE(arr) _countof(arr)
6115 hendricks2 921
#elif defined HAVE_CONSTEXPR
6078 hendricks2 922
template <typename T, size_t N>
923
static FORCE_INLINE constexpr size_t ARRAY_SIZE(T const (&)[N]) noexcept
924
{
925
    return N;
926
}
927
#elif defined __cplusplus
928
struct bad_arg_to_ARRAY_SIZE
929
{
930
   class Is_pointer; // incomplete
931
   class Is_array {};
932
   template <typename T>
933
   static Is_pointer check_type(const T*, const T* const*);
934
   static Is_array check_type(const void*, const void*);
935
};
936
# define ARRAY_SIZE(arr) ( \
937
 
938
 
939
   sizeof(arr) / sizeof((arr)[0]) )
940
#else
941
# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
942
#endif
6535 terminx 943
#define ARRAY_SSIZE(arr) (native_t)ARRAY_SIZE(arr)
6078 hendricks2 944
 
945
 
6072 hendricks2 946
////////// Memory management //////////
947
 
948
#if !defined NO_ALIGNED_MALLOC
6076 hendricks2 949
static FORCE_INLINE void *Baligned_alloc(const size_t alignment, const size_t size)
6072 hendricks2 950
{
951
#ifdef _WIN32
952
    void *ptr = _aligned_malloc(size, alignment);
953
#elif defined __APPLE__ || defined EDUKE32_BSD
954
    void *ptr = NULL;
955
    posix_memalign(&ptr, alignment, size);
956
#else
957
    void *ptr = memalign(alignment, size);
958
#endif
959
 
960
    return ptr;
961
}
962
#else
963
# define Baligned_alloc(alignment, size) Bmalloc(size)
964
#endif
965
 
966
#if defined _WIN32 && !defined NO_ALIGNED_MALLOC
967
# define Baligned_free _aligned_free
968
#else
7746 terminx 969
# define Baligned_free Bfree
6072 hendricks2 970
#endif
971
 
972
 
973
////////// Pointer management //////////
974
 
975
#define DO_FREE_AND_NULL(var) do { \
7705 terminx 976
    Xfree(var); (var) = NULL; \
6072 hendricks2 977
} while (0)
978
 
979
#define ALIGNED_FREE_AND_NULL(var) do { \
7705 terminx 980
    Xaligned_free(var); (var) = NULL; \
6072 hendricks2 981
} while (0)
982
 
983
 
984
////////// Data serialization //////////
985
 
7526 hendricks2 986
static FORCE_INLINE CONSTEXPR uint16_t B_SWAP16_impl(uint16_t value)
5173 hendricks2 987
{
6116 hendricks2 988
    return
989
        ((value & 0xFF00u) >> 8u) |
990
        ((value & 0x00FFu) << 8u);
5173 hendricks2 991
}
7526 hendricks2 992
static FORCE_INLINE CONSTEXPR uint32_t B_SWAP32_impl(uint32_t value)
5173 hendricks2 993
{
6116 hendricks2 994
    return
995
        ((value & 0xFF000000u) >> 24u) |
996
        ((value & 0x00FF0000u) >>  8u) |
997
        ((value & 0x0000FF00u) <<  8u) |
998
        ((value & 0x000000FFu) << 24u);
5173 hendricks2 999
}
7526 hendricks2 1000
static FORCE_INLINE CONSTEXPR uint64_t B_SWAP64_impl(uint64_t value)
4716 terminx 1001
{
6116 hendricks2 1002
    return
1003
      ((value & 0xFF00000000000000ULL) >> 56ULL) |
1004
      ((value & 0x00FF000000000000ULL) >> 40ULL) |
1005
      ((value & 0x0000FF0000000000ULL) >> 24ULL) |
1006
      ((value & 0x000000FF00000000ULL) >>  8ULL) |
1007
      ((value & 0x00000000FF000000ULL) <<  8ULL) |
1008
      ((value & 0x0000000000FF0000ULL) << 24ULL) |
1009
      ((value & 0x000000000000FF00ULL) << 40ULL) |
1010
      ((value & 0x00000000000000FFULL) << 56ULL);
4716 terminx 1011
}
5 Plagman 1012
 
7526 hendricks2 1013
/* The purpose of B_PASS* as functions, as opposed to macros, is to prevent them from being used as lvalues. */
7706 terminx 1014
#if CXXSTD >= 2011 || EDUKE32_MSVC_PREREQ(1900)
7526 hendricks2 1015
template <typename T>
7559 hendricks2 1016
static FORCE_INLINE CONSTEXPR take_sign_t<int16_t, T> B_SWAP16(T x)
7526 hendricks2 1017
{
7559 hendricks2 1018
    return static_cast< take_sign_t<int16_t, T> >(B_SWAP16_impl(static_cast<uint16_t>(x)));
7526 hendricks2 1019
}
1020
template <typename T>
7559 hendricks2 1021
static FORCE_INLINE CONSTEXPR take_sign_t<int32_t, T> B_SWAP32(T x)
7526 hendricks2 1022
{
7559 hendricks2 1023
    return static_cast< take_sign_t<int32_t, T> >(B_SWAP32_impl(static_cast<uint32_t>(x)));
7526 hendricks2 1024
}
1025
template <typename T>
7559 hendricks2 1026
static FORCE_INLINE CONSTEXPR take_sign_t<int64_t, T> B_SWAP64(T x)
7526 hendricks2 1027
{
7559 hendricks2 1028
    return static_cast< take_sign_t<int64_t, T> >(B_SWAP64_impl(static_cast<uint64_t>(x)));
7526 hendricks2 1029
}
1030
 
1031
template <typename T>
7559 hendricks2 1032
static FORCE_INLINE CONSTEXPR take_sign_t<int16_t, T> B_PASS16(T x)
7526 hendricks2 1033
{
7559 hendricks2 1034
    return static_cast< take_sign_t<int16_t, T> >(x);
7526 hendricks2 1035
}
1036
template <typename T>
7559 hendricks2 1037
static FORCE_INLINE CONSTEXPR take_sign_t<int32_t, T> B_PASS32(T x)
7526 hendricks2 1038
{
7559 hendricks2 1039
    return static_cast< take_sign_t<int32_t, T> >(x);
7526 hendricks2 1040
}
1041
template <typename T>
7559 hendricks2 1042
static FORCE_INLINE CONSTEXPR take_sign_t<int64_t, T> B_PASS64(T x)
7526 hendricks2 1043
{
7559 hendricks2 1044
    return static_cast< take_sign_t<int64_t, T> >(x);
7526 hendricks2 1045
}
1046
#else
1047
#define B_SWAP16(x) B_SWAP16_impl(x)
1048
#define B_SWAP32(x) B_SWAP32_impl(x)
1049
#define B_SWAP64(x) B_SWAP64_impl(x)
1050
 
6116 hendricks2 1051
static FORCE_INLINE CONSTEXPR uint16_t B_PASS16(uint16_t const x) { return x; }
1052
static FORCE_INLINE CONSTEXPR uint32_t B_PASS32(uint32_t const x) { return x; }
1053
static FORCE_INLINE CONSTEXPR uint64_t B_PASS64(uint64_t const x) { return x; }
7526 hendricks2 1054
#endif
5174 hendricks2 1055
 
6072 hendricks2 1056
#if B_LITTLE_ENDIAN == 1
1057
# define B_LITTLE64(x) B_PASS64(x)
1058
# define B_BIG64(x)    B_SWAP64(x)
1059
# define B_LITTLE32(x) B_PASS32(x)
1060
# define B_BIG32(x)    B_SWAP32(x)
1061
# define B_LITTLE16(x) B_PASS16(x)
1062
# define B_BIG16(x)    B_SWAP16(x)
1063
#elif B_BIG_ENDIAN == 1
1064
# define B_LITTLE64(x) B_SWAP64(x)
1065
# define B_BIG64(x)    B_PASS64(x)
1066
# define B_LITTLE32(x) B_SWAP32(x)
1067
# define B_BIG32(x)    B_PASS32(x)
1068
# define B_LITTLE16(x) B_SWAP16(x)
1069
# define B_BIG16(x)    B_PASS16(x)
1070
#endif
1071
 
5174 hendricks2 1072
// TODO: Determine when, if ever, we should use the bit-shift-and-mask variants
1073
// due to alignment issues or performance gains.
1074
#if 1
6076 hendricks2 1075
static FORCE_INLINE void B_BUF16(void * const buf, uint16_t const x) { *(uint16_t *) buf = x; }
1076
static FORCE_INLINE void B_BUF32(void * const buf, uint32_t const x) { *(uint32_t *) buf = x; }
1077
static FORCE_INLINE void B_BUF64(void * const buf, uint64_t const x) { *(uint64_t *) buf = x; }
5174 hendricks2 1078
 
7132 terminx 1079
static FORCE_INLINE CONSTEXPR uint16_t B_UNBUF16(void const * const buf) { return *(uint16_t const *) buf; }
1080
static FORCE_INLINE CONSTEXPR uint32_t B_UNBUF32(void const * const buf) { return *(uint32_t const *) buf; }
1081
static FORCE_INLINE CONSTEXPR uint64_t B_UNBUF64(void const * const buf) { return *(uint64_t const *) buf; }
5174 hendricks2 1082
#else
6076 hendricks2 1083
static FORCE_INLINE void B_BUF16(void * const vbuf, uint16_t const x)
4322 hendricks2 1084
{
5174 hendricks2 1085
    uint8_t * const buf = (uint8_t *) vbuf;
4322 hendricks2 1086
    buf[0] = (x & 0x00FF);
1087
    buf[1] = (x & 0xFF00) >> 8;
1088
}
6076 hendricks2 1089
static FORCE_INLINE void B_BUF32(void * const vbuf, uint32_t const x)
4322 hendricks2 1090
{
5174 hendricks2 1091
    uint8_t * const buf = (uint8_t *) vbuf;
4322 hendricks2 1092
    buf[0] = (x & 0x000000FF);
1093
    buf[1] = (x & 0x0000FF00) >> 8;
1094
    buf[2] = (x & 0x00FF0000) >> 16;
1095
    buf[3] = (x & 0xFF000000) >> 24;
1096
}
5174 hendricks2 1097
# if 0
4768 hendricks2 1098
// i686-apple-darwin11-llvm-gcc-4.2 complains "integer constant is too large for 'long' type"
6076 hendricks2 1099
static FORCE_INLINE void B_BUF64(void * const vbuf, uint64_t const x)
4322 hendricks2 1100
{
5174 hendricks2 1101
    uint8_t * const buf = (uint8_t *) vbuf;
4322 hendricks2 1102
    buf[0] = (x & 0x00000000000000FF);
1103
    buf[1] = (x & 0x000000000000FF00) >> 8;
1104
    buf[2] = (x & 0x0000000000FF0000) >> 16;
1105
    buf[3] = (x & 0x00000000FF000000) >> 24;
1106
    buf[4] = (x & 0x000000FF00000000) >> 32;
1107
    buf[5] = (x & 0x0000FF0000000000) >> 40;
1108
    buf[6] = (x & 0x00FF000000000000) >> 48;
1109
    buf[7] = (x & 0xFF00000000000000) >> 56;
1110
}
5174 hendricks2 1111
# endif
4322 hendricks2 1112
 
6076 hendricks2 1113
static FORCE_INLINE uint16_t B_UNBUF16(void const * const vbuf)
4716 terminx 1114
{
5174 hendricks2 1115
    uint8_t const * const buf = (uint8_t const *) vbuf;
1116
    return (buf[1] << 8) | (buf[0]);
1117
}
6076 hendricks2 1118
static FORCE_INLINE uint32_t B_UNBUF32(void const * const vbuf)
5174 hendricks2 1119
{
1120
    uint8_t const * const buf = (uint8_t const *) vbuf;
4716 terminx 1121
    return (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | (buf[0]);
1122
}
6076 hendricks2 1123
static FORCE_INLINE uint64_t B_UNBUF64(void const * const vbuf)
4716 terminx 1124
{
5174 hendricks2 1125
    uint8_t const * const buf = (uint8_t const *) vbuf;
4716 terminx 1126
    return ((uint64_t)buf[7] << 56) | ((uint64_t)buf[6] << 48) | ((uint64_t)buf[5] << 40) |
1127
        ((uint64_t)buf[4] << 32) | (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | (buf[0]);
1128
}
5174 hendricks2 1129
#endif
4322 hendricks2 1130
 
1454 terminx 1131
 
6072 hendricks2 1132
////////// Abstract data operations //////////
5 Plagman 1133
 
7132 terminx 1134
#define ABSTRACT_DECL static FORCE_INLINE WARN_UNUSED_RESULT CONSTEXPR
5 Plagman 1135
 
6293 terminx 1136
#ifdef __cplusplus
7078 terminx 1137
template <typename T, typename X, typename Y> ABSTRACT_DECL T clamp(T in, X min, Y max) { return in <= (T) min ? (T) min : (in >= (T) max ? (T) max : in); }
1138
template <typename T, typename X, typename Y> ABSTRACT_DECL T clamp2(T in, X min, Y max) { return in >= (T) max ? (T) max : (in <= (T) min ? (T) min : in); }
1139
using std::min;
1140
using std::max;
6293 terminx 1141
# define fclamp clamp
1142
# define fclamp2 clamp2
1143
#else
3780 helixhorne 1144
// Clamp <in> to [<min>..<max>]. The case in <= min is handled first.
7078 terminx 1145
ABSTRACT_DECL int32_t clamp(int32_t in, int32_t min, int32_t max) { return in <= min ? min : (in >= max ? max : in); }
1146
ABSTRACT_DECL float fclamp(float in, float min, float max) { return in <= min ? min : (in >= max ? max : in); }
3780 helixhorne 1147
// Clamp <in> to [<min>..<max>]. The case in >= max is handled first.
7078 terminx 1148
ABSTRACT_DECL int32_t clamp2(int32_t in, int32_t min, int32_t max) { return in >= max ? max : (in <= min ? min : in); }
1149
ABSTRACT_DECL float fclamp2(float in, float min, float max) { return in >= max ? max : (in <= min ? min : in); }
1150
 
1151
#ifndef min
1152
# define min(a, b) (((a) < (b)) ? (a) : (b))
6293 terminx 1153
#endif
7078 terminx 1154
#ifndef max
1155
# define max(a, b) (((a) > (b)) ? (a) : (b))
1156
#endif
1157
#endif
3780 helixhorne 1158
 
6119 hendricks2 1159
////////// Mathematical operations //////////
1160
 
1161
#ifdef __cplusplus
7557 hendricks2 1162
#ifdef HAVE_CXX11_HEADERS
6138 hendricks2 1163
template <typename T>
1164
struct DivResult
1165
{
1166
    T q; // quotient
1167
    T r; // remainder
1168
};
1169
template <typename T>
1170
FORCE_INLINE CONSTEXPR DivResult<T> divide(T lhs, T rhs)
1171
{
1172
    return DivResult<T>{(T)(lhs / rhs), (T)(lhs % rhs)};
1173
}
1174
template <native_t base, typename T>
1175
FORCE_INLINE CONSTEXPR DivResult<T> divrhs(T lhs)
1176
{
1177
    return divide(lhs, (T)base);
1178
}
8312 hendricks2 1179
 
1180
template <typename T, typename T2>
1181
static FORCE_INLINE CONSTEXPR_CXX14 enable_if_t<is_signed<T>::value, T> NEGATE_ON_CONDITION(T value, T2 condition)
1182
{
1183
    T const invert = !!condition;
1184
    return (value ^ -invert) + invert;
1185
}
6138 hendricks2 1186
#endif
1187
 
6119 hendricks2 1188
template <size_t base, typename T>
1189
CONSTEXPR size_t logbase(T n)
1190
{
1191
    return n < static_cast<T>(base) ? 1 : 1 + logbase<base>(n / static_cast<T>(base));
1192
}
1193
// hackish version to work around the impossibility of representing abs(INT*_MIN)
1194
template <size_t base, typename T>
1195
CONSTEXPR size_t logbasenegative(T n)
1196
{
1197
    return n > static_cast<T>(-(native_t)base) ? 1 : 1 + logbase<base>(n / static_cast<T>(-(native_t)base));
1198
}
1199
 
8312 hendricks2 1200
#endif
1201
 
6825 hendricks2 1202
#define isPow2OrZero(v) (((v) & ((v) - 1)) == 0)
1203
#define isPow2(v) (isPow2OrZero(v) && (v))
1204
 
7629 terminx 1205
////////// Bitfield manipulation //////////
6119 hendricks2 1206
 
8095 hendricks2 1207
static CONSTEXPR const char pow2char[8] = {1,2,4,8,16,32,64,128u};
7629 terminx 1208
 
7876 terminx 1209
static FORCE_INLINE void bitmap_set(uint8_t *const ptr, int const n) { ptr[n>>3] |= pow2char[n&7]; }
1210
static FORCE_INLINE void bitmap_clear(uint8_t *const ptr, int const n) { ptr[n>>3] &= ~pow2char[n&7]; }
1211
static FORCE_INLINE CONSTEXPR char bitmap_test(uint8_t const *const ptr, int const n) { return ptr[n>>3] & pow2char[n&7]; }
1212
 
6072 hendricks2 1213
////////// Utility functions //////////
4431 terminx 1214
 
7629 terminx 1215
// breadth-first search helpers
1216
template <typename T>
1217
void bfirst_search_init(T *const list, uint8_t *const bitmap, T *const eltnumptr, int const maxelts, int const firstelt)
1218
{
1219
    Bmemset(bitmap, 0, (maxelts+7)>>3);
1220
 
1221
    list[0] = firstelt;
1222
    bitmap_set(bitmap, firstelt);
1223
    *eltnumptr = 1;
1224
}
1225
 
1226
template <typename T>
1227
void bfirst_search_try(T *const list, uint8_t *const bitmap, T *const eltnumptr, int const elt)
1228
{
1229
    if (!bitmap_test(bitmap, elt))
1230
    {
1231
        bitmap_set(bitmap, elt);
1232
        list[(*eltnumptr)++] = elt;
1233
    }
1234
}
1235
 
6072 hendricks2 1236
#if RAND_MAX == 32767
6076 hendricks2 1237
static FORCE_INLINE uint16_t system_15bit_rand(void) { return (uint16_t)rand(); }
6072 hendricks2 1238
#else  // RAND_MAX > 32767, assumed to be of the form 2^k - 1
6076 hendricks2 1239
static FORCE_INLINE uint16_t system_15bit_rand(void) { return ((uint16_t)rand())&0x7fff; }
6072 hendricks2 1240
#endif
5 Plagman 1241
 
6072 hendricks2 1242
// Copy min(strlen(src)+1, n) characters into dst, always terminate with a NUL.
6076 hendricks2 1243
static FORCE_INLINE char *Bstrncpyz(char *dst, const char *src, bsize_t n)
6072 hendricks2 1244
{
1245
    Bstrncpy(dst, src, n);
1246
    dst[n-1] = 0;
1247
    return dst;
1248
}
1249
 
1250
// Append extension when <outbuf> contains no dot.
1251
// <ext> can be like ".mhk" or like "_crash.map", no need to start with a dot.
1252
// The ugly name is deliberate: we should be checking the sizes of all buffers!
1253
static inline void append_ext_UNSAFE(char *outbuf, const char *ext)
1254
{
1255
    char *p = Bstrrchr(outbuf,'.');
1256
 
1257
    if (!p)
1258
        Bstrcat(outbuf, ext);
1259
    else
1260
        Bstrcpy(p, ext);
1261
}
1262
 
1263
/* Begin dependence on compat.o object. */
1264
 
1265
 
1266
#ifdef __cplusplus
1267
extern "C" {
5075 terminx 1268
#endif
5 Plagman 1269
 
6072 hendricks2 1270
 
7359 hendricks2 1271
#ifndef USE_PHYSFS
6072 hendricks2 1272
////////// Directory enumeration //////////
1273
 
4716 terminx 1274
struct Bdirent
1275
{
1276
    char *name;
1277
    uint32_t mode;
1278
    uint32_t size;
1279
    uint32_t mtime;
7016 terminx 1280
    uint16_t namlen;
5 Plagman 1281
};
6072 hendricks2 1282
 
5 Plagman 1283
typedef void BDIR;
1284
 
4716 terminx 1285
BDIR *Bopendir(const char *name);
1286
struct Bdirent *Breaddir(BDIR *dir);
1287
int32_t Bclosedir(BDIR *dir);
7359 hendricks2 1288
#endif
5 Plagman 1289
 
1290
 
6072 hendricks2 1291
////////// Paths //////////
5 Plagman 1292
 
6072 hendricks2 1293
char *Bgethomedir(void);
1294
char *Bgetappdir(void);
4853 hendricks2 1295
 
6072 hendricks2 1296
int32_t Bcorrectfilename(char *filename, int32_t removefn);
1297
int32_t Bcanonicalisefilename(char *filename, int32_t removefn);
4853 hendricks2 1298
 
6072 hendricks2 1299
char *Bgetsystemdrives(void);
5257 hendricks2 1300
 
4853 hendricks2 1301
 
6072 hendricks2 1302
////////// String manipulation //////////
4853 hendricks2 1303
 
6072 hendricks2 1304
char *Bstrtoken(char *s, const char *delim, char **ptrptr, int chop);
1305
char *Bstrtolower(char *str);
4853 hendricks2 1306
 
6072 hendricks2 1307
#define Bwildmatch wildmatch
4853 hendricks2 1308
 
6072 hendricks2 1309
#ifdef _WIN32
7105 terminx 1310
# ifdef _MSC_VER
1311
#  define Bstrlwr _strlwr
1312
#  define Bstrupr _strupr
1313
# else
1314
#  define Bstrlwr strlwr
1315
#  define Bstrupr strupr
1316
# endif
6070 hendricks2 1317
#else
6072 hendricks2 1318
char *Bstrlwr(char *);
1319
char *Bstrupr(char *);
6070 hendricks2 1320
#endif
5 Plagman 1321
 
6072 hendricks2 1322
////////// Miscellaneous //////////
1323
 
8072 terminx 1324
int Bgetpagesize(void);
8188 terminx 1325
size_t Bgetsysmemsize(void);
5 Plagman 1326
 
6072 hendricks2 1327
////////// PANICKING ALLOCATION WRAPPERS //////////
3735 helixhorne 1328
 
4490 helixhorne 1329
#ifdef DEBUGGINGAIDS
1330
extern void xalloc_set_location(int32_t line, const char *file, const char *func);
1331
#endif
1332
void set_memerr_handler(void (*handlerfunc)(int32_t, const char *, const char *));
7095 terminx 1333
void *handle_memerr(void *);
4490 helixhorne 1334
 
6076 hendricks2 1335
static FORCE_INLINE char *xstrdup(const char *s)
4619 terminx 1336
{
1337
    char *ptr = Bstrdup(s);
7660 terminx 1338
    return (EDUKE32_PREDICT_TRUE(ptr != NULL)) ? ptr : (char *)handle_memerr(ptr);
4619 terminx 1339
}
1340
 
6076 hendricks2 1341
static FORCE_INLINE void *xmalloc(const bsize_t size)
4619 terminx 1342
{
1343
    void *ptr = Bmalloc(size);
7660 terminx 1344
    return (EDUKE32_PREDICT_TRUE(ptr != NULL)) ? ptr : handle_memerr(ptr);
4619 terminx 1345
}
1346
 
6076 hendricks2 1347
static FORCE_INLINE void *xcalloc(const bsize_t nmemb, const bsize_t size)
4619 terminx 1348
{
1349
    void *ptr = Bcalloc(nmemb, size);
7660 terminx 1350
    return (EDUKE32_PREDICT_TRUE(ptr != NULL)) ? ptr : handle_memerr(ptr);
4619 terminx 1351
}
1352
 
6076 hendricks2 1353
static FORCE_INLINE void *xrealloc(void * const ptr, const bsize_t size)
4619 terminx 1354
{
1355
    void *newptr = Brealloc(ptr, size);
1356
 
1357
    // According to the C Standard,
1358
    //  - ptr == NULL makes realloc() behave like malloc()
1359
    //  - size == 0 make it behave like free() if ptr != NULL
1360
    // Since we want to catch an out-of-mem in the first case, this leaves:
7660 terminx 1361
    return (EDUKE32_PREDICT_TRUE(newptr != NULL || size == 0)) ? newptr: handle_memerr(ptr);
4619 terminx 1362
}
1363
 
5636 hendricks2 1364
#if !defined NO_ALIGNED_MALLOC
6076 hendricks2 1365
static FORCE_INLINE void *xaligned_alloc(const bsize_t alignment, const bsize_t size)
4695 terminx 1366
{
6072 hendricks2 1367
    void *ptr = Baligned_alloc(alignment, size);
7660 terminx 1368
    return (EDUKE32_PREDICT_TRUE(ptr != NULL)) ? ptr : handle_memerr(ptr);
4695 terminx 1369
}
8371 terminx 1370
 
1371
static FORCE_INLINE void *xaligned_calloc(const bsize_t alignment, const bsize_t count, const bsize_t size)
1372
{
1373
    bsize_t const blocksize = count * size;
1374
    void *ptr = Baligned_alloc(alignment, blocksize);
1375
    if (EDUKE32_PREDICT_TRUE(ptr != NULL))
1376
    {
1377
        Bmemset(ptr, 0, blocksize);
1378
        return ptr;
1379
    }
1380
    return handle_memerr(ptr);
1381
}
6072 hendricks2 1382
#else
1383
# define xaligned_alloc(alignment, size) xmalloc(size)
8371 terminx 1384
# define xaligned_calloc(alignment, count, size) xcalloc(count, size)
5636 hendricks2 1385
#endif
4695 terminx 1386
 
4490 helixhorne 1387
#ifdef DEBUGGINGAIDS
7661 terminx 1388
# define EDUKE32_PRE_XALLOC xalloc_set_location(__LINE__, __FILE__, EDUKE32_FUNCTION),
4490 helixhorne 1389
#else
7661 terminx 1390
# define EDUKE32_PRE_XALLOC
4490 helixhorne 1391
#endif
4695 terminx 1392
 
7661 terminx 1393
#define Xstrdup(s)    (EDUKE32_PRE_XALLOC xstrdup(s))
1394
#define Xmalloc(size) (EDUKE32_PRE_XALLOC xmalloc(size))
1395
#define Xcalloc(nmemb, size) (EDUKE32_PRE_XALLOC xcalloc(nmemb, size))
1396
#define Xrealloc(ptr, size)  (EDUKE32_PRE_XALLOC xrealloc(ptr, size))
1397
#define Xaligned_alloc(alignment, size) (EDUKE32_PRE_XALLOC xaligned_alloc(alignment, size))
8371 terminx 1398
#define Xaligned_calloc(alignment, count, size) (EDUKE32_PRE_XALLOC xaligned_calloc(alignment, count, size))
8273 hendricks2 1399
#define Xfree(ptr) (Bfree(ptr))
1400
#define Xaligned_free(ptr) (Baligned_free(ptr))
8179 terminx 1401
 
6072 hendricks2 1402
#ifdef __cplusplus
1403
}
5706 hendricks2 1404
#endif
1405
 
4695 terminx 1406
 
6072 hendricks2 1407
////////// More utility functions //////////
1408
 
5139 hendricks2 1409
static inline void maybe_grow_buffer(char ** const buffer, int32_t * const buffersize, int32_t const newsize)
1410
{
1411
    if (newsize > *buffersize)
1412
    {
1413
        *buffer = (char *)Xrealloc(*buffer, newsize);
1414
        *buffersize = newsize;
1415
    }
1416
}
1417
 
4490 helixhorne 1418
 
6072 hendricks2 1419
////////// Inlined external libraries //////////
1420
 
6177 hendricks2 1421
#ifndef LIBDIVIDE_BODY
1422
# define LIBDIVIDE_HEADER_ONLY
1423
#endif
1424
#define LIBDIVIDE_C_HEADERS
1425
#define LIBDIVIDE_NONAMESPACE
1426
#define LIBDIVIDE_NOINLINE
7186 terminx 1427
#include "fix16.h"
6072 hendricks2 1428
#include "libdivide.h"
8050 pogokeen 1429
#include "clockticks.hpp"
8179 terminx 1430
#include "debugbreak.h"
1431
 
1432
#include "zpl.h"
1433
 
6072 hendricks2 1434
/* End dependence on compat.o object. */
1435
 
1436
 
1437
////////// EDuke32-specific features //////////
1438
 
1439
#ifndef TRUE
1440
# define TRUE 1
1441
#endif
1442
 
1443
#ifndef FALSE
1444
# define FALSE 0
1445
#endif
1446
 
1447
#define WITHKPLIB
1448
 
1449
#if defined __ANDROID__ || defined EDUKE32_IOS
1450
# define EDUKE32_TOUCH_DEVICES
1451
# define EDUKE32_GLES
1452
#endif
1453
 
1454
#if DEBUGGINGAIDS>=2
1455
# define DEBUG_MAIN_ARRAYS
1456
#endif
1457
 
1458
#if !defined DEBUG_MAIN_ARRAYS
1459
# define HAVE_CLIPSHAPE_FEATURE
1460
#endif
1461
 
4747 terminx 1462
#endif // compat_h_