diff --git a/RELEASES.txt b/RELEASES.txt index 2bf716c8..60aa2758 100644 --- a/RELEASES.txt +++ b/RELEASES.txt @@ -399,6 +399,10 @@ Planned constants internally (e.g. use 0x7fffffffL - 1L instead of -0x80000000L); this fixed a concrete problem with at least VS2010 + x64 +* Portability fix for avoiding direct function pointers to built-in functions + (especially math functions) because they may be implemented as inline + functions or macros on some platforms or polyfill headers + * Portability fixes for MSVC, avoid secure CRT warnings to work better with Windows Store apps diff --git a/src/duk_bi_math.c b/src/duk_bi_math.c index 7a5ed4b2..0d7afe31 100644 --- a/src/duk_bi_math.c +++ b/src/duk_bi_math.c @@ -191,8 +191,69 @@ static double duk__pow_fixed(double x, double y) { return DUK_DOUBLE_NAN; } +/* Wrappers for calling standard math library methods. These may be required + * on platforms where one or more of the math built-ins are defined as macros + * or inline functions and are thus not suitable to be used as function pointers. + */ +#if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS) +static double duk__fabs(double x) { + return fabs(x); +} +static double duk__acos(double x) { + return acos(x); +} +static double duk__asin(double x) { + return asin(x); +} +static double duk__atan(double x) { + return atan(x); +} +static double duk__ceil(double x) { + return ceil(x); +} +static double duk__cos(double x) { + return cos(x); +} +static double duk__exp(double x) { + return exp(x); +} +static double duk__floor(double x) { + return floor(x); +} +static double duk__log(double x) { + return log(x); +} +static double duk__sin(double x) { + return sin(x); +} +static double duk__sqrt(double x) { + return sqrt(x); +} +static double duk__tan(double x) { + return tan(x); +} +static double duk__atan2(double x, double y) { + return atan2(x, y); +} +#endif /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */ + /* order must match constants in genbuiltins.py */ static const duk__one_arg_func duk__one_arg_funcs[] = { +#if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS) + duk__fabs, + duk__acos, + duk__asin, + duk__atan, + duk__ceil, + duk__cos, + duk__exp, + duk__floor, + duk__log, + duk__round_fixed, + duk__sin, + duk__sqrt, + duk__tan +#else DUK_FABS, DUK_ACOS, DUK_ASIN, @@ -206,12 +267,18 @@ static const duk__one_arg_func duk__one_arg_funcs[] = { DUK_SIN, DUK_SQRT, DUK_TAN +#endif }; /* order must match constants in genbuiltins.py */ static const duk__two_arg_func duk__two_arg_funcs[] = { +#if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS) + duk__atan2, + duk__pow_fixed +#else DUK_ATAN2, duk__pow_fixed +#endif }; duk_ret_t duk_bi_math_object_onearg_shared(duk_context *ctx) { diff --git a/src/duk_features.h.in b/src/duk_features.h.in index 688f20b2..84ceaaee 100644 --- a/src/duk_features.h.in +++ b/src/duk_features.h.in @@ -1575,6 +1575,19 @@ typedef FILE duk_file; #define DUK_MEMZERO(p,n) \ DUK_MEMSET((p), 0, (n)) +/* + * Avoiding platform function pointers. + * + * On some platforms built-in functions may be implemented as macros or + * inline functions, so they can't be necessarily addressed by function + * pointers. This is certainly the case with some platform "polyfills" + * which provide missing C99/C++11 functions through macros, and may be + * the case with VS2013 (see GH-17). + */ + +/* This is now the default: the cost in footprint is negligible. */ +#define DUK_USE_AVOID_PLATFORM_FUNCPTRS + /* * Vararg macro wrappers. We need va_copy() which is defined in C99 / C++11, * so an awkward replacement is needed for pre-C99 / pre-C++11 environments.