Subversion Repositories eduke32

Rev

Rev 4747 | 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
 
4685 hendricks2 8
#ifdef __GNUC__
4762 hendricks2 9
# define EDUKE32_GCC_PREREQ(major, minor) (major < __GNUC__ || (major == __GNUC__ && minor <= __GNUC_MINOR__))
4685 hendricks2 10
#else
11
# define EDUKE32_GCC_PREREQ(major, minor) 0
12
#endif
13
 
14
#ifdef __clang__
4762 hendricks2 15
# define EDUKE32_CLANG_PREREQ(major, minor) (major < __clang_major__ || (major == __clang_major__ && minor <= __clang_minor__))
4685 hendricks2 16
#else
17
# define EDUKE32_CLANG_PREREQ(major, minor) 0
18
#endif
19
#ifndef __has_builtin
20
# define __has_builtin(x) 0  // Compatibility with non-clang compilers.
21
#endif
22
#ifndef __has_feature
23
# define __has_feature(x) 0  // Compatibility with non-clang compilers.
24
#endif
25
#ifndef __has_extension
26
# define __has_extension __has_feature // Compatibility with pre-3.0 compilers.
27
#endif
28
 
4697 terminx 29
#ifdef UNREFERENCED_PARAMETER
30
#undef UNREFERENCED_PARAMETER
654 terminx 31
#endif
32
 
4697 terminx 33
#define UNREFERENCED_PARAMETER(x) x = x
34
 
1743 helixhorne 35
#if defined __GNUC__ || defined __clang__
36
# define ATTRIBUTE(attrlist) __attribute__(attrlist)
37
#else
38
# define ATTRIBUTE(attrlist)
39
#endif
40
 
3341 helixhorne 41
#if !defined __clang__ && !defined USING_LTO
42
# define ATTRIBUTE_OPTIMIZE(str) ATTRIBUTE((optimize(str)))
43
#else
44
# define ATTRIBUTE_OPTIMIZE(str)
45
#endif
46
 
4685 hendricks2 47
#if defined __GNUC__ || __has_builtin(__builtin_expect)
4680 terminx 48
#define EDUKE32_PREDICT_TRUE(x)       __builtin_expect(!!(x),1)
49
#define EDUKE32_PREDICT_FALSE(x)     __builtin_expect(!!(x),0)
4685 hendricks2 50
#else
51
#define EDUKE32_PREDICT_TRUE(x) (x)
52
#define EDUKE32_PREDICT_FALSE(x) (x)
53
#endif
54
 
55
#if EDUKE32_GCC_PREREQ(4,5)  || __has_builtin(__builtin_unreachable)
4680 terminx 56
#define EDUKE32_UNREACHABLE_SECTION(...)   __builtin_unreachable()
57
#elif _MSC_VER
58
#define EDUKE32_UNREACHABLE_SECTION(...)   __assume(0)
4685 hendricks2 59
#else
4680 terminx 60
#define EDUKE32_UNREACHABLE_SECTION(...) __VA_ARGS__
61
#endif
62
 
3180 helixhorne 63
#ifndef min
64
#define min(x,y) ((x) < (y) ? (x) : (y))
65
#endif
66
#ifndef max
67
#define max(x,y) ((x) > (y) ? (x) : (y))
68
#endif
69
 
4762 hendricks2 70
#ifndef __APPLE__
71
# include <malloc.h>
72
#endif
73
 
74
#ifdef _WIN32
75
# define WIN32_LEAN_AND_MEAN
76
# include <windows.h>
77
#endif
78
 
79
#ifdef __APPLE__
80
# include <TargetConditionals.h>
81
# if !TARGET_OS_IPHONE
82
#  if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_3
83
#   include <CoreFoundation/CoreFoundation.h>
84
#  endif
85
#  include <CoreServices/CoreServices.h>
86
# endif
87
#endif
88
 
618 terminx 89
// This gives us access to 'intptr_t' and 'uintptr_t', which are
90
// abstractions to the size of a pointer on a given platform
91
// (ie, they're guaranteed to be the same size as a pointer)
3116 hendricks2 92
 
4078 hendricks2 93
#undef __USE_MINGW_ANSI_STDIO // Workaround for MinGW-w64.
94
 
4762 hendricks2 95
#ifndef __STDC_FORMAT_MACROS
3116 hendricks2 96
#define __STDC_FORMAT_MACROS
4762 hendricks2 97
#endif
4540 hendricks2 98
#ifndef __STDC_LIMIT_MACROS
4708 helixhorne 99
# define __STDC_LIMIT_MACROS
4540 hendricks2 100
#endif
4619 terminx 101
#if defined(HAVE_INTTYPES) || defined(__cplusplus)
4708 helixhorne 102
# include <stdint.h>
103
# include <inttypes.h>
3496 hendricks2 104
 
105
// Ghetto. Blame devkitPPC's faulty headers.
4708 helixhorne 106
# ifdef GEKKO
3496 hendricks2 107
#  undef PRIdPTR
108
#  define PRIdPTR "d"
109
#  undef PRIxPTR
110
#  define PRIxPTR "x"
111
#  undef SCNx32
112
#  define SCNx32 "x"
4708 helixhorne 113
# endif
3496 hendricks2 114
 
795 terminx 115
#elif defined(_MSC_VER)
4708 helixhorne 116
# include "msvc/inttypes.h" // from http://code.google.com/p/msinttypes/
618 terminx 117
#endif
118
 
1435 terminx 119
#ifndef _MSC_VER
3278 hendricks2 120
#  ifndef __fastcall
121
#    if defined(__GNUC__) && defined(__i386__)
2992 helixhorne 122
#      define __fastcall __attribute__((fastcall))
3278 hendricks2 123
#    else
124
#      define __fastcall
2992 helixhorne 125
#    endif
126
#  endif
1435 terminx 127
#endif
128
 
