From ea196c3befe9fefe287e483164dbbdbac9a288ee Mon Sep 17 00:00:00 2001 From: Sami Vaarala Date: Mon, 5 May 2014 18:25:15 +0300 Subject: [PATCH 01/17] fix variable declarations outside block top --- src/duk_hobject_props.c | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/src/duk_hobject_props.c b/src/duk_hobject_props.c index 09ef01e8..5709a5b5 100644 --- a/src/duk_hobject_props.c +++ b/src/duk_hobject_props.c @@ -1984,6 +1984,8 @@ int duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key) { if (duk__get_own_property_desc_raw(thr, h_target, key, arr_idx, &desc, 1 /*push_value*/)) { duk_tval *tv_hook = duk_require_tval(ctx, -3); /* value from hook */ duk_tval *tv_targ = duk_require_tval(ctx, -1); /* value from target */ + int datadesc_reject; + int accdesc_reject; DUK_DDD(DUK_DDDPRINT("proxy 'get': target has matching property %!O, check for " "conflicting property; tv_hook=%!T, tv_targ=%!T, desc.flags=0x%08x, " @@ -1991,14 +1993,14 @@ int duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key) { key, tv_hook, tv_targ, (int) desc.flags, (void *) desc.get, (void *) desc.set)); - int datadesc_reject = !(desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) && - !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && - !(desc.flags & DUK_PROPDESC_FLAG_WRITABLE) && - !duk_js_samevalue(tv_hook, tv_targ); - int accdesc_reject = (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) && - !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && - (desc.get == NULL) && - !DUK_TVAL_IS_UNDEFINED(tv_hook); + datadesc_reject = !(desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) && + !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && + !(desc.flags & DUK_PROPDESC_FLAG_WRITABLE) && + !duk_js_samevalue(tv_hook, tv_targ); + accdesc_reject = (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) && + !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && + (desc.get == NULL) && + !DUK_TVAL_IS_UNDEFINED(tv_hook); if (datadesc_reject || accdesc_reject) { DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "proxy get rejected"); } @@ -2769,6 +2771,8 @@ int duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, du if (duk__get_own_property_desc_raw(thr, h_target, key, arr_idx, &desc, 1 /*push_value*/)) { duk_tval *tv_targ = duk_require_tval(ctx, -1); + int datadesc_reject; + int accdesc_reject; DUK_DDD(DUK_DDDPRINT("proxy 'set': target has matching property %!O, check for " "conflicting property; tv_val=%!T, tv_targ=%!T, desc.flags=0x%08x, " @@ -2776,13 +2780,13 @@ int duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, du key, tv_val, tv_targ, (int) desc.flags, (void *) desc.get, (void *) desc.set)); - int datadesc_reject = !(desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) && - !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && - !(desc.flags & DUK_PROPDESC_FLAG_WRITABLE) && - !duk_js_samevalue(tv_val, tv_targ); - int accdesc_reject = (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) && - !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && - (desc.set == NULL); + datadesc_reject = !(desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) && + !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && + !(desc.flags & DUK_PROPDESC_FLAG_WRITABLE) && + !duk_js_samevalue(tv_val, tv_targ); + accdesc_reject = (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) && + !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && + (desc.set == NULL); if (datadesc_reject || accdesc_reject) { DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "proxy set rejected"); } @@ -3606,12 +3610,14 @@ int duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, in DUK_ASSERT(key != NULL); if (duk__get_own_property_desc_raw(thr, h_target, key, arr_idx, &desc, 0 /*push_value*/)) { + int desc_reject; + DUK_DDD(DUK_DDDPRINT("proxy 'deleteProperty': target has matching property %!O, check for " "conflicting property; desc.flags=0x%08x, " "desc.get=%p, desc.set=%p", key, (int) desc.flags, (void *) desc.get, (void *) desc.set)); - int desc_reject = !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE); + desc_reject = !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE); if (desc_reject) { /* unconditional */ DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "proxy deleteProperty rejected"); From 9d85ee153613b9d2c6aceb387688317375208afd Mon Sep 17 00:00:00 2001 From: Sami Vaarala Date: Mon, 5 May 2014 18:25:27 +0300 Subject: [PATCH 02/17] add missing duk_internal.h include --- src/duk_replacements.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/duk_replacements.c b/src/duk_replacements.c index 97eff8d9..fce1868e 100644 --- a/src/duk_replacements.c +++ b/src/duk_replacements.c @@ -6,6 +6,8 @@ * mimics the standard prototypes. */ +#include "duk_internal.h" + #ifdef DUK_USE_COMPUTED_NAN double duk_computed_nan; #endif From 922b832859f011be78d1138629d33dbf2fa61298 Mon Sep 17 00:00:00 2001 From: Sami Vaarala Date: Mon, 5 May 2014 18:26:17 +0300 Subject: [PATCH 03/17] bcc detection --- src/duk_features.h.in | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/duk_features.h.in b/src/duk_features.h.in index d9a540ee..fdb8e6ef 100644 --- a/src/duk_features.h.in +++ b/src/duk_features.h.in @@ -244,6 +244,11 @@ static __inline__ unsigned long long duk_rdtsc(void) { #define DUK_F_MINGW #endif +/* BCC (Bruce's C compiler): this is a "torture target" for compilation */ +#if defined(__BCC__) || defined(__BCC_VERSION__) +#define DUK_F_BCC +#endif + /* * Platform detection, system includes, Date provider selection. * @@ -484,8 +489,11 @@ static __inline__ unsigned long long duk_rdtsc(void) { #error cannot check complement of two #endif -/* Pointer size determination based on architecture. */ +/* Pointer size determination based on architecture. + * XXX: unsure about BCC correctness. + */ #if defined(DUK_F_X86) || defined(DUK_F_X32) || \ + defined(DUK_F_BCC) || \ (defined(__WORDSIZE) && (__WORDSIZE == 32)) #define DUK_F_32BIT_PTRS #elif defined(DUK_F_X64) || \ From 70d1cb2bf1b1b14dae7d72993974a8a701d0ded1 Mon Sep 17 00:00:00 2001 From: Sami Vaarala Date: Mon, 5 May 2014 18:38:26 +0300 Subject: [PATCH 04/17] avoid endian.h and stdint.h with BCC, force byteorder and align with BCC --- src/duk_features.h.in | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/duk_features.h.in b/src/duk_features.h.in index fdb8e6ef..739e588c 100644 --- a/src/duk_features.h.in +++ b/src/duk_features.h.in @@ -394,7 +394,11 @@ static __inline__ unsigned long long duk_rdtsc(void) { #define DUK_USE_DATE_PRS_STRPTIME #define DUK_USE_DATE_FMT_STRFTIME #include +#if defined(DUK_F_BCC) +/* no endian.h */ +#else #include +#endif /* DUK_F_BCC */ #include #include #include @@ -418,7 +422,11 @@ static __inline__ unsigned long long duk_rdtsc(void) { #define DUK_USE_DATE_PRS_STRPTIME #define DUK_USE_DATE_FMT_STRFTIME #include +#if defined(DUK_F_BCC) +/* no endian.h */ +#else #include +#endif /* DUK_F_BCC */ #include #include #include @@ -432,10 +440,10 @@ static __inline__ unsigned long long duk_rdtsc(void) { #include /* varargs */ #include #include /* e.g. ptrdiff_t */ -#ifdef DUK_F_TOS -/*FIXME*/ +#if defined(DUK_F_TOS) || defined(DUK_F_BCC) +/* stdint.h not available */ #else -/* XXX: technically C99 (C++11) but found in many systems */ +/* technically C99 (C++11) but found in many systems */ #include #endif #include @@ -869,7 +877,8 @@ typedef double duk_double_t; #define DUK_USE_ALIGN_4 #elif defined(DUK_F_MIPS) #define DUK_USE_ALIGN_4 -#elif defined(DUK_F_X86) || defined(DUK_F_X32) || defined(DUK_F_X64) +#elif defined(DUK_F_X86) || defined(DUK_F_X32) || defined(DUK_F_X64) || \ + defined(DUK_F_BCC) #define DUK_USE_UNALIGNED_ACCESSES_POSSIBLE #else /* unknown, use safe default */ @@ -1110,6 +1119,11 @@ typedef double duk_double_t; #endif #endif +/* Bruce's C Compiler (BCC), assume we're on x86. */ +#if !defined(DUK_F_BYTEORDER) && defined(DUK_F_BCC) +#define DUK_F_BYTEORDER 1 +#endif + /* Check whether or not byte order detection worked based on the intermediate * define, and define final values. If detection failed, #error out. */ From dd7552613282ced8a96af14203b68e66c8cbb63b Mon Sep 17 00:00:00 2001 From: Sami Vaarala Date: Mon, 5 May 2014 18:39:05 +0300 Subject: [PATCH 05/17] invert DUK_F_HAVE_64BIT determination to allow better if-else ladder --- src/duk_features.h.in | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/duk_features.h.in b/src/duk_features.h.in index 739e588c..9fdd5abf 100644 --- a/src/duk_features.h.in +++ b/src/duk_features.h.in @@ -661,20 +661,22 @@ typedef signed long duk_int32_t; #error cannot detect 32-bit type #endif -#define DUK_F_HAVE_64BIT +#undef DUK_F_HAVE_64BIT #if defined(ULONG_MAX) && (ULONG_MAX == 18446744073709551615ULL) +#define DUK_F_HAVE_64BIT typedef unsigned long duk_uint64_t; typedef signed long duk_int64_t; #elif defined(ULLONG_MAX) && (ULLONG_MAX == 18446744073709551615ULL) +#define DUK_F_HAVE_64BIT typedef unsigned long long duk_uint64_t; typedef signed long long duk_int64_t; #elif defined(DUK_F_MINGW) || defined(DUK_F_MSVC) /* Both MinGW and MSVC have a 64-bit type. */ +#define DUK_F_HAVE_64BIT typedef unsigned long duk_uint64_t; typedef signed long duk_int64_t; #else /* cannot detect 64-bit type, not always needed so don't error */ -#undef DUK_F_HAVE_64BIT #endif typedef duk_uint8_t duk_uint_least8_t; From 337f65bf1c8a122e41209e0575877141fc8ea59e Mon Sep 17 00:00:00 2001 From: Sami Vaarala Date: Mon, 5 May 2014 18:42:36 +0300 Subject: [PATCH 06/17] hide ULL constants from the preprocessor if they are not supported (as with BCC) --- src/duk_features.h.in | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/duk_features.h.in b/src/duk_features.h.in index 9fdd5abf..c4d29257 100644 --- a/src/duk_features.h.in +++ b/src/duk_features.h.in @@ -249,6 +249,14 @@ static __inline__ unsigned long long duk_rdtsc(void) { #define DUK_F_BCC #endif +#if defined(DUK_F_BCC) +/* preprocessor does not understand ULL constants (12345ULL) so we can't + * evaluate any expressions with them (e.g. BCC). + */ +#else +#define DUK_F_ULL_CONSTS +#endif + /* * Platform detection, system includes, Date provider selection. * @@ -662,6 +670,7 @@ typedef signed long duk_int32_t; #endif #undef DUK_F_HAVE_64BIT +#if defined(DUK_F_ULL_CONSTS) #if defined(ULONG_MAX) && (ULONG_MAX == 18446744073709551615ULL) #define DUK_F_HAVE_64BIT typedef unsigned long duk_uint64_t; @@ -678,6 +687,7 @@ typedef signed long duk_int64_t; #else /* cannot detect 64-bit type, not always needed so don't error */ #endif +#endif /* DUK_F_ULL_CONSTS */ typedef duk_uint8_t duk_uint_least8_t; typedef duk_int8_t duk_int_least8_t; @@ -745,6 +755,7 @@ typedef duk_int32_t duk_intmax_t; #define DUK_UINT_FAST32_MAX 0xffffffffUL #define DUK_INT_FAST32_MIN (-0x80000000L) #define DUK_INT_FAST32_MAX 0x7fffffffL +#if defined(DUK_F_HAVE_64BIT) #define DUK_UINT64_MIN 0ULL #define DUK_UINT64_MAX 0xffffffffffffffffULL #define DUK_INT64_MIN (-0x8000000000000000LL) @@ -757,6 +768,7 @@ typedef duk_int32_t duk_intmax_t; #define DUK_UINT_FAST64_MAX 0xffffffffffffffffULL #define DUK_INT_FAST64_MIN (-0x8000000000000000LL) #define DUK_INT_FAST64_MAX 0x7fffffffffffffffULL +#endif #define DUK_UINTPTR_MIN 0UL #define DUK_UINTPTR_MAX 0xffffffffUL #define DUK_INTPTR_MIN (-0x80000000L) From 03b0d33bff9bc2649512bb64fb2fc9fd8e7e97a2 Mon Sep 17 00:00:00 2001 From: Sami Vaarala Date: Mon, 5 May 2014 18:45:08 +0300 Subject: [PATCH 07/17] fix duk_intmax_t, duk_uintmax_t: duplicate definition, did not take 64-bit type availability into account for non-C99 build --- src/duk_features.h.in | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/duk_features.h.in b/src/duk_features.h.in index c4d29257..c22c75bd 100644 --- a/src/duk_features.h.in +++ b/src/duk_features.h.in @@ -701,8 +701,13 @@ typedef duk_uint16_t duk_uint_fast16_t; typedef duk_int16_t duk_int_fast16_t; typedef duk_uint32_t duk_uint_fast32_t; typedef duk_int32_t duk_int_fast32_t; +#if defined(DUK_F_HAVE_64BIT) +typedef duk_int64_t duk_intmax_t; +typedef duk_uint64_t duk_uintmax_t; +#else typedef duk_int32_t duk_intmax_t; typedef duk_uint32_t duk_uintmax_t; +#endif /* This detection is not very reliable. */ #if defined(DUK_F_32BIT_PTRS) @@ -715,10 +720,6 @@ typedef duk_uint64_t duk_uintptr_t; #error cannot determine intptr type #endif -/* Pretend that maximum int is 32 bits. */ -typedef duk_uint32_t duk_uintmax_t; -typedef duk_int32_t duk_intmax_t; - #define DUK_UINT8_MIN 0UL #define DUK_UINT8_MAX 0xffUL #define DUK_INT8_MIN (-0x80L) From 1d215dc089789e9addbbbab3a69e279c490b961c Mon Sep 17 00:00:00 2001 From: Sami Vaarala Date: Mon, 5 May 2014 18:47:03 +0300 Subject: [PATCH 08/17] use computed nan/infinity on bcc --- src/duk_features.h.in | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/duk_features.h.in b/src/duk_features.h.in index c22c75bd..ebac0612 100644 --- a/src/duk_features.h.in +++ b/src/duk_features.h.in @@ -249,6 +249,10 @@ static __inline__ unsigned long long duk_rdtsc(void) { #define DUK_F_BCC #endif +#if defined(__VBCC_) +#define DUK_F_VBCC +#endif + #if defined(DUK_F_BCC) /* preprocessor does not understand ULL constants (12345ULL) so we can't * evaluate any expressions with them (e.g. BCC). @@ -1211,7 +1215,7 @@ typedef double duk_double_t; #define DUK_DOUBLE_INFINITY (__builtin_inf()) #elif defined(INFINITY) #define DUK_DOUBLE_INFINITY ((double) INFINITY) -#elif !defined(__VBCC__) && !defined(_MSC_VER) +#elif !defined(__VBCC__) && !defined(DUK_F_MSVC) && !defined(DUK_F_BCC) #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. @@ -1226,7 +1230,7 @@ extern double duk_computed_infinity; #undef DUK_USE_COMPUTED_NAN #if defined(NAN) #define DUK_DOUBLE_NAN NAN -#elif !defined(__VBCC__) && !defined(_MSC_VER) +#elif !defined(__VBCC__) && !defined(DUK_F_MSVC) && !defined(DUK_F_BCC) #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. From 63095c16604ee3b8c8c7de5cae7a8e8bc31d5844 Mon Sep 17 00:00:00 2001 From: Sami Vaarala Date: Mon, 5 May 2014 18:48:52 +0300 Subject: [PATCH 09/17] fix DUK_F_VBCC detection, replace __VBCC__ with DUK_F_VBCC, also some _MSC_VER to DUK_F_MSVC replacements --- src/duk_features.h.in | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/duk_features.h.in b/src/duk_features.h.in index ebac0612..854937a3 100644 --- a/src/duk_features.h.in +++ b/src/duk_features.h.in @@ -249,7 +249,7 @@ static __inline__ unsigned long long duk_rdtsc(void) { #define DUK_F_BCC #endif -#if defined(__VBCC_) +#if defined(__VBCC__) #define DUK_F_VBCC #endif @@ -526,7 +526,7 @@ static __inline__ unsigned long long duk_rdtsc(void) { /* Intermediate define for 'have inttypes.h' */ #undef DUK_F_HAVE_INTTYPES #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ - !(defined(DUK_F_AMIGAOS) && defined(__VBCC__)) + !(defined(DUK_F_AMIGAOS) && defined(DUK_F_VBCC)) /* vbcc + AmigaOS has C99 but no inttypes.h */ #define DUK_F_HAVE_INTTYPES #elif defined(__cplusplus) && (__cplusplus >= 201103L) @@ -869,7 +869,7 @@ typedef double duk_double_t; * unless they are known to be unreliable. For instance, 64-bit types are * available on VBCC but seem to misbehave. */ -#if defined(DUK_F_HAVE_64BIT) && !defined(__VBCC__) +#if defined(DUK_F_HAVE_64BIT) && !defined(DUK_F_VBCC) #define DUK_USE_64BIT_OPS #else #undef DUK_USE_64BIT_OPS @@ -1215,7 +1215,7 @@ typedef double duk_double_t; #define DUK_DOUBLE_INFINITY (__builtin_inf()) #elif defined(INFINITY) #define DUK_DOUBLE_INFINITY ((double) INFINITY) -#elif !defined(__VBCC__) && !defined(DUK_F_MSVC) && !defined(DUK_F_BCC) +#elif !defined(DUK_F_VBCC) && !defined(DUK_F_MSVC) && !defined(DUK_F_BCC) #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. @@ -1230,7 +1230,7 @@ extern double duk_computed_infinity; #undef DUK_USE_COMPUTED_NAN #if defined(NAN) #define DUK_DOUBLE_NAN NAN -#elif !defined(__VBCC__) && !defined(DUK_F_MSVC) && !defined(DUK_F_BCC) +#elif !defined(DUK_F_VBCC) && !defined(DUK_F_MSVC) && !defined(DUK_F_BCC) #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. @@ -1259,7 +1259,7 @@ extern double duk_computed_nan; defined(FP_SUBNORMAL) && defined(FP_NORMAL)) /* missing some obvious constants */ #define DUK_F_USE_REPL_ALL -#elif defined(DUK_F_AMIGAOS) && defined(__VBCC__) +#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_FREEBSD) && defined(DUK_F_CLANG) @@ -1309,7 +1309,7 @@ extern double duk_computed_nan; */ #if defined(DUK_F_C99) && \ !defined(__UCLIBC__) /* uclibc may be missing these */ && \ - !(defined(DUK_F_AMIGAOS) && defined(__VBCC__)) /* vbcc + AmigaOS may be missing these */ + !(defined(DUK_F_AMIGAOS) && defined(DUK_F_VBCC)) /* vbcc + AmigaOS may be missing these */ #define DUK_USE_MATH_FMIN #define DUK_USE_MATH_FMAX #define DUK_USE_MATH_ROUND @@ -1496,7 +1496,7 @@ typedef FILE duk_file; #elif defined(__clang__) /* syntax same as gcc */ #define DUK_NORETURN(decl) decl __attribute__((noreturn)) -#elif defined(_MSC_VER) +#elif defined(DUK_F_MSVC) /* http://msdn.microsoft.com/en-us/library/aa235362(VS.60).aspx */ #define DUK_NORETURN(decl) __declspec(noreturn) decl #else @@ -1592,7 +1592,7 @@ typedef FILE duk_file; #define DUK_LINE_MACRO __LINE__ -#if !defined(__VBCC__) && !defined(_MSC_VER) +#if !defined(DUK_F_VBCC) && !defined(DUK_F_MSVC) #define DUK_FUNC_MACRO __func__ #else #define DUK_FUNC_MACRO "unknown" From 8615b19ff89ab41cbfdbf162b452aafb941ef3c4 Mon Sep 17 00:00:00 2001 From: Sami Vaarala Date: Mon, 5 May 2014 18:54:14 +0300 Subject: [PATCH 10/17] avoid auto initializers when variable is not static: these are rejected by some old compilers like bcc --- src/duk_api.c | 6 +++++- src/duk_api_logging.c | 3 ++- src/duk_bi_json.c | 3 ++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/duk_api.c b/src/duk_api.c index e945f52a..6f1ae7e3 100644 --- a/src/duk_api.c +++ b/src/duk_api.c @@ -1383,11 +1383,15 @@ static int duk__defaultvalue_coerce_attempt(duk_context *ctx, int index, int fun void duk_to_defaultvalue(duk_context *ctx, int index, int hint) { duk_hthread *thr = (duk_hthread *) ctx; duk_hobject *obj; - int coercers[] = { DUK_STRIDX_VALUE_OF, DUK_STRIDX_TO_STRING }; + /* inline initializer for coercers[] is not allowed by old compilers like BCC */ + int coercers[2]; DUK_ASSERT(ctx != NULL); DUK_ASSERT(thr != NULL); + coercers[0] = DUK_STRIDX_VALUE_OF; + coercers[1] = DUK_STRIDX_TO_STRING; + index = duk_require_normalize_index(ctx, index); if (!duk_is_object(ctx, index)) { diff --git a/src/duk_api_logging.c b/src/duk_api_logging.c index 5186cff5..02da2034 100644 --- a/src/duk_api_logging.c +++ b/src/duk_api_logging.c @@ -15,7 +15,8 @@ void duk_log(duk_context *ctx, int level, const char *fmt, ...) { duk_hthread *thr = (duk_hthread *) ctx; va_list ap; char buf[DUK__LOGFMT_BUFSIZE]; - duk_uint16_t stridx_logfunc[6] = { + /* stridx_logfunc[] must be static to allow initializer with old compilers like BCC */ + static const duk_uint16_t stridx_logfunc[6] = { DUK_STRIDX_LC_TRACE, DUK_STRIDX_LC_DEBUG, DUK_STRIDX_LC_INFO, DUK_STRIDX_LC_WARN, DUK_STRIDX_LC_ERROR, DUK_STRIDX_LC_FATAL }; diff --git a/src/duk_bi_json.c b/src/duk_bi_json.c index 0c4d1ca9..4b79fdcc 100644 --- a/src/duk_bi_json.c +++ b/src/duk_bi_json.c @@ -1860,7 +1860,8 @@ void duk_bi_json_stringify_helper(duk_context *ctx, if (duk_is_number(ctx, idx_space)) { double d; int nspace; - char spaces[10] = { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }; /* FIXME:helper */ + /* spaces[] must be static to allow initializer with old compilers like BCC */ + static const char spaces[10] = { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }; /* FIXME:helper */ /* ToInteger() coercion; NaN -> 0, infinities are clamped to 0 and 10 */ /* FIXME: get_clamped_int; double arithmetic is expensive */ From c889764db3ac9c3a7bc1f9f26971a3817422f9f8 Mon Sep 17 00:00:00 2001 From: Sami Vaarala Date: Mon, 5 May 2014 19:00:35 +0300 Subject: [PATCH 11/17] add stubbed Math built-in for BCC torturing --- src/duk_bi_math.c | 33 +++++++++++++++++++++++++++++++++ src/duk_features.h.in | 6 ++++++ 2 files changed, 39 insertions(+) diff --git a/src/duk_bi_math.c b/src/duk_bi_math.c index c22cb349..7a5ed4b2 100644 --- a/src/duk_bi_math.c +++ b/src/duk_bi_math.c @@ -4,6 +4,8 @@ #include "duk_internal.h" +#if defined(DUK_USE_MATH_BUILTIN) + /* * Use static helpers which can work with math.h functions matching * the following signatures. This is not portable if any of these math @@ -248,3 +250,34 @@ duk_ret_t duk_bi_math_object_random(duk_context *ctx) { duk_push_number(ctx, (duk_double_t) duk_util_tinyrandom_get_double((duk_hthread *) ctx)); return 1; } + +#else /* DUK_USE_MATH_BUILTIN */ + +/* A stubbed built-in is useful for e.g. compilation torture testing with BCC. */ + +duk_ret_t duk_bi_math_object_onearg_shared(duk_context *ctx) { + DUK_UNREF(ctx); + return DUK_RET_UNIMPLEMENTED_ERROR; +} + +duk_ret_t duk_bi_math_object_twoarg_shared(duk_context *ctx) { + DUK_UNREF(ctx); + return DUK_RET_UNIMPLEMENTED_ERROR; +} + +duk_ret_t duk_bi_math_object_max(duk_context *ctx) { + DUK_UNREF(ctx); + return DUK_RET_UNIMPLEMENTED_ERROR; +} + +duk_ret_t duk_bi_math_object_min(duk_context *ctx) { + DUK_UNREF(ctx); + return DUK_RET_UNIMPLEMENTED_ERROR; +} + +duk_ret_t duk_bi_math_object_random(duk_context *ctx) { + DUK_UNREF(ctx); + return DUK_RET_UNIMPLEMENTED_ERROR; +} + +#endif /* DUK_USE_MATH_BUILTIN */ diff --git a/src/duk_features.h.in b/src/duk_features.h.in index 854937a3..1fe89707 100644 --- a/src/duk_features.h.in +++ b/src/duk_features.h.in @@ -1779,6 +1779,12 @@ typedef FILE duk_file; * Ecmascript features / compliance options */ +#if defined(DUK_F_BCC) +/* Math built-in is stubbed out on BCC to allow compiler torture testing. */ +#else +#define DUK_USE_MATH_BUILTIN +#endif + #define DUK_USE_REGEXP_SUPPORT #if defined(DUK_OPT_NO_REGEXP_SUPPORT) #undef DUK_USE_REGEXP_SUPPORT From 69bd47dfd3f866d30ede92feb0995984634d2dd0 Mon Sep 17 00:00:00 2001 From: Sami Vaarala Date: Mon, 5 May 2014 19:01:49 +0300 Subject: [PATCH 12/17] don't do function pointer casting in initializers, it breaks bcc compilation --- src/genbuiltins.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/genbuiltins.py b/src/genbuiltins.py index 8de9107a..c03a8c83 100644 --- a/src/genbuiltins.py +++ b/src/genbuiltins.py @@ -1443,7 +1443,10 @@ class GenBuiltins: genc.emitLine('/* native functions: %d */' % len(self.native_func_list)) genc.emitLine('const duk_c_function duk_bi_native_functions[] = {') for i in self.native_func_list: - genc.emitLine('\t(duk_c_function) %s,' % i) + # The function pointer cast here makes BCC complain about + # "initializer too complicated", so omit the cast. + #genc.emitLine('\t(duk_c_function) %s,' % i) + genc.emitLine('\t%s,' % i) genc.emitLine('};') def generateDefineNames(self, id): From 7189f98a933d703c2b8ebe9f83dbcdedb26d84ed Mon Sep 17 00:00:00 2001 From: Sami Vaarala Date: Mon, 5 May 2014 19:02:27 +0300 Subject: [PATCH 13/17] comment inside assert macro breaks bcc build --- src/duk_js_executor.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/duk_js_executor.c b/src/duk_js_executor.c index f7cecbf8..d2c7131c 100644 --- a/src/duk_js_executor.c +++ b/src/duk_js_executor.c @@ -756,8 +756,8 @@ static int duk__handle_longjmp(duk_hthread *thr, DUK_HOBJECT_IS_COMPILEDFUNCTION((resumee->callstack + resumee->callstack_top - 2)->func))); /* an Ecmascript function */ DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_YIELDED || (resumee->callstack + resumee->callstack_top - 2)->idx_retval >= 0); /* waiting for a value */ - DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_INACTIVE || /* INACTIVE: no activation, single function value on valstack */ - resumee->callstack_top == 0); + DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_INACTIVE || + resumee->callstack_top == 0); /* INACTIVE: no activation, single function value on valstack */ DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_INACTIVE || (resumee->valstack_top == resumee->valstack + 1 && DUK_TVAL_IS_OBJECT(resumee->valstack_top - 1) && From 4455aaffd0307e1a082da6ad0a1cef4de19c233c Mon Sep 17 00:00:00 2001 From: Sami Vaarala Date: Mon, 5 May 2014 19:09:15 +0300 Subject: [PATCH 14/17] fix some preprocessor constants which were missing L specifier --- src/duk_features.h.in | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/duk_features.h.in b/src/duk_features.h.in index 1fe89707..2e1e13d0 100644 --- a/src/duk_features.h.in +++ b/src/duk_features.h.in @@ -223,7 +223,7 @@ static __inline__ unsigned long long duk_rdtsc(void) { #define DUK_F_GCC #if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) /* Convenience, e.g. gcc 4.5.1 == 40501; http://stackoverflow.com/questions/6031819/emulating-gccs-builtin-unreachable */ -#define DUK_F_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +#define DUK_F_GCC_VERSION (__GNUC__ * 10000L + __GNUC_MINOR__ * 100L + __GNUC_PATCHLEVEL__) #else #error cannot figure out gcc version #endif @@ -310,7 +310,7 @@ static __inline__ unsigned long long duk_rdtsc(void) { #if defined(DUK_F_QNX) && defined(DUK_COMPILING_DUKTAPE) /* See: /opt/qnx650/target/qnx6/usr/include/sys/platform.h */ #define _XOPEN_SOURCE 600 -#define _POSIX_C_SOURCE 200112 +#define _POSIX_C_SOURCE 200112L #endif #if defined(__APPLE__) @@ -491,7 +491,7 @@ static __inline__ unsigned long long duk_rdtsc(void) { * format characters need to be changed. */ #if defined(INT_MAX) -#if INT_MAX < 2147483647 +#if INT_MAX < 2147483647L #error INT_MAX too small, expected int to be 32 bits at least #endif #else @@ -1490,7 +1490,7 @@ typedef FILE duk_file; * http://clang.llvm.org/docs/LanguageExtensions.html */ -#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 20500) +#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 20500L) /* since gcc-2.5 */ #define DUK_NORETURN(decl) decl __attribute__((noreturn)) #elif defined(__clang__) @@ -1514,7 +1514,7 @@ typedef FILE duk_file; * http://clang.llvm.org/docs/LanguageExtensions.html */ -#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40500) +#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40500L) /* since gcc-4.5 */ #define DUK_UNREACHABLE() do { __builtin_unreachable(); } while(0) #elif defined(__clang__) && defined(__has_builtin) @@ -1563,7 +1563,7 @@ typedef FILE duk_file; #endif #if defined(DUK_USE_BRANCH_HINTS) -#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERISON >= 40500) +#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERISON >= 40500L) /* GCC: test not very accurate; enable only in relatively recent builds * because of bugs in gcc-4.4 (http://lists.debian.org/debian-gcc/2010/04/msg00000.html) */ From 7387fcda14a54ed628e225c94aa1a526123df94c Mon Sep 17 00:00:00 2001 From: Sami Vaarala Date: Mon, 5 May 2014 19:14:00 +0300 Subject: [PATCH 15/17] cast switch argument to duk_small_int_t to ensure it fits into compiler 'int'; this was broken when compiler 'int' is 16 bits --- src/duk_bi_duktape.c | 2 +- src/duk_bi_string.c | 2 +- src/duk_heap_alloc.c | 2 +- src/duk_heap_markandsweep.c | 2 +- src/duk_heap_refcount.c | 4 ++-- src/duk_js_executor.c | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/duk_bi_duktape.c b/src/duk_bi_duktape.c index ddb6bec7..5a123024 100644 --- a/src/duk_bi_duktape.c +++ b/src/duk_bi_duktape.c @@ -49,7 +49,7 @@ duk_ret_t duk_bi_duktape_object_info(duk_context *ctx) { /* heaphdr size and additional allocation size, followed by * type specific stuff (with varying value count) */ - switch (DUK_HEAPHDR_GET_TYPE(h)) { + switch ((duk_small_int_t) DUK_HEAPHDR_GET_TYPE(h)) { case DUK_HTYPE_STRING: { duk_hstring *h_str = (duk_hstring *) h; duk_push_int(ctx, (int) (sizeof(duk_hstring) + DUK_HSTRING_GET_BYTELEN(h_str) + 1)); diff --git a/src/duk_bi_string.c b/src/duk_bi_string.c index 961bf344..ba9ea080 100644 --- a/src/duk_bi_string.c +++ b/src/duk_bi_string.c @@ -655,7 +655,7 @@ duk_ret_t duk_bi_string_prototype_replace(duk_context *ctx) { } ch2 = r[0]; - switch (ch2) { + switch ((duk_small_int_t) ch2) { case (duk_int_t) '$': { ch1 = (1 << 8) + (duk_int_t) '$'; goto repl_write; diff --git a/src/duk_heap_alloc.c b/src/duk_heap_alloc.c index c5ebf1ee..1d90804f 100644 --- a/src/duk_heap_alloc.c +++ b/src/duk_heap_alloc.c @@ -69,7 +69,7 @@ void duk_heap_free_heaphdr_raw(duk_heap *heap, duk_heaphdr *hdr) { DUK_DDD(DUK_DDDPRINT("free heaphdr %p, htype %d", (void *) hdr, (int) DUK_HEAPHDR_GET_TYPE(hdr))); - switch (DUK_HEAPHDR_GET_TYPE(hdr)) { + switch ((duk_small_int_t) DUK_HEAPHDR_GET_TYPE(hdr)) { case DUK_HTYPE_STRING: /* no inner refs to free */ break; diff --git a/src/duk_heap_markandsweep.c b/src/duk_heap_markandsweep.c index ea3534b3..204e77ec 100644 --- a/src/duk_heap_markandsweep.c +++ b/src/duk_heap_markandsweep.c @@ -156,7 +156,7 @@ static void duk__mark_heaphdr(duk_heap *heap, duk_heaphdr *h) { heap->mark_and_sweep_recursion_depth++; - switch (DUK_HEAPHDR_GET_TYPE(h)) { + switch ((duk_small_int_t) DUK_HEAPHDR_GET_TYPE(h)) { case DUK_HTYPE_STRING: duk__mark_hstring(heap, (duk_hstring *) h); break; diff --git a/src/duk_heap_refcount.c b/src/duk_heap_refcount.c index 9d0cdca6..c7a2a50d 100644 --- a/src/duk_heap_refcount.c +++ b/src/duk_heap_refcount.c @@ -144,7 +144,7 @@ static void duk__refcount_finalize_hobject(duk_hthread *thr, duk_hobject *h) { void duk_heap_refcount_finalize_heaphdr(duk_hthread *thr, duk_heaphdr *hdr) { DUK_ASSERT(hdr); - switch (DUK_HEAPHDR_GET_TYPE(hdr)) { + switch ((duk_small_int_t) DUK_HEAPHDR_GET_TYPE(hdr)) { case DUK_HTYPE_OBJECT: duk__refcount_finalize_hobject(thr, (duk_hobject *) hdr); break; @@ -421,7 +421,7 @@ void duk_heap_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h) { } #endif - switch (DUK_HEAPHDR_GET_TYPE(h)) { + switch ((duk_small_int_t) DUK_HEAPHDR_GET_TYPE(h)) { case DUK_HTYPE_STRING: /* * Strings have no internal references but do have "weak" diff --git a/src/duk_js_executor.c b/src/duk_js_executor.c index d2c7131c..4d9c1d64 100644 --- a/src/duk_js_executor.c +++ b/src/duk_js_executor.c @@ -1656,7 +1656,7 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) { ins = bcode[act->pc++]; - switch (DUK_DEC_OP(ins)) { + switch ((duk_small_int_t) DUK_DEC_OP(ins)) { case DUK_OP_LDREG: { int t; From 467112d04c23e99a4d19b2b9a075cdcd63d086e5 Mon Sep 17 00:00:00 2001 From: Sami Vaarala Date: Mon, 5 May 2014 19:14:33 +0300 Subject: [PATCH 16/17] BCC note --- website/guide/portability.html | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/website/guide/portability.html b/website/guide/portability.html index 67916a6d..b35fc289 100644 --- a/website/guide/portability.html +++ b/website/guide/portability.html @@ -177,6 +177,13 @@ detail below the table.

