327 lines
10 KiB
C
327 lines
10 KiB
C
/* 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
|