1346 terminx 129
#ifndef TRUE
2992 helixhorne 130
#  define TRUE 1
1346 terminx 131
#endif
132
 
133
#ifndef FALSE
2992 helixhorne 134
#  define FALSE 0
1346 terminx 135
#endif
136
 
1592 terminx 137
#define WITHKPLIB
138
 
4658 terminx 139
#include "libdivide.h"
140
 
5 Plagman 141
// Define this to rewrite all 'B' versions to library functions. This
142
// is for platforms which give us a standard sort of C library so we
143
// link directly. Platforms like PalmOS which don't have a standard C
144
// library will need to wrap these functions with suitable emulations.
4747 terminx 145
#define compat_h_macrodef__
5 Plagman 146
 
3116 hendricks2 147
#ifdef EXTERNC
285 terminx 148
#  include <cstdarg>
4747 terminx 149
#  ifdef compat_h_macrodef__
285 terminx 150
#   include <cstdio>
151
#   include <cstring>
152
#   include <cstdlib>
153
#   include <ctime>
154
#  endif
5 Plagman 155
#else
156
# include <stdarg.h>
1660 terminx 157
# include <stddef.h>
5 Plagman 158
#endif
159
 
4747 terminx 160
#ifdef compat_h_macrodef__
3116 hendricks2 161
# ifndef EXTERNC
5 Plagman 162
#  include <stdio.h>
163
#  include <string.h>
164
#  include <stdlib.h>
165
#  include <time.h>
166
# endif
167
# include <fcntl.h>
168
# include <ctype.h>
169
# include <sys/types.h>
170
# include <sys/stat.h>
171
# include <errno.h>
172
# if defined(_WIN32)
173
#  include <io.h>
174
# else
175
#  include <unistd.h>
176
# endif
177
#endif
178
 
2481 helixhorne 179
#include <assert.h>
180
 
5 Plagman 181
#ifdef EFENCE
182
# include <efence.h>
2254 helixhorne 183
#elif defined DMALLOC
184
# include <dmalloc.h>
5 Plagman 185
#endif
186
 
1454 terminx 187
#if defined(_MSC_VER)
4708 helixhorne 188
# include <direct.h>
5 Plagman 189
# define longlong(x) x##i64
4708 helixhorne 190
# if _MSC_VER < 1800
191
#  define inline __inline
192
# endif
5 Plagman 193
#else
194
# define longlong(x) x##ll
195
#endif
196
 
4606 terminx 197
#if defined(__arm__)
4708 helixhorne 198
# define Bsqrt __sqrt
199
# define Bsqrtf __sqrtf
4606 terminx 200
#else
4708 helixhorne 201
# define Bsqrt sqrt
202
# define Bsqrtf sqrtf
4606 terminx 203
#endif
204
 
5 Plagman 205
#ifndef NULL
206
# define NULL ((void *)0)
207
#endif
208
 
2270 helixhorne 209
#if DEBUGGINGAIDS>=2
210
# define DEBUG_MAIN_ARRAYS
211
#endif
212
 
4743 terminx 213
#ifndef FORCE_INLINE
214
# ifdef _MSC_VER    // Visual Studio
215
#  define FORCE_INLINE static __forceinline
216
# else
217
#  ifdef __GNUC__
218
#    define FORCE_INLINE static inline __attribute__((always_inline))
219
#  else
220
#    define FORCE_INLINE static inline
221
#  endif
222
# endif
223
#endif
224
 
3116 hendricks2 225
#ifndef DISABLE_INLINING
226
# define EXTERN_INLINE static inline
227
# define EXTERN_INLINE_HEADER static inline
228
#else
4247 hendricks2 229
# define EXTERN_INLINE __fastcall
230
# define EXTERN_INLINE_HEADER extern __fastcall
3116 hendricks2 231
#endif
232
 
2495 hendricks2 233
#if !defined DEBUG_MAIN_ARRAYS
234
# define HAVE_CLIPSHAPE_FEATURE
235
#endif
236
 
1935 helixhorne 237
// redefined for apple/ppc, which chokes on stderr when linking...
238
#define ERRprintf(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__)
239
 
5 Plagman 240
#if defined(__linux)
241
# include <endian.h>
242
# if __BYTE_ORDER == __LITTLE_ENDIAN
243
#  define B_LITTLE_ENDIAN 1
244
#  define B_BIG_ENDIAN    0
245
# elif __BYTE_ORDER == __BIG_ENDIAN
246
#  define B_LITTLE_ENDIAN 0
247
#  define B_BIG_ENDIAN    1
248
# endif
249
# define B_ENDIAN_C_INLINE 1
250
 
2916 terminx 251
#elif defined(GEKKO) || defined(__ANDROID__)
2630 helixhorne 252
# define B_LITTLE_ENDIAN 0
253
# define B_BIG_ENDIAN 1
254
# define B_ENDIAN_C_INLINE 1
255
 
2916 terminx 256
#elif defined(__OpenBSD__)
257
# include <machine/endian.h>
258
# if _BYTE_ORDER == _LITTLE_ENDIAN
259
#  define B_LITTLE_ENDIAN 1
260
#  define B_BIG_ENDIAN    0
261
# elif _BYTE_ORDER == _BIG_ENDIAN
262
#  define B_LITTLE_ENDIAN 0
263
#  define B_BIG_ENDIAN    1
264
# endif
265
# define B_SWAP64(x) __swap64(x)
266
# define B_SWAP32(x) __swap32(x)
267
# define B_SWAP16(x) __swap16(x)
268
 
269
#elif defined(__FreeBSD__) || defined(__NetBSD__)
5 Plagman 270
# include <sys/endian.h>
271
# if _BYTE_ORDER == _LITTLE_ENDIAN
272
#  define B_LITTLE_ENDIAN 1
273
#  define B_BIG_ENDIAN    0
274
# elif _BYTE_ORDER == _BIG_ENDIAN
275
#  define B_LITTLE_ENDIAN 0
276
#  define B_BIG_ENDIAN    1
277
# endif
278
# define B_SWAP64(x) __bswap64(x)
279
# define B_SWAP32(x) __bswap32(x)
280
# define B_SWAP16(x) __bswap16(x)
281
 