32-bit Java. Tested with CrossBridge 1.0.1 on 64-bit Windows 7. + +Linux +BCC
(Bruce's C compiler) +i386 +-3 and -ansi required; compiles but doesn't link. This is an + old compiler useful for portability torture tests (for instance 16-bit integers). + From 4296fb40e612151ff2612402c8bff7096bd16376 Mon Sep 17 00:00:00 2001 From: Sami Vaarala Date: Mon, 5 May 2014 19:21:46 +0300 Subject: [PATCH 17/17] document bcc compilation issues; they're most likely similar to problems encountered with other older compilers --- doc/code-issues.txt | 147 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) diff --git a/doc/code-issues.txt b/doc/code-issues.txt index 89c9be1f..76e48147 100644 --- a/doc/code-issues.txt +++ b/doc/code-issues.txt @@ -147,6 +147,34 @@ Be careful especially of assertions, debug prints, and other macros:: DUK_UNREF(y); int flags = 0; /* problem: DUK_UNREF() */ +Note that even **disabled** debug prints break the variable declaration +part because disabled debug prints are replaced with ``do {} while (0)`` +(this is intentional to flush out this kind of errors even in release +builds):: + + { + int x; + + DUK_DDD(DUK_DDDPRINT("debug print")); + + int y; /* error here */ + + x = 123; + ... + } + +The fix is:: + + { + int x; + int y; + + DUK_DDD(DUK_DDDPRINT("debug print")); + + x = 123; + ... + } + Include guards -------------- @@ -626,6 +654,118 @@ EBCDIC See separate section below. +Portability issues on very old compilers +======================================== + +Initialization of auto arrays +----------------------------- + +Some old compilers (such as bcc) refuse to compile the following (error +message is something along the lines of: initialization of auto arrays +is illegal):: + + int myarray[] = { 123, 234 }; + +or even:: + + int myarray[2] = { 123, 234 }; + +Apparently the following would be legal:: + + static int myarray[2] = { 123, 234 }; + +The workaround is to use a static array or initialize explicitly:: + + int myarray[2]; + + myarray[0] = 123; + myarray[1] = 234; + +Initializer is too complicated (bcc) +------------------------------------ + +BCC complains about "initializer is too complicated" when a function pointer +array contains casts:: + + ... + (duk_c_function) my_function, + ... + +This works:: + + ... + my_function, + ... + +Non-integral selector in switch (bcc) +------------------------------------- + +For some reason BCC fails to compile switch statements where the value is +obtained with a macro such as:: + + switch (DUK_DEC_OP(ins)) { + ... + } + +This is probably caused by the fact that ``DUK_DEC_OP(ins)`` is a 32-bit value +while BCC's integer type is 16 bits. Switch argument needs to be ``int``, so +one needs to:: + + switch ((int) DUK_DEC_OP(ins)) { + ... + } + +Or perhaps (using type wrappers):: + + switch ((duk_small_int_t) DUK_DEC_OP(ins)) { + ... + } + +Division by zero is a compile error +----------------------------------- + +Attempting to create NaN or infinity values with expressions like ``0/0`` and +``1/0`` are treated as compile errors by some compilers (such as BCC) while +others will just replace them with an incorrect value (e.g. VBCC replaces them +with zero). Run-time computed NaN / infinity values are needed on such platforms. + +ULL integer constants may cause an error +---------------------------------------- + +The following may cause a compilation error (e.g. BCC):: + + #if defined(ULONG_MAX) && (ULONG_MAX == 18446744073709551615ULL) + +The error happens even if ``ULONG_MAX`` is not defined. Instead, this needs +to be restructured in one of several ways. For instance, old compilers can be +rejected explicitly:: + + #if defined(DUK_F_BCC) + /* cannot check ULONG_MAX */ + #else + #if defined(ULONG_MAX) && (ULONG_MAX == 18446744073709551615ULL) + /* ... */ + #endif + #endif + +The important point is that the old compiler cannot process the preprocessor +line containing the integer constant; if it processes even part of the line, +it may choke on a syntax error. + +Comments inside macro arguments may cause an error (BCC) +-------------------------------------------------------- + +The following causes an error on BCC:: + + DUK_ASSERT(FOO || /* foo happens */ + BAR); + +The comment causes BCC to produce an error like "incorrect number of macro +arguments". The fix is to remove the comment from inside the macro:: + + DUK_ASSERT(FOO || + BAR); + Character values in char literals and strings, EBCDIC ===================================================== @@ -839,3 +979,10 @@ clang ----- Clang has some issues with union aliasing. See ``misc/clang_aliasing.c``. + +bcc +--- + +BCC is not a realistic compilation target at the moment but serves as a nice +"torture target". Various issues have been documented above in portability +issues.