diff --git a/dmd2/expression.c b/dmd2/expression.c index 9fd2eb1c..2e7aeeb6 100644 --- a/dmd2/expression.c +++ b/dmd2/expression.c @@ -2567,7 +2567,7 @@ void floatToBuffer(OutBuffer *buf, Type *type, real_t value) real_t r = strtold(buffer, NULL); __locale_decpoint = save; #else - real_t r = strtold(buffer, NULL); + real_t r = Port::strtold(buffer, NULL); #endif #if IN_LLVM if (r == value) // if exact duplication diff --git a/dmd2/lexer.c b/dmd2/lexer.c index 2e53a992..4d92e357 100644 --- a/dmd2/lexer.c +++ b/dmd2/lexer.c @@ -2365,7 +2365,7 @@ done: #ifdef IN_GCC t->float80value = real_t::parse((char *)stringbuffer.data, real_t::LongDouble); #else - t->float80value = strtold((char *)stringbuffer.data, NULL); + t->float80value = Port::strtold((char *)stringbuffer.data, NULL); #endif errno = 0; float strtofres; diff --git a/dmd2/root/longdouble.h b/dmd2/root/longdouble.h index 99f91f4d..0e8e4498 100644 --- a/dmd2/root/longdouble.h +++ b/dmd2/root/longdouble.h @@ -34,6 +34,12 @@ typedef volatile long double volatile_longdouble; // template longdouble ldouble(T x) { return (longdouble) x; } #define ldouble(x) ((longdouble)(x)) +#if __MINGW32__ +// MinGW supports 80 bit reals, but the formatting functions map to versions +// from the MSVC runtime by default which don't. +#define sprintf __mingw_sprintf +#endif + inline size_t ld_sprint(char* str, int fmt, longdouble x) { char sfmt[4] = "%Lg"; @@ -41,6 +47,10 @@ inline size_t ld_sprint(char* str, int fmt, longdouble x) return sprintf(str, sfmt, x); } +#if __MINGW32__ +#undef sprintf +#endif + #else #include diff --git a/dmd2/root/port.c b/dmd2/root/port.c index 820a36e8..4422809a 100644 --- a/dmd2/root/port.c +++ b/dmd2/root/port.c @@ -348,9 +348,201 @@ int Port::stricmp(const char *s1, const char *s2) return ::stricmp(s1, s2); } +// See vcbuild/strtold.c. +longdouble strtold(const char *p, char **endp); + +longdouble Port::strtold(const char *p, char **endp) +{ + return ::strtold(p, endp); +} + #endif -#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __HAIKU__ || __MINGW32__ +#if __MINGW32__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static double zero = 0; +double Port::nan = copysign(NAN, 1.0); +double Port::infinity = 1 / zero; +double Port::dbl_max = 1.7976931348623157e308; +double Port::dbl_min = 5e-324; +longdouble Port::ldbl_max = LDBL_MAX; + +struct PortInitializer +{ + PortInitializer(); +}; + +static PortInitializer portinitializer; + +PortInitializer::PortInitializer() +{ + assert(!signbit(Port::nan)); +} + +int Port::isNan(double r) +{ + return isnan(r); +} + +int Port::isNan(longdouble r) +{ + return isnan(r); +} + +int Port::isSignallingNan(double r) +{ + /* A signalling NaN is a NaN with 0 as the most significant bit of + * its significand, which is bit 51 of 0..63 for 64 bit doubles. + */ + return isNan(r) && !((((unsigned char*)&r)[6]) & 8); +} + +int Port::isSignallingNan(longdouble r) +{ + /* A signalling NaN is a NaN with 0 as the most significant bit of + * its significand, which is bit 62 of 0..79 for 80 bit reals. + */ + return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40); +} + +int Port::isFinite(double r) +{ + return ::finite(r); +} + +int Port::isInfinity(double r) +{ + return isinf(r); +} + +int Port::Signbit(double r) +{ + union { double d; long long ll; } u; + u.d = r; + return u.ll < 0; +} + +double Port::floor(double d) +{ + return ::floor(d); +} + +double Port::pow(double x, double y) +{ + return ::pow(x, y); +} + +longdouble Port::fmodl(longdouble x, longdouble y) +{ + return ::fmodl(x, y); +} + +unsigned long long Port::strtoull(const char *p, char **pend, int base) +{ + return ::strtoull(p, pend, base); +} + +char *Port::ull_to_string(char *buffer, ulonglong ull) +{ + sprintf(buffer, "%llu", ull); + return buffer; +} + +wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull) +{ + swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull); + return buffer; +} + +double Port::ull_to_double(ulonglong ull) +{ + return (double) ull; +} + +const char *Port::list_separator() +{ + return ","; +} + +const wchar_t *Port::wlist_separator() +{ + return L","; +} + +char *Port::strupr(char *s) +{ + char *t = s; + + while (*s) + { + *s = toupper(*s); + s++; + } + + return t; +} + +int Port::memicmp(const char *s1, const char *s2, int n) +{ + int result = 0; + + for (int i = 0; i < n; i++) + { char c1 = s1[i]; + char c2 = s2[i]; + + result = c1 - c2; + if (result) + { + result = toupper(c1) - toupper(c2); + if (result) + break; + } + } + return result; +} + +int Port::stricmp(const char *s1, const char *s2) +{ + int result = 0; + + for (;;) + { char c1 = *s1; + char c2 = *s2; + + result = c1 - c2; + if (result) + { + result = toupper(c1) - toupper(c2); + if (result) + break; + } + if (!c1) + break; + s1++; + s2++; + } + return result; +} + +longdouble Port::strtold(const char *p, char **endp) +{ + return ::__mingw_strtold(p, endp); +} + +#endif + +#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __HAIKU__ #include #if linux @@ -408,7 +600,7 @@ int Port::isNan(double r) #else return __inline_isnan(r); #endif -#elif __HAIKU__ || __OpenBSD__ || __MINGW32__ +#elif __HAIKU__ || __OpenBSD__ return isnan(r); #else #undef isnan @@ -424,7 +616,7 @@ int Port::isNan(longdouble r) #else return __inline_isnan(r); #endif -#elif __HAIKU__ || __OpenBSD__ || __MINGW32__ +#elif __HAIKU__ || __OpenBSD__ return isnan(r); #else #undef isnan @@ -460,7 +652,7 @@ int Port::isInfinity(double r) { #if __APPLE__ return fpclassify(r) == FP_INFINITE; -#elif defined __HAIKU__ || __OpenBSD__ || __MINGW32__ +#elif defined __HAIKU__ || __OpenBSD__ return isinf(r); #else #undef isinf @@ -586,6 +778,11 @@ int Port::stricmp(const char *s1, const char *s2) return result; } +longdouble Port::strtold(const char *p, char **endp) +{ + return ::strtold(p, endp); +} + #endif #if __sun @@ -731,4 +928,9 @@ char *Port::strupr(char *s) return t; } +longdouble Port::strtold(const char *p, char **endp) +{ + return ::strtold(p, endp); +} + #endif diff --git a/dmd2/root/port.h b/dmd2/root/port.h index c02675d0..41c2aaff 100644 --- a/dmd2/root/port.h +++ b/dmd2/root/port.h @@ -19,8 +19,6 @@ #if _MSC_VER #include // for _isnan #include // for alloca -// According to VC 8.0 docs, long double is the same as double -longdouble strtold(const char *p,char **endp); #define strtof strtod #define isnan _isnan @@ -41,14 +39,6 @@ struct Port static double dbl_min; static longdouble ldbl_max; -#if !defined __HAIKU__ || __OpenBSD__ -#elif __GNUC__ - // These conflict with macros in math.h, should rename them - #undef isnan - #undef isfinite - #undef isinfinity - #undef signbit -#endif static int isNan(double); static int isNan(longdouble); @@ -80,6 +70,8 @@ struct Port static int memicmp(const char *s1, const char *s2, int n); static int stricmp(const char *s1, const char *s2); + + static longdouble strtold(const char *p, char **endp); }; #endif