282
#elif defined(__APPLE__)
4708 helixhorne 283
# if !defined __x86_64__ && defined __GNUC__
1935 helixhorne 284
// PK 20110617: is*() crashes for me in x86 code compiled from 64-bit, and gives link errors on ppc
1905 helixhorne 285
//              This hack patches all occurences.
1907 helixhorne 286
#  define isdigit(ch) ({ int32_t c__dontuse_=ch; c__dontuse_>='0' && c__dontuse_<='9'; })
287
#  define isalpha(ch) ({ int32_t c__dontuse2_=ch; (c__dontuse2_>='A' && c__dontuse2_<='Z') || (c__dontuse2_>='a' && c__dontuse2_<='z'); })
288
#  define isalnum(ch2)  ({ int32_t c2__dontuse_=ch2; isalpha(c2__dontuse_) || isdigit(c2__dontuse_); })
1935 helixhorne 289
#  if defined __BIG_ENDIAN__
290
#    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'); })
291
#    define isprint(ch)  ({ int32_t c__dontuse_=ch; (c__dontuse_>=0x20 && c__dontuse_<0x7f); })
292
#    undef ERRprintf
293
#    define ERRprintf(fmt, ...) printf(fmt, ## __VA_ARGS__)
294
#  endif
1905 helixhorne 295
# endif
5 Plagman 296
# if defined(__LITTLE_ENDIAN__)
297
#  define B_LITTLE_ENDIAN 1
298
#  define B_BIG_ENDIAN    0
299
# elif defined(__BIG_ENDIAN__)
300
#  define B_LITTLE_ENDIAN 0
301
#  define B_BIG_ENDIAN    1
302
# endif
303
# include <libkern/OSByteOrder.h>
304
# define B_SWAP64(x) OSSwapConstInt64(x)
305
# define B_SWAP32(x) OSSwapConstInt32(x)
306
# define B_SWAP16(x) OSSwapConstInt16(x)
307
 
308
#elif defined(__BEOS__)
309
# include <posix/endian.h>
310
# if LITTLE_ENDIAN != 0
311
#  define B_LITTLE_ENDIAN 1
312
#  define B_BIG_ENDIAN    0
313
# elif BIG_ENDIAN != 0
314
#  define B_LITTLE_ENDIAN 0
315
#  define B_BIG_ENDIAN    1
316
# endif
317
# define B_ENDIAN_C_INLINE 1
318
 
319
#elif defined(__QNX__)
320
# if defined __LITTLEENDIAN__
321
#  define B_LITTLE_ENDIAN 1
322
#  define B_BIG_ENDIAN    0
323
# elif defined __BIGENDIAN__
324
#  define B_LITTLE_ENDIAN 0
325
#  define B_BIG_ENDIAN    1
326
# endif
327
# define B_ENDIAN_C_INLINE 1
328
 
329
#elif defined(__sun)
330
# if defined _LITTLE_ENDIAN
331
#  define B_LITTLE_ENDIAN 1
332
#  define B_BIG_ENDIAN    0
333
# elif defined _BIG_ENDIAN
334
#  define B_LITTLE_ENDIAN 0
335
#  define B_BIG_ENDIAN    1
336
# endif
337
# define B_ENDIAN_C_INLINE 1
338
 
339
#elif defined(_WIN32) || defined(SKYOS) || defined(__SYLLABLE__)
340
# define B_LITTLE_ENDIAN 1
341
# define B_BIG_ENDIAN    0
342
# define B_ENDIAN_C_INLINE 1
343
#endif
344
 
345
#if !defined(B_LITTLE_ENDIAN) || !defined(B_BIG_ENDIAN)
346
# error Unknown endianness
347
#endif
348
 
4274 hendricks2 349
#if defined _LP64 || defined __LP64__ || defined __64BIT__ || _ADDR64 || defined _WIN64 || defined __arch64__ || __WORDSIZE == 64 || (defined __sparc && defined __sparcv9) || defined __x86_64 || defined __amd64 || defined __x86_64__ || defined __amd64__ || defined _M_X64 || defined _M_IA64 || defined __ia64 || defined __IA64__
350
# define BITNESS64
351
#endif
352
 
3116 hendricks2 353
#ifdef EXTERNC
285 terminx 354
 
355
# ifndef SCREWED_UP_CPP
1124 terminx 356
//   using namespace std;
285 terminx 357
# endif
358
 
