Subversion Repositories eduke32

Rev

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