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