5 Plagman 359
extern "C" {
360
#endif
361
 
362
#if defined B_ENDIAN_X86_INLINE
363
# if defined(_MSC_VER)
364
        // inline asm using bswap/xchg
365
# elif defined(__GNUC__)
366
        // inline asm using bswap/xchg
367
# endif
368
#elif defined B_ENDIAN_C_INLINE
4743 terminx 369
FORCE_INLINE uint16_t B_SWAP16(uint16_t s) { return (s >> 8) | (s << 8); }
370
FORCE_INLINE uint32_t B_SWAP32(uint32_t l)
4716 terminx 371
{
372
    return ((l >> 8) & 0xff00) | ((l & 0xff00) << 8) | (l << 24) | (l >> 24);
373
}
4743 terminx 374
FORCE_INLINE uint64_t B_SWAP64(uint64_t l)
4716 terminx 375
{
376
    return (l >> 56) | ((l >> 40) & 0xff00) | ((l >> 24) & 0xff0000) | ((l >> 8) & 0xff000000) |
377
        ((l & 255) << 56) | ((l & 0xff00) << 40) | ((l & 0xff0000) << 24) | ((l & 0xff000000) << 8);
378
}
5 Plagman 379
#endif
380
 
4743 terminx 381
FORCE_INLINE void B_BUF16(uint8_t *buf, uint16_t x)
4322 hendricks2 382
{
383
    buf[0] = (x & 0x00FF);
384
    buf[1] = (x & 0xFF00) >> 8;
385
}
4743 terminx 386
FORCE_INLINE void B_BUF32(uint8_t *buf, uint32_t x)
4322 hendricks2 387
{
388
    buf[0] = (x & 0x000000FF);
389
    buf[1] = (x & 0x0000FF00) >> 8;
390
    buf[2] = (x & 0x00FF0000) >> 16;
391
    buf[3] = (x & 0xFF000000) >> 24;
392
}
4743 terminx 393
FORCE_INLINE void B_BUF64(uint8_t *buf, uint64_t x)
4322 hendricks2 394
{
395
    buf[0] = (x & 0x00000000000000FF);
396
    buf[1] = (x & 0x000000000000FF00) >> 8;
397
    buf[2] = (x & 0x0000000000FF0000) >> 16;
398
    buf[3] = (x & 0x00000000FF000000) >> 24;
399
    buf[4] = (x & 0x000000FF00000000) >> 32;
400
    buf[5] = (x & 0x0000FF0000000000) >> 40;
401
    buf[6] = (x & 0x00FF000000000000) >> 48;
402
    buf[7] = (x & 0xFF00000000000000) >> 56;
403
}
404
 
4743 terminx 405
FORCE_INLINE uint16_t B_UNBUF16(const uint8_t *buf) { return (buf[1] << 8) | (buf[0]); }
406
FORCE_INLINE uint32_t B_UNBUF32(const uint8_t *buf)
4716 terminx 407
{
408
    return (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | (buf[0]);
409
}
4743 terminx 410
FORCE_INLINE uint64_t B_UNBUF64(const uint8_t *buf)
4716 terminx 411
{
412
    return ((uint64_t)buf[7] << 56) | ((uint64_t)buf[6] << 48) | ((uint64_t)buf[5] << 40) |
413
        ((uint64_t)buf[4] << 32) | (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | (buf[0]);
414
}
4322 hendricks2 415
 
4716 terminx 416
#if defined (BITNESS64)
4658 terminx 417
#include <emmintrin.h>
4743 terminx 418
FORCE_INLINE int32_t Blrintf(const float x)
1454 terminx 419
{
4658 terminx 420
    __m128 xx = _mm_load_ss(&x);
421
    return _mm_cvtss_si32(xx);
1454 terminx 422
}
4658 terminx 423
#elif defined (_MSC_VER)
4743 terminx 424
FORCE_INLINE int32_t Blrintf(const float x)
1454 terminx 425
{
4658 terminx 426
    int n;
427
    __asm fld x;
428
    __asm fistp n;
429
    return n;
1454 terminx 430
}
431
#else
4685 hendricks2 432
#include <math.h>
4658 terminx 433
#define Blrintf lrintf
1454 terminx 434
#endif
435
 
5 Plagman 436
#if B_LITTLE_ENDIAN == 1
437
# define B_LITTLE64(x) (x)
438
# define B_BIG64(x)    B_SWAP64(x)
439
# define B_LITTLE32(x) (x)
440
# define B_BIG32(x)    B_SWAP32(x)
441
# define B_LITTLE16(x) (x)
442
# define B_BIG16(x)    B_SWAP16(x)
443
#elif B_BIG_ENDIAN == 1
444
# define B_LITTLE64(x) B_SWAP64(x)
445
# define B_BIG64(x)    (x)
446
# define B_LITTLE32(x) B_SWAP32(x)
447
# define B_BIG32(x)    (x)
448
# define B_LITTLE16(x) B_SWAP16(x)
449
# define B_BIG16(x)    (x)
450
#endif
451
 
452
#ifndef FP_OFF
714 qbix79 453
# define FP_OFF(__p) ((uintptr_t)(__p))
5 Plagman 454
#endif
455
 
4747 terminx 456
#ifdef compat_h_macrodef__
5 Plagman 457
 
458
# ifndef O_BINARY
459
#  define O_BINARY 0
460
# endif
461
# ifndef O_TEXT
462
#  define O_TEXT 0
463
# endif
464
 
465
# ifndef F_OK
466
#  define F_OK 0
467
# endif
468
 
469
# define BO_BINARY O_BINARY
470
# define BO_TEXT   O_TEXT
471
# define BO_RDONLY O_RDONLY
472
# define BO_WRONLY O_WRONLY
473
# define BO_RDWR   O_RDWR
474
# define BO_APPEND O_APPEND
475
# define BO_CREAT  O_CREAT
476
# define BO_TRUNC  O_TRUNC
477
# define BS_IRGRP  S_IRGRP
478
# define BS_IWGRP  S_IWGRP
479
# define BS_IEXEC  S_IEXEC
2916 terminx 480
# ifdef __ANDROID__
481
#  define BS_IWRITE S_IWUSR
482
#  define BS_IREAD  S_IRUSR
483
# else
484
#  define BS_IWRITE S_IWRITE
485
#  define BS_IREAD  S_IREAD
486
# endif
5 Plagman 487
# define BS_IFIFO  S_IFIFO
488
# define BS_IFCHR  S_IFCHR
489
# define BS_IFBLK  S_IFBLK
490
# define BS_IFDIR  S_IFDIR
491
# define BS_IFREG  S_IFREG
492
# define BSEEK_SET SEEK_SET
493
# define BSEEK_CUR SEEK_CUR
494
# define BSEEK_END SEEK_END
495
#else
496
# define BO_BINARY 0
497
# define BO_TEXT   1
498
# define BO_RDONLY 2
499
# define BO_WRONLY 4
500
# define BO_RDWR   6
501
# define BO_APPEND 8
502
# define BO_CREAT  16
503
# define BO_TRUNC  32
504
# define BS_IRGRP  0
505
# define BS_IWGRP  0
506
# define BS_IEXEC  1
507
# define BS_IWRITE 2
508
# define BS_IREAD  4
509
# define BS_IFIFO  0x1000
510
# define BS_IFCHR  0x2000
511
# define BS_IFBLK  0x3000
512
# define BS_IFDIR  0x4000
513
# define BS_IFREG  0x8000
514
# define BSEEK_SET 0
515
# define BSEEK_CUR 1
516
# define BSEEK_END 2
517
#endif
518
 
519
#ifdef UNDERSCORES
520
# define ASMSYM(x) "_" x
521
#else
522
# define ASMSYM(x) x
523
#endif
524
 
525
#ifndef min
4716 terminx 526
# define min(a, b) (((a) < (b)) ? (a) : (b))
5 Plagman 527
#endif
528
 
529
#ifndef max
4716 terminx 530
# define max(a, b) (((a) > (b)) ? (a) : (b))
5 Plagman 531
#endif
532
 
1854 helixhorne 533
#if __GNUC__ >= 4
4743 terminx 534
# define CLAMP_DECL FORCE_INLINE __attribute__((warn_unused_result))
1854 helixhorne 535
#else
4743 terminx 536
# define CLAMP_DECL FORCE_INLINE
1854 helixhorne 537
#endif
3780 helixhorne 538
 
539
// Clamp <in> to [<min>..<max>]. The case in <= min is handled first.
540
CLAMP_DECL int32_t clamp(int32_t in, int32_t min, int32_t max)
1852 helixhorne 541
{
2412 helixhorne 542
    return in <= min ? min : (in >= max ? max : in);
1852 helixhorne 543
}
5 Plagman 544
 
3780 helixhorne 545
// Clamp <in> to [<min>..<max>]. The case in >= max is handled first.
546
CLAMP_DECL int32_t clamp2(int32_t in, int32_t min, int32_t max)
547
{
548
    return in >= max ? max : (in <= min ? min : in);
549
}
550
 
4431 terminx 551
// Clamp <in> to [<min>..<max>]. The case in <= min is handled first.
552
CLAMP_DECL float fclamp(float in, float min, float max)
553
{
554
    return in <= min ? min : (in >= max ? max : in);
555
}
556
 
557
// Clamp <in> to [<min>..<max>]. The case in >= max is handled first.
558
CLAMP_DECL float fclamp2(float in, float min, float max)
559
{
560
    return in >= max ? max : (in <= min ? min : in);
561
}
562
 
1457 terminx 563
#define BMAX_PATH 256
5 Plagman 564
 
565
 
4716 terminx 566
struct Bdirent
567
{
568
    uint16_t namlen;
569
    char *name;
570
    uint32_t mode;
571
    uint32_t size;
572
    uint32_t mtime;
5 Plagman 573
};
574
typedef void BDIR;
575
 
4716 terminx 576
BDIR *Bopendir(const char *name);
577
struct Bdirent *Breaddir(BDIR *dir);
578
int32_t Bclosedir(BDIR *dir);
5 Plagman 579
 
3411 terminx 580
#ifdef _MSC_VER
581
typedef intptr_t ssize_t;
582
#endif
5 Plagman 583
 
4747 terminx 584
#ifdef compat_h_macrodef__
285 terminx 585
  typedef FILE BFILE;
5 Plagman 586
# define bsize_t size_t
587
# define bssize_t ssize_t
588
#else
285 terminx 589
  typedef void          BFILE;
1205 terminx 590
  typedef uint32_t bsize_t;
1346 terminx 591
  typedef int32_t bssize_t;
5 Plagman 592
#endif
593
 
2105 helixhorne 594
#if RAND_MAX == 32767
4743 terminx 595
FORCE_INLINE uint16_t system_15bit_rand(void) { return (uint16_t)rand(); }
2105 helixhorne 596
#else  // RAND_MAX > 32767, assumed to be of the form 2^k - 1
4743 terminx 597
FORCE_INLINE uint16_t system_15bit_rand(void) { return ((uint16_t)rand())&0x7fff; }
2105 helixhorne 598
#endif
5 Plagman 599
 
2394 helixhorne 600
#if defined(_MSC_VER)
601
// XXX: non-__compat_h_macrodef__ version?
602
#define strtoll _strtoi64
603
#endif
604
 
4747 terminx 605
#ifdef compat_h_macrodef__
2546 helixhorne 606
# define Bassert assert
5 Plagman 607
# define Brand rand
608
# define Balloca alloca
4708 helixhorne 609
# define Bmalloc malloc
610
# define Bcalloc calloc
611
# define Brealloc realloc
612
# define Bfree free
613
# if defined(__cplusplus) && defined(_MSC_VER)
4697 terminx 614
#  define Bstrdup _strdup
4708 helixhorne 615
#  define Bchdir _chdir
616
#  define Bgetcwd _getcwd
617
# else
2105 helixhorne 618
#  define Bstrdup strdup
4708 helixhorne 619
#  define Bchdir chdir
620
#  define Bgetcwd getcwd
621
# endif
5 Plagman 622
# define Bopen open
623
# define Bclose close
624
# define Bwrite write
625
# define Bread read
626
# define Blseek lseek
627
# if defined(__GNUC__)
628
#  define Btell(h) lseek(h,0,SEEK_CUR)
629
# else
630
#  define Btell tell
631
# endif
3168 helixhorne 632
# ifdef _MSC_VER
4708 helixhorne 633
#  define Bstat stat
634
#  define Bfstat fstat
3168 helixhorne 635
# else
4708 helixhorne 636
#  define Bstat stat
637
#  define Bfstat fstat
3168 helixhorne 638
# endif
3163 hendricks2 639
# define Bfileno fileno
640
# define Bferror ferror
5 Plagman 641
# define Bfopen fopen
642
# define Bfclose fclose
2725 hendricks2 643
# define Bfflush fflush
5 Plagman 644
# define Bfeof feof
645
# define Bfgetc fgetc
646
# define Brewind rewind
647
# define Bfgets fgets
648
# define Bfputc fputc
649
# define Bfputs fputs
650
# define Bfread fread
651
# define Bfwrite fwrite
652
# define Bfprintf fprintf
2493 hendricks2 653
# define Bfscanf fscanf
654
# define Bfseek fseek
2521 hendricks2 655
# define Bftell ftell
656
# define Bputs puts
5 Plagman 657
# define Bstrcpy strcpy
658
# define Bstrncpy strncpy
659
# define Bstrcmp strcmp
660
# define Bstrncmp strncmp
1454 terminx 661
# if defined(_MSC_VER) 
662
#  define Bstrcasecmp _stricmp
663
#  define Bstrncasecmp _strnicmp
4708 helixhorne 664
# elif defined(__QNX__)
5 Plagman 665
#  define Bstrcasecmp stricmp
666
#  define Bstrncasecmp strnicmp
667
# else
668
#  define Bstrcasecmp strcasecmp
669
#  define Bstrncasecmp strncasecmp
670
# endif
671
# if defined(_WIN32)
672
#  define Bstrlwr strlwr
673
#  define Bstrupr strupr
674
#  define Bmkdir(s,x) mkdir(s)
675
# else
676
#  define Bmkdir mkdir
677
# endif
678
# define Bstrcat strcat
679
# define Bstrncat strncat
680
# define Bstrlen strlen
681
# define Bstrchr strchr
682
# define Bstrrchr strrchr
2412 helixhorne 683
// XXX: different across 32- and 64-bit archs (e.g.
684
// parsing the decimal representation of 0xffffffff,
685
// 4294967295 -- long is signed, so strtol would
686
// return LONG_MAX (== 0x7fffffff on 32-bit archs))
2374 helixhorne 687
# define Batoi(str) ((int32_t)strtol(str, NULL, 10))
688
# define Batol(str) (strtol(str, NULL, 10))
2521 hendricks2 689
# define Batof(str) (strtod(str, NULL))
5 Plagman 690
# define Bstrtol strtol
691
# define Bstrtoul strtoul
692
# define Bstrtod strtod
1763 terminx 693
# define Bstrstr strstr
3833 hendricks2 694
# define Bislower islower
695
# define Bisupper isupper
696
# define Bisdigit isdigit
5 Plagman 697
# define Btoupper toupper
698
# define Btolower tolower
699
# define Bmemcpy memcpy
700
# define Bmemmove memmove
701
# define Bmemchr memchr
702
# define Bmemset memset
703
# define Bmemcmp memcmp
2521 hendricks2 704
# define Bscanf scanf
5 Plagman 705
# define Bprintf printf
2521 hendricks2 706
# define Bsscanf sscanf
5 Plagman 707
# define Bsprintf sprintf
708
# ifdef _MSC_VER
709
#  define Bsnprintf _snprintf
710
#  define Bvsnprintf _vsnprintf
711
# else
712
#  define Bsnprintf snprintf
713
#  define Bvsnprintf vsnprintf
714
# endif
715
# define Bvfprintf vfprintf
716
# define Bgetenv getenv
717
# define Btime() time(NULL)
3293 hendricks2 718
# define Butime utime
5 Plagman 719
 
720
#else
721
 
2546 helixhorne 722
void Bassert(int);
1205 terminx 723
int32_t Brand(void);
5 Plagman 724
void *Bmalloc(bsize_t size);
725
void Bfree(void *ptr);
1205 terminx 726
int32_t Bopen(const char *pathname, int32_t flags, unsigned mode);
727
int32_t Bclose(int32_t fd);
728
bssize_t Bwrite(int32_t fd, const void *buf, bsize_t count);
729
bssize_t Bread(int32_t fd, void *buf, bsize_t count);
730
int32_t Blseek(int32_t fildes, int32_t offset, int32_t whence);
5 Plagman 731
BFILE *Bfopen(const char *path, const char *mode);
1205 terminx 732
int32_t Bfclose(BFILE *stream);
733
int32_t Bfeof(BFILE *stream);
734
int32_t Bfgetc(BFILE *stream);
5 Plagman 735
void Brewind(BFILE *stream);
1205 terminx 736
char *Bfgets(char *s, int32_t size, BFILE *stream);
737
int32_t Bfputc(int32_t c, BFILE *stream);
738
int32_t Bfputs(const char *s, BFILE *stream);
5 Plagman 739
bsize_t Bfread(void *ptr, bsize_t size, bsize_t nmemb, BFILE *stream);
740
bsize_t Bfwrite(const void *ptr, bsize_t size, bsize_t nmemb, BFILE *stream);
741
char *Bstrdup(const char *s);
742
char *Bstrcpy(char *dest, const char *src);
743
char *Bstrncpy(char *dest, const char *src, bsize_t n);
1205 terminx 744
int32_t Bstrcmp(const char *s1, const char *s2);
745
int32_t Bstrncmp(const char *s1, const char *s2, bsize_t n);
746
int32_t Bstrcasecmp(const char *s1, const char *s2);
747
int32_t Bstrncasecmp(const char *s1, const char *s2, bsize_t n);
5 Plagman 748
char *Bstrcat(char *dest, const char *src);
749
char *Bstrncat(char *dest, const char *src, bsize_t n);
750
bsize_t Bstrlen(const char *s);
1205 terminx 751
char *Bstrchr(const char *s, int32_t c);
752
char *Bstrrchr(const char *s, int32_t c);
753
int32_t Batoi(const char *nptr);
754
int32_t Batol(const char *nptr);
1743 helixhorne 755
int32_t Bstrtol(const char *nptr, char **endptr, int32_t base);
756
uint32_t Bstrtoul(const char *nptr, char **endptr, int32_t base);
5 Plagman 757
void *Bmemcpy(void *dest, const void *src, bsize_t n);
758
void *Bmemmove(void *dest, const void *src, bsize_t n);
1205 terminx 759
void *Bmemchr(const void *s, int32_t c, bsize_t n);
760
void *Bmemset(void *s, int32_t c, bsize_t n);
761
int32_t Bmemcmp(const void *s1, const void *s2, bsize_t n);
4716 terminx 762
int32_t Bprintf(const char *format, ...) ATTRIBUTE((format(printf, 1, 2)));
763
int32_t Bsprintf(char *str, const char *format, ...) ATTRIBUTE((format(printf, 2, 3)));
764
int32_t Bsnprintf(char *str, bsize_t size, const char *format, ...) ATTRIBUTE((format(printf, 3, 4)));
1205 terminx 765
int32_t Bvsnprintf(char *str, bsize_t size, const char *format, va_list ap);
5 Plagman 766
char *Bgetcwd(char *buf, bsize_t size);
767
char *Bgetenv(const char *name);
768
#endif
769
 
770
char *Bgethomedir(void);
1205 terminx 771
char *Bgetsupportdir(int32_t global);
772
uint32_t Bgetsysmemsize(void);
773
int32_t Bcorrectfilename(char *filename, int32_t removefn);
774
int32_t Bcanonicalisefilename(char *filename, int32_t removefn);
5 Plagman 775
char *Bgetsystemdrives(void);
1205 terminx 776
int32_t Bfilelength(int32_t fd);
1799 helixhorne 777
char *Bstrtoken(char *s, const char *delim, char **ptrptr, int32_t chop);
2458 hendricks2 778
char *Bstrtolower(char *str);
4658 terminx 779
#define Bwildmatch wildmatch
5 Plagman 780
 
781
#if !defined(_WIN32)
782
char *Bstrlwr(char *);
783
char *Bstrupr(char *);
784
#endif
785
 
3735 helixhorne 786
// Copy min(strlen(src)+1, n) characters into dst, always terminate with a NUL.
4743 terminx 787
FORCE_INLINE char *Bstrncpyz(char *dst, const char *src, bsize_t n)
3213 terminx 788
{
789
    Bstrncpy(dst, src, n);
790
    dst[n-1] = 0;
791
    return dst;
792
}
793
 
3735 helixhorne 794
// Append extension when <outbuf> contains no dot.
3876 helixhorne 795
// <ext> can be like ".mhk" or like "_crash.map", no need to start with a dot.
3735 helixhorne 796
// The ugly name is deliberate: we should be checking the sizes of all buffers!
797
static inline void append_ext_UNSAFE(char *outbuf, const char *ext)
798
{
799
    char *p = Bstrrchr(outbuf,'.');
800
 
801
    if (!p)
802
        Bstrcat(outbuf, ext);
803
    else
3876 helixhorne 804
        Bstrcpy(p, ext);
3735 helixhorne 805
}
806
 
4490 helixhorne 807
#ifdef DEBUGGINGAIDS
808
extern void xalloc_set_location(int32_t line, const char *file, const char *func);
809
#endif
810
void set_memerr_handler(void (*handlerfunc)(int32_t, const char *, const char *));
4619 terminx 811
void handle_memerr(void);
4490 helixhorne 812
 
4743 terminx 813
FORCE_INLINE char *xstrdup(const char *s)
4619 terminx 814
{
815
    char *ptr = Bstrdup(s);
816
    if (ptr == NULL) handle_memerr();
817
    return ptr;
818
}
819
 
4743 terminx 820
FORCE_INLINE void *xmalloc(const bsize_t size)
4619 terminx 821
{
822
    void *ptr = Bmalloc(size);
823
    if (ptr == NULL) handle_memerr();
824
    return ptr;
825
}
826
 
4743 terminx 827
FORCE_INLINE void *xcalloc(const bsize_t nmemb, const bsize_t size)
4619 terminx 828
{
829
    void *ptr = Bcalloc(nmemb, size);
830
    if (ptr == NULL) handle_memerr();
831
    return ptr;
832
}
833
 
4743 terminx 834
FORCE_INLINE void *xrealloc(void * const ptr, const bsize_t size)
4619 terminx 835
{
836
    void *newptr = Brealloc(ptr, size);
837
 
838
    // According to the C Standard,
839
    //  - ptr == NULL makes realloc() behave like malloc()
840
    //  - size == 0 make it behave like free() if ptr != NULL
841
    // Since we want to catch an out-of-mem in the first case, this leaves:
842
    if (newptr == NULL && size != 0)
843
        handle_memerr();
844
 
845
    return newptr;
846
}
847
 
4743 terminx 848
FORCE_INLINE void *xaligned_malloc(const bsize_t alignment, const bsize_t size)
4695 terminx 849
{
850
#ifdef _WIN32
851
    void *ptr = _aligned_malloc(size, alignment);
4762 hendricks2 852
#elif defined __APPLE__
853
    void *ptr = NULL;
854
    posix_memalign(&ptr, alignment, size);
4695 terminx 855
#else
856
    void *ptr = memalign(alignment, size);
857
#endif
4619 terminx 858
 
4695 terminx 859
    if (ptr == NULL) handle_memerr();
860
    return ptr;
861
}
862
 
863
 
3116 hendricks2 864
#ifdef EXTERNC
5 Plagman 865
}
866
#endif
867
 
4442 terminx 868
#define DO_FREE_AND_NULL(var) do { \
869
    if (var != NULL) { Bfree(var); var = NULL; } \
870
} while (0)
871
 
4695 terminx 872
#define ALIGNED_FREE_AND_NULL(var) do { \
873
    if (var != NULL) { Baligned_free(var); var = NULL; } \
874
} while (0)
875
 
