diff --git a/source/build/include/compat.h b/source/build/include/compat.h index 0a9bec6da..d316a2572 100644 --- a/source/build/include/compat.h +++ b/source/build/include/compat.h @@ -2,11 +2,14 @@ // certain build environments. It also levels the playing field caused // by different platforms. -#pragma once - #ifndef compat_h_ #define compat_h_ +#pragma once + + +////////// Compiler detection ////////// + #ifdef __GNUC__ # define EDUKE32_GCC_PREREQ(major, minor) (major < __GNUC__ || (major == __GNUC__ && minor <= __GNUC_MINOR__)) #else @@ -28,6 +31,15 @@ # define __has_extension __has_feature // Compatibility with pre-3.0 compilers. #endif + +////////// Language and compiler feature polyfills ////////// + +#ifdef __cplusplus +# define EXTERNC extern "C" +#else +# define EXTERNC +#endif + #ifndef UNREFERENCED_PARAMETER # define UNREFERENCED_PARAMETER(x) (x) = (x) #endif @@ -52,6 +64,46 @@ # define ATTRIBUTE_OPTIMIZE(str) #endif +#if EDUKE32_GCC_PREREQ(4,0) +# define WARN_UNUSED_RESULT __attribute__((warn_unused_result)) +#else +# define WARN_UNUSED_RESULT +#endif + +#if defined _MSC_VER && _MSC_VER < 1800 +# define inline __inline +#endif + +#ifndef FORCE_INLINE +# ifdef _MSC_VER // Visual Studio +# define FORCE_INLINE static __forceinline +# else +# ifdef __GNUC__ +# define FORCE_INLINE static inline __attribute__((always_inline)) +# else +# define FORCE_INLINE static inline +# endif +# endif +#endif + +#ifndef _MSC_VER +# ifndef __fastcall +# if defined(__GNUC__) && defined(__i386__) +# define __fastcall __attribute__((fastcall)) +# else +# define __fastcall +# endif +# endif +#endif + +#ifndef DISABLE_INLINING +# define EXTERN_INLINE static inline +# define EXTERN_INLINE_HEADER static inline +#else +# define EXTERN_INLINE __fastcall +# define EXTERN_INLINE_HEADER extern __fastcall +#endif + #if defined __GNUC__ || __has_builtin(__builtin_expect) #define EDUKE32_PREDICT_TRUE(x) __builtin_expect(!!(x),1) #define EDUKE32_PREDICT_FALSE(x) __builtin_expect(!!(x),0) @@ -68,12 +120,50 @@ #define EDUKE32_UNREACHABLE_SECTION(...) __VA_ARGS__ #endif -#if defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ || defined __bsdi__ || defined __DragonFly__ -# define EDUKE32_BSD +// Detection of __func__ or equivalent functionality, found in SDL_assert.h +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 supports __func__ as a standard. */ +# define EDUKE32_FUNCTION __func__ +#elif ((__GNUC__ >= 2) || defined(_MSC_VER)) +# define EDUKE32_FUNCTION __FUNCTION__ +#else +# define EDUKE32_FUNCTION "???" #endif -#if !defined __APPLE__ && (!defined EDUKE32_BSD || !__STDC__) -# include +/* Static assertions, based on source found in LuaJIT's src/lj_def.h. */ +#define EDUKE32_ASSERT_NAME2(name, line) name ## line +#define EDUKE32_ASSERT_NAME(line) EDUKE32_ASSERT_NAME2(eduke32_assert_, line) +#ifdef __COUNTER__ +# define EDUKE32_STATIC_ASSERT(cond) \ + extern void EDUKE32_ASSERT_NAME(__COUNTER__)(int STATIC_ASSERTION_FAILED[(cond)?1:-1]) +#else +# define EDUKE32_STATIC_ASSERT(cond) \ + extern void EDUKE32_ASSERT_NAME(__LINE__)(int STATIC_ASSERTION_FAILED[(cond)?1:-1]) +#endif + +#define ARRAY_SIZE(Ar) (sizeof(Ar)/sizeof((Ar)[0])) +#define ARRAY_SSIZE(Ar) (signed)ARRAY_SIZE(Ar) + +#ifdef _MSC_VER +# define longlong(x) x##i64 +#else +# define longlong(x) x##ll +#endif + +#ifndef FP_OFF +# define FP_OFF(__p) ((uintptr_t)(__p)) +#endif + +#ifdef UNDERSCORES +# define ASMSYM(x) "_" x +#else +# define ASMSYM(x) x +#endif + + +////////// Platform detection ////////// + +#if defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ || defined __bsdi__ || defined __DragonFly__ +# define EDUKE32_BSD #endif #ifdef __APPLE__ @@ -82,149 +172,20 @@ # define EDUKE32_IOS # else # define EDUKE32_OSX -# if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_3 -# include -# endif -# include # endif #endif -#if defined __ANDROID__ || defined EDUKE32_IOS -# define EDUKE32_TOUCH_DEVICES -# define EDUKE32_GLES + +////////// Architecture detection ////////// + +#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__ + +# define BITNESS64 + #endif -// This gives us access to 'intptr_t' and 'uintptr_t', which are -// abstractions to the size of a pointer on a given platform -// (ie, they're guaranteed to be the same size as a pointer) - -#undef __USE_MINGW_ANSI_STDIO // Workaround for MinGW-w64. - -#ifndef __STDC_FORMAT_MACROS -#define __STDC_FORMAT_MACROS -#endif -#ifndef __STDC_LIMIT_MACROS -# define __STDC_LIMIT_MACROS -#endif -#if defined(HAVE_INTTYPES) || defined(__cplusplus) -# include -# include - -// Ghetto. Blame devkitPPC's faulty headers. -# ifdef GEKKO -# undef PRIdPTR -# define PRIdPTR "d" -# undef PRIxPTR -# define PRIxPTR "x" -# undef SCNx32 -# define SCNx32 "x" -# endif - -#elif defined(_MSC_VER) -# include "msvc/inttypes.h" // from http://code.google.com/p/msinttypes/ -#endif - -#ifndef _MSC_VER -# ifndef __fastcall -# if defined(__GNUC__) && defined(__i386__) -# define __fastcall __attribute__((fastcall)) -# else -# define __fastcall -# endif -# endif -#endif - -#ifndef TRUE -# define TRUE 1 -#endif - -#ifndef FALSE -# define FALSE 0 -#endif - -#define WITHKPLIB - -#include "libdivide.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(_WIN32) -# include -#else -# include -#endif - -#include - -#ifdef EFENCE -# include -#elif defined DMALLOC -# include -#endif - -#if defined(_MSC_VER) -# include -# define longlong(x) x##i64 -# if _MSC_VER < 1800 -# define inline __inline -# endif -#else -# define longlong(x) x##ll -#endif - -#if defined(__arm__) -# define Bsqrt __builtin_sqrt -# define Bsqrtf __builtin_sqrtf -#else -# define Bsqrt sqrt -# define Bsqrtf sqrtf -#endif - -#ifndef NULL -# define NULL ((void *)0) -#endif - -#if DEBUGGINGAIDS>=2 -# define DEBUG_MAIN_ARRAYS -#endif - -#ifndef DISABLE_INLINING -# define EXTERN_INLINE static inline -# define EXTERN_INLINE_HEADER static inline -#else -# define EXTERN_INLINE __fastcall -# define EXTERN_INLINE_HEADER extern __fastcall -#endif - -#ifndef FORCE_INLINE -# ifdef _MSC_VER // Visual Studio -# define FORCE_INLINE static __forceinline -# else -# ifdef __GNUC__ -# define FORCE_INLINE static inline __attribute__((always_inline)) -# else -# define FORCE_INLINE static inline -# endif -# endif -#endif - -#if !defined DEBUG_MAIN_ARRAYS -# define HAVE_CLIPSHAPE_FEATURE -#endif - -// redefined for apple/ppc, which chokes on stderr when linking... -#define ERRprintf(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__) - #if defined(__linux) # include # if __BYTE_ORDER == __LITTLE_ENDIAN @@ -268,19 +229,6 @@ # define B_SWAP16(x) __bswap16(x) #elif defined(__APPLE__) -# if !defined __x86_64__ && defined __GNUC__ -// PK 20110617: is*() crashes for me in x86 code compiled from 64-bit, and gives link errors on ppc -// This hack patches all occurences. -# define isdigit(ch) ({ int32_t c__dontuse_=ch; c__dontuse_>='0' && c__dontuse_<='9'; }) -# define isalpha(ch) ({ int32_t c__dontuse2_=ch; (c__dontuse2_>='A' && c__dontuse2_<='Z') || (c__dontuse2_>='a' && c__dontuse2_<='z'); }) -# define isalnum(ch2) ({ int32_t c2__dontuse_=ch2; isalpha(c2__dontuse_) || isdigit(c2__dontuse_); }) -# if defined __BIG_ENDIAN__ -# 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'); }) -# define isprint(ch) ({ int32_t c__dontuse_=ch; (c__dontuse_>=0x20 && c__dontuse_<0x7f); }) -# undef ERRprintf -# define ERRprintf(fmt, ...) printf(fmt, ## __VA_ARGS__) -# endif -# endif # if defined(__LITTLE_ENDIAN__) # define B_LITTLE_ENDIAN 1 # define B_BIG_ENDIAN 0 @@ -334,23 +282,397 @@ # error Unknown endianness #endif -#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__ -# define BITNESS64 +////////// Standard library headers ////////// +#undef __USE_MINGW_ANSI_STDIO // Workaround for MinGW-w64. + +#ifndef __STDC_FORMAT_MACROS +# define __STDC_FORMAT_MACROS +#endif +#ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS +#endif +#if defined(HAVE_INTTYPES) || defined(__cplusplus) +# include +# include + +#elif defined(_MSC_VER) +# include "msvc/inttypes.h" // from http://code.google.com/p/msinttypes/ #endif -#ifdef __cplusplus +#include +#include +#include +#include +#include -# ifndef SCREWED_UP_CPP -// using namespace std; +#include + +#include +#include +#include + +#include + + +////////// Platform headers ////////// + +#if !defined __APPLE__ && (!defined EDUKE32_BSD || !__STDC__) +# include +#endif + +#include +#include +#include + +#if defined(_WIN32) +# include +#else +# include +#endif + +#ifdef _MSC_VER +# include +#endif + + +////////// External library headers ////////// + +#ifdef EFENCE +# include +#elif defined DMALLOC +# include +#endif + + +////////// DEPRECATED: Standard library prefixing ////////// + +#ifdef _MSC_VER +typedef intptr_t ssize_t; +#endif +typedef size_t bsize_t; +typedef ssize_t bssize_t; + +typedef FILE BFILE; + +#ifndef O_BINARY +# define O_BINARY 0 +#endif +#ifndef O_TEXT +# define O_TEXT 0 +#endif + +#ifndef F_OK +# define F_OK 0 +#endif + +#define BO_BINARY O_BINARY +#define BO_TEXT O_TEXT +#define BO_RDONLY O_RDONLY +#define BO_WRONLY O_WRONLY +#define BO_RDWR O_RDWR +#define BO_APPEND O_APPEND +#define BO_CREAT O_CREAT +#define BO_TRUNC O_TRUNC +#define BS_IRGRP S_IRGRP +#define BS_IWGRP S_IWGRP +#define BS_IEXEC S_IEXEC +#define BS_IFIFO S_IFIFO +#define BS_IFCHR S_IFCHR +#define BS_IFBLK S_IFBLK +#define BS_IFDIR S_IFDIR +#define BS_IFREG S_IFREG +#define BSEEK_SET SEEK_SET +#define BSEEK_CUR SEEK_CUR +#define BSEEK_END SEEK_END + +#define BMAX_PATH 256 + +#define Bassert assert +#define Brand rand +#define Balloca alloca +#define Bmalloc malloc +#define Bcalloc calloc +#define Brealloc realloc +#define Bfree free +#define Bopen open +#define Bclose close +#define Bwrite write +#define Bread read +#define Blseek lseek +#define Bstat stat +#define Bfstat fstat +#define Bfileno fileno +#define Bferror ferror +#define Bfopen fopen +#define Bfclose fclose +#define Bfflush fflush +#define Bfeof feof +#define Bfgetc fgetc +#define Brewind rewind +#define Bfgets fgets +#define Bfputc fputc +#define Bfputs fputs +#define Bfread fread +#define Bfwrite fwrite +#define Bfprintf fprintf +#define Bfscanf fscanf +#define Bfseek fseek +#define Bftell ftell +#define Bputs puts +#define Bstrcpy strcpy +#define Bstrncpy strncpy +#define Bstrcmp strcmp +#define Bstrncmp strncmp +#define Bstrcat strcat +#define Bstrncat strncat +#define Bstrlen strlen +#define Bstrchr strchr +#define Bstrrchr strrchr +#define Bstrtol strtol +#define Bstrtoul strtoul +#define Bstrtod strtod +#define Bstrstr strstr +#define Bislower islower +#define Bisupper isupper +#define Bisdigit isdigit +#define Btoupper toupper +#define Btolower tolower +#define Bmemcpy memcpy +#define Bmemmove memmove +#define Bmemchr memchr +#define Bmemset memset +#define Bmemcmp memcmp +#define Bscanf scanf +#define Bprintf printf +#define Bsscanf sscanf +#define Bsprintf sprintf +#define Bvfprintf vfprintf +#define Bgetenv getenv +#define Butime utime + + +////////// Standard library wrappers ////////// + +#ifdef __ANDROID__ +# define BS_IWRITE S_IWUSR +# define BS_IREAD S_IRUSR +#else +# define BS_IWRITE S_IWRITE +# define BS_IREAD S_IREAD +#endif + +#if defined(__cplusplus) && defined(_MSC_VER) +# define Bstrdup _strdup +# define Bchdir _chdir +# define Bgetcwd _getcwd +#else +# define Bstrdup strdup +# define Bchdir chdir +# define Bgetcwd getcwd +#endif + +#if defined(__GNUC__) +# define Btell(h) lseek(h,0,SEEK_CUR) +#else +# define Btell tell +#endif + +#if defined(_MSC_VER) +# define Bstrcasecmp _stricmp +# define Bstrncasecmp _strnicmp +#elif defined(__QNX__) +# define Bstrcasecmp stricmp +# define Bstrncasecmp strnicmp +#else +# define Bstrcasecmp strcasecmp +# define Bstrncasecmp strncasecmp +#endif + +#ifdef _MSC_VER +# define Bsnprintf _snprintf +# define Bvsnprintf _vsnprintf +#else +# define Bsnprintf snprintf +# define Bvsnprintf vsnprintf +#endif + +#define Btime() time(NULL) + +#if defined(_WIN32) +# define Bmkdir(s,x) mkdir(s) +#else +# define Bmkdir mkdir +#endif + +// XXX: different across 32- and 64-bit archs (e.g. +// parsing the decimal representation of 0xffffffff, +// 4294967295 -- long is signed, so strtol would +// return LONG_MAX (== 0x7fffffff on 32-bit archs)) +#define Batoi(str) ((int32_t)strtol(str, NULL, 10)) +#define Batol(str) (strtol(str, NULL, 10)) +#define Batof(str) (strtod(str, NULL)) + +#if defined BITNESS64 && (defined __SSE2__ || defined _MSC_VER) +#include +FORCE_INLINE int32_t Blrintf(const float x) +{ + __m128 xx = _mm_load_ss(&x); + return _mm_cvtss_si32(xx); +} +#elif defined (_MSC_VER) +FORCE_INLINE int32_t Blrintf(const float x) +{ + int n; + __asm fld x; + __asm fistp n; + return n; +} +#else +#define Blrintf lrintf +#endif + +#if defined(__arm__) +# define Bsqrt __builtin_sqrt +# define Bsqrtf __builtin_sqrtf +#else +# define Bsqrt sqrt +# define Bsqrtf sqrtf +#endif + +// redefined for apple/ppc, which chokes on stderr when linking... +#if defined EDUKE32_OSX && defined __BIG_ENDIAN__ +# define ERRprintf(fmt, ...) printf(fmt, ## __VA_ARGS__) +#else +# define ERRprintf(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__) +#endif + +#ifdef DEBUGGINGAIDS +# define Bexit(status) do { initprintf("exit(%d) at %s:%d in %s()\n", status, __FILE__, __LINE__, EDUKE32_FUNCTION); exit(status); } while (0) +#else +# define Bexit exit +#endif + + +////////// Standard library monkey patching ////////// + +#ifndef NULL +# define NULL ((void *)0) +#endif + +#ifdef _MSC_VER +# define strtoll _strtoi64 +#endif + +#ifdef GEKKO +# undef PRIdPTR +# define PRIdPTR "d" +# undef PRIxPTR +# define PRIxPTR "x" +# undef SCNx32 +# define SCNx32 "x" +#endif + +#if defined EDUKE32_OSX +# if !defined __x86_64__ && defined __GNUC__ +// PK 20110617: is*() crashes for me in x86 code compiled from 64-bit, and gives link errors on ppc +// This hack patches all occurences. +# define isdigit(ch) ({ int32_t c__dontuse_=ch; c__dontuse_>='0' && c__dontuse_<='9'; }) +# define isalpha(ch) ({ int32_t c__dontuse2_=ch; (c__dontuse2_>='A' && c__dontuse2_<='Z') || (c__dontuse2_>='a' && c__dontuse2_<='z'); }) +# define isalnum(ch2) ({ int32_t c2__dontuse_=ch2; isalpha(c2__dontuse_) || isdigit(c2__dontuse_); }) +# if defined __BIG_ENDIAN__ +# 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'); }) +# define isprint(ch) ({ int32_t c__dontuse_=ch; (c__dontuse_>=0x20 && c__dontuse_<0x7f); }) +# endif # endif - -extern "C" { #endif +#ifdef __ANDROID__ +void eduke32_exit_return(int) ATTRIBUTE((noreturn)); +# define exit(x) eduke32_exit_return(x) +#endif + + +////////// Typedefs ////////// + +typedef struct { + int32_t x, y; +} vec2_t; + +typedef struct { + uint32_t x, y; +} vec2u_t; + +typedef struct { + int32_t x, y, z; +} vec3_t; + +typedef struct { + float x, y; +} vec2f_t; + +typedef struct { + union { float x; float d; }; + union { float y; float u; }; + union { float z; float v; }; +} vec3f_t; + +EDUKE32_STATIC_ASSERT(sizeof(vec3f_t) == sizeof(float) * 3); + +typedef struct { + union { double x; double d; }; + union { double y; double u; }; + union { double z; double v; }; +} vec3d_t; + +EDUKE32_STATIC_ASSERT(sizeof(vec3d_t) == sizeof(double) * 3); + + +////////// Memory management ////////// + +#if !defined NO_ALIGNED_MALLOC +FORCE_INLINE void *Baligned_alloc(const size_t alignment, const size_t size) +{ +#ifdef _WIN32 + void *ptr = _aligned_malloc(size, alignment); +#elif defined __APPLE__ || defined EDUKE32_BSD + void *ptr = NULL; + posix_memalign(&ptr, alignment, size); +#else + void *ptr = memalign(alignment, size); +#endif + + return ptr; +} +#else +# define Baligned_alloc(alignment, size) Bmalloc(size) +#endif + +#if defined _WIN32 && !defined NO_ALIGNED_MALLOC +# define Baligned_free _aligned_free +#else +# define Baligned_free Bfree +#endif + + +////////// Pointer management ////////// + +#define DO_FREE_AND_NULL(var) do { \ + Bfree(var); (var) = NULL; \ +} while (0) + +#define ALIGNED_FREE_AND_NULL(var) do { \ + Baligned_free(var); (var) = NULL; \ +} while (0) + +#define MAYBE_FCLOSE_AND_NULL(fileptr) do { \ + if (fileptr) { Bfclose(fileptr); fileptr=NULL; } \ +} while (0) + + +////////// Data serialization ////////// + #if defined B_USE_COMPAT_SWAP FORCE_INLINE uint16_t B_SWAP16(uint16_t s) { return (s >> 8) | (s << 8); } @@ -388,6 +710,22 @@ FORCE_INLINE uint16_t B_PASS16(uint16_t const x) { return x; } FORCE_INLINE uint32_t B_PASS32(uint32_t const x) { return x; } FORCE_INLINE uint64_t B_PASS64(uint64_t const x) { return x; } +#if B_LITTLE_ENDIAN == 1 +# define B_LITTLE64(x) B_PASS64(x) +# define B_BIG64(x) B_SWAP64(x) +# define B_LITTLE32(x) B_PASS32(x) +# define B_BIG32(x) B_SWAP32(x) +# define B_LITTLE16(x) B_PASS16(x) +# define B_BIG16(x) B_SWAP16(x) +#elif B_BIG_ENDIAN == 1 +# define B_LITTLE64(x) B_SWAP64(x) +# define B_BIG64(x) B_PASS64(x) +# define B_LITTLE32(x) B_SWAP32(x) +# define B_BIG32(x) B_PASS32(x) +# define B_LITTLE16(x) B_SWAP16(x) +# define B_BIG16(x) B_PASS16(x) +#endif + // TODO: Determine when, if ever, we should use the bit-shift-and-mask variants // due to alignment issues or performance gains. #if 1 @@ -447,183 +785,26 @@ FORCE_INLINE uint64_t B_UNBUF64(void const * const vbuf) } #endif -#if defined BITNESS64 && (defined __SSE2__ || defined _MSC_VER) -#include -FORCE_INLINE int32_t Blrintf(const float x) -{ - __m128 xx = _mm_load_ss(&x); - return _mm_cvtss_si32(xx); -} -#elif defined (_MSC_VER) -FORCE_INLINE int32_t Blrintf(const float x) -{ - int n; - __asm fld x; - __asm fistp n; - return n; -} -#else -#include -#define Blrintf lrintf -#endif -#if B_LITTLE_ENDIAN == 1 -# define B_LITTLE64(x) B_PASS64(x) -# define B_BIG64(x) B_SWAP64(x) -# define B_LITTLE32(x) B_PASS32(x) -# define B_BIG32(x) B_SWAP32(x) -# define B_LITTLE16(x) B_PASS16(x) -# define B_BIG16(x) B_SWAP16(x) -#elif B_BIG_ENDIAN == 1 -# define B_LITTLE64(x) B_SWAP64(x) -# define B_BIG64(x) B_PASS64(x) -# define B_LITTLE32(x) B_SWAP32(x) -# define B_BIG32(x) B_PASS32(x) -# define B_LITTLE16(x) B_SWAP16(x) -# define B_BIG16(x) B_PASS16(x) -#endif - -#ifndef FP_OFF -# define FP_OFF(__p) ((uintptr_t)(__p)) -#endif - -#ifndef O_BINARY -# define O_BINARY 0 -#endif -#ifndef O_TEXT -# define O_TEXT 0 -#endif - -#ifndef F_OK -# define F_OK 0 -#endif - -#define BO_BINARY O_BINARY -#define BO_TEXT O_TEXT -#define BO_RDONLY O_RDONLY -#define BO_WRONLY O_WRONLY -#define BO_RDWR O_RDWR -#define BO_APPEND O_APPEND -#define BO_CREAT O_CREAT -#define BO_TRUNC O_TRUNC -#define BS_IRGRP S_IRGRP -#define BS_IWGRP S_IWGRP -#define BS_IEXEC S_IEXEC -#ifdef __ANDROID__ -# define BS_IWRITE S_IWUSR -# define BS_IREAD S_IRUSR -#else -# define BS_IWRITE S_IWRITE -# define BS_IREAD S_IREAD -#endif -#define BS_IFIFO S_IFIFO -#define BS_IFCHR S_IFCHR -#define BS_IFBLK S_IFBLK -#define BS_IFDIR S_IFDIR -#define BS_IFREG S_IFREG -#define BSEEK_SET SEEK_SET -#define BSEEK_CUR SEEK_CUR -#define BSEEK_END SEEK_END - -#ifdef UNDERSCORES -# define ASMSYM(x) "_" x -#else -# define ASMSYM(x) x -#endif +////////// Abstract data operations ////////// #ifndef min # define min(a, b) (((a) < (b)) ? (a) : (b)) #endif - #ifndef max # define max(a, b) (((a) > (b)) ? (a) : (b)) #endif -#if __GNUC__ >= 4 -# define CLAMP_DECL FORCE_INLINE __attribute__((warn_unused_result)) -#else -# define CLAMP_DECL FORCE_INLINE -#endif - +#define CLAMP_DECL FORCE_INLINE WARN_UNUSED_RESULT // Clamp to [..]. The case in <= min is handled first. CLAMP_DECL int32_t clamp(int32_t in, int32_t min, int32_t max) { return in <= min ? min : (in >= max ? max : in); } - +CLAMP_DECL float fclamp(float in, float min, float max) { return in <= min ? min : (in >= max ? max : in); } // Clamp to [..]. The case in >= max is handled first. CLAMP_DECL int32_t clamp2(int32_t in, int32_t min, int32_t max) { return in >= max ? max : (in <= min ? min : in); } - -// Clamp to [..]. The case in <= min is handled first. -CLAMP_DECL float fclamp(float in, float min, float max) { return in <= min ? min : (in >= max ? max : in); } - -// Clamp to [..]. The case in >= max is handled first. CLAMP_DECL float fclamp2(float in, float min, float max) { return in >= max ? max : (in <= min ? min : in); } -#define BMAX_PATH 256 -/* Static assertions, based on source found in LuaJIT's src/lj_def.h. */ -#define EDUKE32_ASSERT_NAME2(name, line) name ## line -#define EDUKE32_ASSERT_NAME(line) EDUKE32_ASSERT_NAME2(eduke32_assert_, line) -#ifdef __COUNTER__ -# define EDUKE32_STATIC_ASSERT(cond) \ - extern void EDUKE32_ASSERT_NAME(__COUNTER__)(int STATIC_ASSERTION_FAILED[(cond)?1:-1]) -#else -# define EDUKE32_STATIC_ASSERT(cond) \ - extern void EDUKE32_ASSERT_NAME(__LINE__)(int STATIC_ASSERTION_FAILED[(cond)?1:-1]) -#endif - -struct Bdirent -{ - uint16_t namlen; - char *name; - uint32_t mode; - uint32_t size; - uint32_t mtime; -}; -typedef void BDIR; - -BDIR *Bopendir(const char *name); -struct Bdirent *Breaddir(BDIR *dir); -int32_t Bclosedir(BDIR *dir); - -#ifdef _MSC_VER -typedef intptr_t ssize_t; -#endif - -typedef FILE BFILE; -typedef size_t bsize_t; -typedef ssize_t bssize_t; - - -typedef struct { - int32_t x, y; -} vec2_t; - -typedef struct { - uint32_t x, y; -} vec2u_t; - -typedef struct { - int32_t x, y, z; -} vec3_t; - -typedef struct { - float x, y; -} vec2f_t; - -typedef struct { - union { float x; float d; }; - union { float y; float u; }; - union { float z; float v; }; -} vec3f_t; - -EDUKE32_STATIC_ASSERT(sizeof(vec3f_t) == sizeof(float) * 3); - -typedef struct { - union { double x; double d; }; - union { double y; double u; }; - union { double z; double v; }; -} vec3d_t; - -EDUKE32_STATIC_ASSERT(sizeof(vec3d_t) == sizeof(double) * 3); +////////// Utility functions ////////// #if RAND_MAX == 32767 FORCE_INLINE uint16_t system_15bit_rand(void) { return (uint16_t)rand(); } @@ -631,140 +812,6 @@ FORCE_INLINE uint16_t system_15bit_rand(void) { return (uint16_t)rand(); } FORCE_INLINE uint16_t system_15bit_rand(void) { return ((uint16_t)rand())&0x7fff; } #endif -#if defined(_MSC_VER) -#define strtoll _strtoi64 -#endif - -#define Bassert assert -#define Brand rand -#define Balloca alloca -#define Bmalloc malloc -#define Bcalloc calloc -#define Brealloc realloc -#define Bfree free -#if defined(__cplusplus) && defined(_MSC_VER) -# define Bstrdup _strdup -# define Bchdir _chdir -# define Bgetcwd _getcwd -#else -# define Bstrdup strdup -# define Bchdir chdir -# define Bgetcwd getcwd -#endif -#define Bopen open -#define Bclose close -#define Bwrite write -#define Bread read -#define Blseek lseek -#if defined(__GNUC__) -# define Btell(h) lseek(h,0,SEEK_CUR) -#else -# define Btell tell -#endif -#ifdef _MSC_VER -# define Bstat stat -# define Bfstat fstat -#else -# define Bstat stat -# define Bfstat fstat -#endif -#define Bfileno fileno -#define Bferror ferror -#define Bfopen fopen -#define Bfclose fclose -#define Bfflush fflush -#define Bfeof feof -#define Bfgetc fgetc -#define Brewind rewind -#define Bfgets fgets -#define Bfputc fputc -#define Bfputs fputs -#define Bfread fread -#define Bfwrite fwrite -#define Bfprintf fprintf -#define Bfscanf fscanf -#define Bfseek fseek -#define Bftell ftell -#define Bputs puts -#define Bstrcpy strcpy -#define Bstrncpy strncpy -#define Bstrcmp strcmp -#define Bstrncmp strncmp -#if defined(_MSC_VER) -# define Bstrcasecmp _stricmp -# define Bstrncasecmp _strnicmp -#elif defined(__QNX__) -# define Bstrcasecmp stricmp -# define Bstrncasecmp strnicmp -#else -# define Bstrcasecmp strcasecmp -# define Bstrncasecmp strncasecmp -#endif -#if defined(_WIN32) -# define Bstrlwr strlwr -# define Bstrupr strupr -# define Bmkdir(s,x) mkdir(s) -#else -# define Bmkdir mkdir -#endif -#define Bstrcat strcat -#define Bstrncat strncat -#define Bstrlen strlen -#define Bstrchr strchr -#define Bstrrchr strrchr -// XXX: different across 32- and 64-bit archs (e.g. -// parsing the decimal representation of 0xffffffff, -// 4294967295 -- long is signed, so strtol would -// return LONG_MAX (== 0x7fffffff on 32-bit archs)) -#define Batoi(str) ((int32_t)strtol(str, NULL, 10)) -#define Batol(str) (strtol(str, NULL, 10)) -#define Batof(str) (strtod(str, NULL)) -#define Bstrtol strtol -#define Bstrtoul strtoul -#define Bstrtod strtod -#define Bstrstr strstr -#define Bislower islower -#define Bisupper isupper -#define Bisdigit isdigit -#define Btoupper toupper -#define Btolower tolower -#define Bmemcpy memcpy -#define Bmemmove memmove -#define Bmemchr memchr -#define Bmemset memset -#define Bmemcmp memcmp -#define Bscanf scanf -#define Bprintf printf -#define Bsscanf sscanf -#define Bsprintf sprintf -#ifdef _MSC_VER -# define Bsnprintf _snprintf -# define Bvsnprintf _vsnprintf -#else -# define Bsnprintf snprintf -# define Bvsnprintf vsnprintf -#endif -#define Bvfprintf vfprintf -#define Bgetenv getenv -#define Btime() time(NULL) -#define Butime utime - -char *Bgethomedir(void); -char *Bgetappdir(void); -uint32_t Bgetsysmemsize(void); -int32_t Bcorrectfilename(char *filename, int32_t removefn); -int32_t Bcanonicalisefilename(char *filename, int32_t removefn); -char *Bgetsystemdrives(void); -int32_t Bfilelength(int32_t fd); -char *Bstrtoken(char *s, const char *delim, char **ptrptr, int chop); -char *Bstrtolower(char *str); -#define Bwildmatch wildmatch - -#if !defined(_WIN32) -char *Bstrlwr(char *); -char *Bstrupr(char *); -#endif - // Copy min(strlen(src)+1, n) characters into dst, always terminate with a NUL. FORCE_INLINE char *Bstrncpyz(char *dst, const char *src, bsize_t n) { @@ -786,6 +833,69 @@ static inline void append_ext_UNSAFE(char *outbuf, const char *ext) Bstrcpy(p, ext); } + +/* Begin dependence on compat.o object. */ + + +#ifdef __cplusplus +extern "C" { +#endif + + +////////// Directory enumeration ////////// + +struct Bdirent +{ + uint16_t namlen; + char *name; + uint32_t mode; + uint32_t size; + uint32_t mtime; +}; + +typedef void BDIR; + +BDIR *Bopendir(const char *name); +struct Bdirent *Breaddir(BDIR *dir); +int32_t Bclosedir(BDIR *dir); + + +////////// Paths ////////// + +char *Bgethomedir(void); +char *Bgetappdir(void); + +int32_t Bcorrectfilename(char *filename, int32_t removefn); +int32_t Bcanonicalisefilename(char *filename, int32_t removefn); + +char *Bgetsystemdrives(void); + + +////////// String manipulation ////////// + +char *Bstrtoken(char *s, const char *delim, char **ptrptr, int chop); +char *Bstrtolower(char *str); + +#define Bwildmatch wildmatch + +#ifdef _WIN32 +# define Bstrlwr strlwr +# define Bstrupr strupr +#else +char *Bstrlwr(char *); +char *Bstrupr(char *); +#endif + + +////////// Miscellaneous ////////// + +int32_t Bfilelength(int32_t fd); + +uint32_t Bgetsysmemsize(void); + + +////////// PANICKING ALLOCATION WRAPPERS ////////// + #ifdef DEBUGGINGAIDS extern void xalloc_set_location(int32_t line, const char *file, const char *func); #endif @@ -828,86 +938,37 @@ FORCE_INLINE void *xrealloc(void * const ptr, const bsize_t size) } #if !defined NO_ALIGNED_MALLOC -FORCE_INLINE void *xaligned_malloc(const bsize_t alignment, const bsize_t size) +FORCE_INLINE void *xaligned_alloc(const bsize_t alignment, const bsize_t size) { -#ifdef _WIN32 - void *ptr = _aligned_malloc(size, alignment); -#elif defined __APPLE__ || defined EDUKE32_BSD - void *ptr = NULL; - posix_memalign(&ptr, alignment, size); -#else - void *ptr = memalign(alignment, size); -#endif - + void *ptr = Baligned_alloc(alignment, size); if (ptr == NULL) handle_memerr(); return ptr; } +#else +# define xaligned_alloc(alignment, size) xmalloc(size) +#endif + +#ifdef DEBUGGINGAIDS +# define EDUKE32_PRE_XALLLOC xalloc_set_location(__LINE__, __FILE__, EDUKE32_FUNCTION) +# define Xstrdup(s) (EDUKE32_PRE_XALLLOC, xstrdup(s)) +# define Xmalloc(size) (EDUKE32_PRE_XALLLOC, xmalloc(size)) +# define Xcalloc(nmemb, size) (EDUKE32_PRE_XALLLOC, xcalloc(nmemb, size)) +# define Xrealloc(ptr, size) (EDUKE32_PRE_XALLLOC, xrealloc(ptr, size)) +# define Xaligned_alloc(alignment, size) (EDUKE32_PRE_XALLLOC, xaligned_alloc(alignment, size)) +#else +# define Xstrdup xstrdup +# define Xmalloc xmalloc +# define Xcalloc xcalloc +# define Xrealloc xrealloc +# define Xaligned_alloc xaligned_alloc #endif #ifdef __cplusplus } #endif -#define DO_FREE_AND_NULL(var) do { \ - Bfree(var); (var) = NULL; \ -} while (0) -#define ALIGNED_FREE_AND_NULL(var) do { \ - Baligned_free(var); (var) = NULL; \ -} while (0) - -#define MAYBE_FCLOSE_AND_NULL(fileptr) do { \ - if (fileptr) { Bfclose(fileptr); fileptr=NULL; } \ -} while (0) - -#define ARRAY_SIZE(Ar) (sizeof(Ar)/sizeof((Ar)[0])) -#define ARRAY_SSIZE(Ar) (bssize_t)ARRAY_SIZE(Ar) - -////////// PANICKING ALLOCATION MACROS (wrapping the functions) ////////// -#ifdef DEBUGGINGAIDS -// Detection of __func__ or equivalent functionality, found in SDL_assert.h -# if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 supports __func__ as a standard. */ -# define EDUKE32_FUNCTION __func__ -# elif ((__GNUC__ >= 2) || defined(_MSC_VER)) -# define EDUKE32_FUNCTION __FUNCTION__ -# else -# define EDUKE32_FUNCTION "???" -# endif - -# define EDUKE32_PRE_XALLLOC xalloc_set_location(__LINE__, __FILE__, EDUKE32_FUNCTION) -# define Xstrdup(s) (EDUKE32_PRE_XALLLOC, xstrdup(s)) -# define Xmalloc(size) (EDUKE32_PRE_XALLLOC, xmalloc(size)) -# define Xcalloc(nmemb, size) (EDUKE32_PRE_XALLLOC, xcalloc(nmemb, size)) -# define Xrealloc(ptr, size) (EDUKE32_PRE_XALLLOC, xrealloc(ptr, size)) -# if !defined NO_ALIGNED_MALLOC -# define Xaligned_alloc(alignment, size) (EDUKE32_PRE_XALLLOC, xaligned_malloc(alignment, size)) -# else -# define Xaligned_alloc(alignment, size) Xmalloc(size) -# endif -# define Bexit(status) do { initprintf("exit(%d) at %s:%d in %s()\n", status, __FILE__, __LINE__, EDUKE32_FUNCTION); exit(status); } while (0) -#else -# define Xstrdup xstrdup -# define Xmalloc xmalloc -# define Xcalloc xcalloc -# define Xrealloc xrealloc -# if !defined NO_ALIGNED_MALLOC -# define Xaligned_alloc xaligned_malloc -# else -# define Xaligned_alloc(alignment, size) Xmalloc(size) -# endif -# define Bexit exit -#endif - -#ifdef __ANDROID__ -void eduke32_exit_return(int) ATTRIBUTE((noreturn)); -# define exit(x) eduke32_exit_return(x) -#endif - -#if defined _WIN32 && !defined NO_ALIGNED_MALLOC -# define Baligned_free _aligned_free -#else -# define Baligned_free Bfree -#endif +////////// More utility functions ////////// static inline void maybe_grow_buffer(char ** const buffer, int32_t * const buffersize, int32_t const newsize) { @@ -918,6 +979,38 @@ static inline void maybe_grow_buffer(char ** const buffer, int32_t * const buffe } } -////////// + +////////// Inlined external libraries ////////// + +#include "libdivide.h" + + +/* End dependence on compat.o object. */ + + +////////// EDuke32-specific features ////////// + +#ifndef TRUE +# define TRUE 1 +#endif + +#ifndef FALSE +# define FALSE 0 +#endif + +#define WITHKPLIB + +#if defined __ANDROID__ || defined EDUKE32_IOS +# define EDUKE32_TOUCH_DEVICES +# define EDUKE32_GLES +#endif + +#if DEBUGGINGAIDS>=2 +# define DEBUG_MAIN_ARRAYS +#endif + +#if !defined DEBUG_MAIN_ARRAYS +# define HAVE_CLIPSHAPE_FEATURE +#endif #endif // compat_h_