/* An abort()-like primitive is needed by the default fatal error handler. */ #if !defined(DUK_ABORT) #define DUK_ABORT abort #endif #if !defined(DUK_SETJMP) #define DUK_JMPBUF_TYPE jmp_buf #define DUK_SETJMP(jb) setjmp((jb)) #define DUK_LONGJMP(jb) longjmp((jb), 1) #endif #if 0 /* sigsetjmp() alternative */ #define DUK_JMPBUF_TYPE sigjmp_buf #define DUK_SETJMP(jb) sigsetjmp((jb)) #define DUK_LONGJMP(jb) siglongjmp((jb), 1) #endif /* Special naming to avoid conflict with e.g. DUK_FREE() in duk_heap.h * (which is unfortunately named). May sometimes need replacement, e.g. * some compilers don't handle zero length or NULL correctly in realloc(). */ #if !defined(DUK_ANSI_MALLOC) #define DUK_ANSI_MALLOC malloc #endif #if !defined(DUK_ANSI_REALLOC) #define DUK_ANSI_REALLOC realloc #endif #if !defined(DUK_ANSI_CALLOC) #define DUK_ANSI_CALLOC calloc #endif #if !defined(DUK_ANSI_FREE) #define DUK_ANSI_FREE free #endif /* ANSI C (various versions) and some implementations require that the * pointer arguments to memset(), memcpy(), and memmove() be valid values * even when byte size is 0 (even a NULL pointer is considered invalid in * this context). Zero-size operations as such are allowed, as long as their * pointer arguments point to a valid memory area. The DUK_MEMSET(), * DUK_MEMCPY(), and DUK_MEMMOVE() macros require this same behavior, i.e.: * (1) pointers must be valid and non-NULL, (2) zero size must otherwise be * allowed. If these are not fulfilled, a macro wrapper is needed. * * http://stackoverflow.com/questions/5243012/is-it-guaranteed-to-be-safe-to-perform-memcpy0-0-0 * http://lists.cs.uiuc.edu/pipermail/llvmdev/2007-October/011065.html * * Not sure what's the required behavior when a pointer points just past the * end of a buffer, which often happens in practice (e.g. zero size memmoves). * For example, if allocation size is 3, the following pointer would not * technically point to a valid memory byte: * * <-- alloc --> * | 0 | 1 | 2 | ..... * ^-- p=3, points after last valid byte (2) */ #if !defined(DUK_MEMCPY) #if defined(DUK_F_UCLIBC) /* Old uclibcs have a broken memcpy so use memmove instead (this is overly wide * now on purpose): http://lists.uclibc.org/pipermail/uclibc-cvs/2008-October/025511.html */ #define DUK_MEMCPY memmove #else #define DUK_MEMCPY memcpy #endif #endif #if !defined(DUK_MEMMOVE) #define DUK_MEMMOVE memmove #endif #if !defined(DUK_MEMCMP) #define DUK_MEMCMP memcmp #endif #if !defined(DUK_MEMSET) #define DUK_MEMSET memset #endif #if !defined(DUK_STRLEN) #define DUK_STRLEN strlen #endif #if !defined(DUK_STRCMP) #define DUK_STRCMP strcmp #endif #if !defined(DUK_STRNCMP) #define DUK_STRNCMP strncmp #endif #if !defined(DUK_SPRINTF) #define DUK_SPRINTF sprintf #endif #if !defined(DUK_SNPRINTF) /* snprintf() is technically not part of C89 but usually available. */ #define DUK_SNPRINTF snprintf #endif #if !defined(DUK_VSPRINTF) #define DUK_VSPRINTF vsprintf #endif #if !defined(DUK_VSNPRINTF) /* vsnprintf() is technically not part of C89 but usually available. */ #define DUK_VSNPRINTF vsnprintf #endif #if !defined(DUK_SSCANF) #define DUK_SSCANF sscanf #endif #if !defined(DUK_VSSCANF) #define DUK_VSSCANF vsscanf #endif #if !defined(DUK_MEMZERO) #define DUK_MEMZERO(p,n) DUK_MEMSET((p), 0, (n)) #endif #if !defined(DUK_DOUBLE_INFINITY) #undef DUK_USE_COMPUTED_INFINITY #if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION < 40600) /* GCC older than 4.6: avoid overflow warnings related to using INFINITY */ #define DUK_DOUBLE_INFINITY (__builtin_inf()) #elif defined(INFINITY) #define DUK_DOUBLE_INFINITY ((double) INFINITY) #elif !defined(DUK_F_VBCC) && !defined(DUK_F_MSVC) && !defined(DUK_F_BCC) && \ !defined(DUK_F_OLD_SOLARIS) && !defined(DUK_F_AIX) #define DUK_DOUBLE_INFINITY (1.0 / 0.0) #else /* In VBCC (1.0 / 0.0) results in a warning and 0.0 instead of infinity. * Use a computed infinity (initialized when a heap is created at the * latest). */ #define DUK_USE_COMPUTED_INFINITY #define DUK_DOUBLE_INFINITY duk_computed_infinity #endif #endif #if !defined(DUK_DOUBLE_NAN) #undef DUK_USE_COMPUTED_NAN #if defined(NAN) #define DUK_DOUBLE_NAN NAN #elif !defined(DUK_F_VBCC) && !defined(DUK_F_MSVC) && !defined(DUK_F_BCC) && \ !defined(DUK_F_OLD_SOLARIS) && !defined(DUK_F_AIX) #define DUK_DOUBLE_NAN (0.0 / 0.0) #else /* In VBCC (0.0 / 0.0) results in a warning and 0.0 instead of NaN. * In MSVC (VS2010 Express) (0.0 / 0.0) results in a compile error. * Use a computed NaN (initialized when a heap is created at the * latest). */ #define DUK_USE_COMPUTED_NAN #define DUK_DOUBLE_NAN duk_computed_nan #endif #endif /* Many platforms are missing fpclassify() and friends, so use replacements * if necessary. The replacement constants (FP_NAN etc) can be anything but * match Linux constants now. */ #undef DUK_USE_REPL_FPCLASSIFY #undef DUK_USE_REPL_SIGNBIT #undef DUK_USE_REPL_ISFINITE #undef DUK_USE_REPL_ISNAN #undef DUK_USE_REPL_ISINF /* Complex condition broken into separate parts. */ #undef DUK_F_USE_REPL_ALL #if !(defined(FP_NAN) && defined(FP_INFINITE) && defined(FP_ZERO) && \ defined(FP_SUBNORMAL) && defined(FP_NORMAL)) /* Missing some obvious constants. */ #define DUK_F_USE_REPL_ALL #elif defined(DUK_F_AMIGAOS) && defined(DUK_F_VBCC) /* VBCC is missing the built-ins even in C99 mode (perhaps a header issue). */ #define DUK_F_USE_REPL_ALL #elif defined(DUK_F_AMIGAOS) && defined(DUK_F_M68K) /* AmigaOS + M68K seems to have math issues even when using GCC cross * compilation. Use replacements for all AmigaOS versions on M68K * regardless of compiler. */ #define DUK_F_USE_REPL_ALL #elif defined(DUK_F_FREEBSD) && defined(DUK_F_CLANG) /* Placeholder fix for (detection is wider than necessary): * http://llvm.org/bugs/show_bug.cgi?id=17788 */ #define DUK_F_USE_REPL_ALL #elif defined(DUK_F_UCLIBC) /* At least some uclibc versions have broken floating point math. For * example, fpclassify() can incorrectly classify certain NaN formats. * To be safe, use replacements. */ #define DUK_F_USE_REPL_ALL #elif defined(DUK_F_AIX) /* Older versions may be missing isnan(), etc. */ #define DUK_F_USE_REPL_ALL #endif #if defined(DUK_F_USE_REPL_ALL) #define DUK_USE_REPL_FPCLASSIFY #define DUK_USE_REPL_SIGNBIT #define DUK_USE_REPL_ISFINITE #define DUK_USE_REPL_ISNAN #define DUK_USE_REPL_ISINF #define DUK_FPCLASSIFY duk_repl_fpclassify #define DUK_SIGNBIT duk_repl_signbit #define DUK_ISFINITE duk_repl_isfinite #define DUK_ISNAN duk_repl_isnan #define DUK_ISINF duk_repl_isinf #define DUK_FP_NAN 0 #define DUK_FP_INFINITE 1 #define DUK_FP_ZERO 2 #define DUK_FP_SUBNORMAL 3 #define DUK_FP_NORMAL 4 #else #define DUK_FPCLASSIFY fpclassify #define DUK_SIGNBIT signbit #define DUK_ISFINITE isfinite #define DUK_ISNAN isnan #define DUK_ISINF isinf #define DUK_FP_NAN FP_NAN #define DUK_FP_INFINITE FP_INFINITE #define DUK_FP_ZERO FP_ZERO #define DUK_FP_SUBNORMAL FP_SUBNORMAL #define DUK_FP_NORMAL FP_NORMAL #endif #if defined(DUK_F_USE_REPL_ALL) #undef DUK_F_USE_REPL_ALL #endif /* These functions don't currently need replacement but are wrapped for * completeness. Because these are used as function pointers, they need * to be defined as concrete C functions (not macros). */ #if !defined(DUK_FABS) #define DUK_FABS fabs #endif #if !defined(DUK_FLOOR) #define DUK_FLOOR floor #endif #if !defined(DUK_CEIL) #define DUK_CEIL ceil #endif #if !defined(DUK_FMOD) #define DUK_FMOD fmod #endif #if !defined(DUK_POW) #define DUK_POW pow #endif #if !defined(DUK_ACOS) #define DUK_ACOS acos #endif #if !defined(DUK_ASIN) #define DUK_ASIN asin #endif #if !defined(DUK_ATAN) #define DUK_ATAN atan #endif #if !defined(DUK_ATAN2) #define DUK_ATAN2 atan2 #endif #if !defined(DUK_SIN) #define DUK_SIN sin #endif #if !defined(DUK_COS) #define DUK_COS cos #endif #if !defined(DUK_TAN) #define DUK_TAN tan #endif #if !defined(DUK_EXP) #define DUK_EXP exp #endif #if !defined(DUK_LOG) #define DUK_LOG log #endif #if !defined(DUK_SQRT) #define DUK_SQRT sqrt #endif /* The functions below exist only in C99/C++11 or later and need a workaround * for platforms that don't include them. MSVC isn't detected as C99, but * these functions also exist in MSVC 2013 and later so include a clause for * that too. Android doesn't have log2; disable all of these for Android. */ #if (defined(DUK_F_C99) || defined(DUK_F_CPP11) || (defined(_MSC_VER) && (_MSC_VER >= 1800))) && \ !defined(DUK_F_ANDROID) && !defined(DUK_F_MINT) #if !defined(DUK_CBRT) #define DUK_CBRT cbrt #endif #if !defined(DUK_LOG2) #define DUK_LOG2 log2 #endif #if !defined(DUK_LOG10) #define DUK_LOG10 log10 #endif #if !defined(DUK_TRUNC) #define DUK_TRUNC trunc #endif #endif /* DUK_F_C99 etc */ /* NetBSD 6.0 x86 (at least) has a few problems with pow() semantics, * see test-bug-netbsd-math-pow.js. MinGW has similar (but different) * issues, see test-bug-mingw-math-issues.js. Enable pow() workarounds * for these targets. */ #undef DUK_USE_POW_WORKAROUNDS #if defined(DUK_F_NETBSD) || defined(DUK_F_MINGW) #define DUK_USE_POW_WORKAROUNDS #endif /* Similar workarounds for atan2() semantics issues. MinGW issues are * documented in test-bug-mingw-math-issues.js. */ #undef DUK_USE_ATAN2_WORKAROUNDS #if defined(DUK_F_MINGW) #define DUK_USE_ATAN2_WORKAROUNDS #endif /* Rely as little as possible on compiler behavior for NaN comparison, * signed zero handling, etc. Currently never activated but may be needed * for broken compilers. */ #undef DUK_USE_PARANOID_MATH /* There was a curious bug where test-bi-date-canceling.js would fail e.g. * on 64-bit Ubuntu, gcc-4.8.1, -m32, and no -std=c99. Some date computations * using doubles would be optimized which then broke some corner case tests. * The problem goes away by adding 'volatile' to the datetime computations. * Not sure what the actual triggering conditions are, but using this on * non-C99 systems solves the known issues and has relatively little cost * on other platforms. */ #undef DUK_USE_PARANOID_DATE_COMPUTATION #if !defined(DUK_F_C99) #define DUK_USE_PARANOID_DATE_COMPUTATION #endif