2995 helixhorne 876
#define MAYBE_FCLOSE_AND_NULL(fileptr) do { \
877
    if (fileptr) { Bfclose(fileptr); fileptr=NULL; } \
878
} while (0)
879
 
3232 terminx 880
#define NOWARN(print_func, fmt, ...) do { \
3170 helixhorne 881
    print_func(fmt, ## __VA_ARGS__); \
882
} while (0)
883
 
3232 terminx 884
#define NOWARN_RETURN(print_func, var, fmt, ...) do { \
3170 helixhorne 885
    var = print_func(fmt, ## __VA_ARGS__); \
886
} while (0)
887
 
3232 terminx 888
#ifdef __cplusplus
3237 hendricks2 889
#ifndef FORCE_WARNINGS
3232 terminx 890
#ifdef _MSC_VER
891
// TODO: add MSVC pragmas to disable equivalent warning, if necessary later
3231 helixhorne 892
#else
3232 terminx 893
#ifdef _WIN32
894
// MinGW's _Pragma is completely broken so our GCC NOWARN macro is useless there
895
 #pragma GCC diagnostic ignored "-Wformat"
896
#else
897
 #undef NOWARN
898
 #undef NOWARN_RETURN
3231 helixhorne 899
 
3232 terminx 900
 #define NOWARN(print_func, fmt, ...) do { _Pragma("GCC diagnostic ignored \"-Wformat\"") \
3170 helixhorne 901
    print_func(fmt, ## __VA_ARGS__); \
902
    _Pragma("GCC diagnostic warning \"-Wformat\"") } while (0)
903
 
3232 terminx 904
 #define NOWARN_RETURN(print_func, var, fmt, ...) do { _Pragma("GCC diagnostic ignored \"-Wformat\"") \
3170 helixhorne 905
    var = print_func(fmt, ## __VA_ARGS__); \
906
    _Pragma("GCC diagnostic warning \"-Wformat\"") } while (0)
3232 terminx 907
#endif // _WIN32
908
#endif // _MSC_VER
3237 hendricks2 909
#endif // FORCE_WARNINGS
3190 terminx 910
#endif // __cplusplus
3170 helixhorne 911
 
912
#define OSD_Printf_nowarn(fmt, ...) NOWARN(OSD_Printf, fmt, ## __VA_ARGS__)
913
#define Bsprintf_nowarn(fmt, ...) NOWARN(Bsprintf, fmt, ## __VA_ARGS__)
914
#define Bsprintf_nowarn_return(x, fmt, ...) NOWARN_RETURN(Bsprintf, x, fmt, ## __VA_ARGS__)
915
#define initprintf_nowarn(fmt, ...) NOWARN(initprintf, fmt, ## __VA_ARGS__)
916
#define message_nowarn(fmt, ...) NOWARN(message, fmt, ## __VA_ARGS__)
917
 
3644 helixhorne 918
/* Static assertions, based on source found in LuaJIT's src/lj_def.h. */
919
#define EDUKE32_ASSERT_NAME2(name, line) name ## line
920
#define EDUKE32_ASSERT_NAME(line) EDUKE32_ASSERT_NAME2(eduke32_assert_, line)
921
#ifdef __COUNTER__
922
# define EDUKE32_STATIC_ASSERT(cond) \
923
    extern void EDUKE32_ASSERT_NAME(__COUNTER__)(int STATIC_ASSERTION_FAILED[(cond)?1:-1])
924
#else
925
# define EDUKE32_STATIC_ASSERT(cond) \
926
    extern void EDUKE32_ASSERT_NAME(__LINE__)(int STATIC_ASSERTION_FAILED[(cond)?1:-1])
927
#endif
928
 
4199 helixhorne 929
#define ARRAY_SIZE(Ar) (sizeof(Ar)/sizeof((Ar)[0]))
930
#define ARRAY_SSIZE(Ar) (bssize_t)ARRAY_SIZE(Ar)
931
 
4490 helixhorne 932
////////// PANICKING ALLOCATION MACROS (wrapping the functions) //////////
933
#ifdef DEBUGGINGAIDS
934
// Detection of __func__ or equivalent functionality, found in SDL_assert.h
935
# if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 supports __func__ as a standard. */
936
#  define EDUKE32_FUNCTION __func__
937
# elif ((__GNUC__ >= 2) || defined(_MSC_VER))
938
#  define EDUKE32_FUNCTION __FUNCTION__
939
# else
940
#  define EDUKE32_FUNCTION "???"
941
# endif
942
 
943
# define EDUKE32_PRE_XALLLOC xalloc_set_location(__LINE__, __FILE__, EDUKE32_FUNCTION)
944
# define Xstrdup(s) (EDUKE32_PRE_XALLLOC, xstrdup(s))
945
# define Xmalloc(size) (EDUKE32_PRE_XALLLOC, xmalloc(size))
946
# define Xcalloc(nmemb, size) (EDUKE32_PRE_XALLLOC, xcalloc(nmemb, size))
947
# define Xrealloc(ptr, size) (EDUKE32_PRE_XALLLOC, xrealloc(ptr, size))
4695 terminx 948
# define Xaligned_alloc(size, alignment) (EDUKE32_PRE_XALLLOC, xaligned_malloc(size, alignment))
4502 hendricks2 949
# define Bexit(status) do { initprintf("exit(%d) at %s:%d in %s()\n", status, __FILE__, __LINE__, EDUKE32_FUNCTION); exit(status); } while (0)
4490 helixhorne 950
#else
951
# define Xstrdup xstrdup
952
# define Xmalloc xmalloc
953
# define Xcalloc xcalloc
954
# define Xrealloc xrealloc
4736 helixhorne 955
# define Xaligned_alloc xaligned_malloc
4502 hendricks2 956
# define Bexit exit
4490 helixhorne 957
#endif
4695 terminx 958
 
959
#ifdef _WIN32
960
# define Baligned_free(ptr) _aligned_free(ptr)
961
#else
962
# define Baligned_free(ptr) Bfree(ptr)
963
#endif
964
 
4490 helixhorne 965
//////////
966
 
4747 terminx 967
#endif // compat_h_