1 // Compiler implementation of the D programming language 2 // Copyright (c) 1999-2015 by Digital Mars 3 // All Rights Reserved 4 // written by Walter Bright 5 // http://www.digitalmars.com 6 // Distributed under the Boost Software License, Version 1.0. 7 // http://www.boost.org/LICENSE_1_0.txt 8 9 module ddmd.root.port; 10 11 import core.stdc.ctype; 12 import core.stdc..string; 13 import core.stdc.stdio; 14 import core.stdc.errno; 15 import core.math; 16 17 version(CRuntime_DigitalMars) __gshared extern (C) extern const(char)* __locale_decpoint; 18 version(CRuntime_Microsoft) extern(C++) struct longdouble { real r; } 19 version(CRuntime_Microsoft) extern(C++) size_t ld_sprint(char* str, int fmt, longdouble x); 20 21 extern (C) float strtof(const(char)* p, char** endp); 22 extern (C) double strtod(const(char)* p, char** endp); 23 24 version(CRuntime_Microsoft) 25 extern (C++) longdouble strtold_dm(const(char)* p, char** endp); 26 else 27 extern (C) real strtold(const(char)* p, char** endp); 28 29 version(CRuntime_Microsoft) 30 { 31 enum _OVERFLOW = 3; /* overflow range error */ 32 enum _UNDERFLOW = 4; /* underflow range error */ 33 34 extern (C) int _atoflt(float* value, const char * str); 35 extern (C) int _atodbl(double* value, const char * str); 36 } 37 38 extern (C++) struct Port 39 { 40 enum nan = double.nan; 41 enum infinity = double.infinity; 42 enum ldbl_max = real.max; 43 enum ldbl_nan = real.nan; 44 enum ldbl_infinity = real.infinity; 45 version(DigitalMars) 46 { 47 static __gshared bool yl2x_supported = true; 48 static __gshared bool yl2xp1_supported = true; 49 } 50 else 51 { 52 static __gshared bool yl2x_supported = false; 53 static __gshared bool yl2xp1_supported = false; 54 } 55 static __gshared real snan; 56 static this() 57 { 58 /* 59 * Use a payload which is different from the machine NaN, 60 * so that uninitialised variables can be 61 * detected even if exceptions are disabled. 62 */ 63 ushort* us = cast(ushort*)&snan; 64 us[0] = 0; 65 us[1] = 0; 66 us[2] = 0; 67 us[3] = 0xA000; 68 us[4] = 0x7FFF; 69 } 70 71 static bool isNan(double r) 72 { 73 return !(r == r); 74 } 75 76 static real sqrt(real x) 77 { 78 return .sqrt(x); 79 } 80 81 static real fmodl(real a, real b) 82 { 83 return a % b; 84 } 85 86 static real fequal(real a, real b) 87 { 88 return memcmp(&a, &b, 10) == 0; 89 } 90 91 static int memicmp(const char* s1, const char* s2, size_t n) 92 { 93 int result = 0; 94 95 for (int i = 0; i < n; i++) 96 { 97 char c1 = s1[i]; 98 char c2 = s2[i]; 99 100 result = c1 - c2; 101 if (result) 102 { 103 result = toupper(c1) - toupper(c2); 104 if (result) 105 break; 106 } 107 } 108 return result; 109 } 110 111 static char* strupr(char* s) 112 { 113 char* t = s; 114 115 while (*s) 116 { 117 *s = cast(char)toupper(*s); 118 s++; 119 } 120 121 return t; 122 } 123 124 static int isSignallingNan(double r) 125 { 126 return isNan(r) && !(((cast(ubyte*)&r)[6]) & 8); 127 } 128 129 static int isSignallingNan(real r) 130 { 131 return isNan(r) && !(((cast(ubyte*)&r)[7]) & 0x40); 132 } 133 134 version(CRuntime_Microsoft) 135 { 136 static int isSignallingNan(longdouble ld) 137 { 138 return isSignallingNan(*cast(real*)&ld); 139 } 140 } 141 142 static int isInfinity(double r) 143 { 144 return r is double.infinity || r is -double.infinity; 145 } 146 147 static float strtof(const(char)* p, char** endp) 148 { 149 version (CRuntime_DigitalMars) 150 { 151 auto save = __locale_decpoint; 152 __locale_decpoint = "."; 153 } 154 version (CRuntime_Microsoft) 155 { 156 float r; 157 if(endp) 158 { 159 r = .strtod(p, endp); // does not set errno for underflows, but unused 160 } 161 else 162 { 163 int res = _atoflt(&r, p); 164 if (res == _UNDERFLOW || res == _OVERFLOW) 165 errno = ERANGE; 166 } 167 } 168 else 169 { 170 auto r = .strtof(p, endp); 171 } 172 version (CRuntime_DigitalMars) __locale_decpoint = save; 173 return r; 174 } 175 176 static double strtod(const(char)* p, char** endp) 177 { 178 version (CRuntime_DigitalMars) 179 { 180 auto save = __locale_decpoint; 181 __locale_decpoint = "."; 182 } 183 version (CRuntime_Microsoft) 184 { 185 double r; 186 if(endp) 187 { 188 r = .strtod(p, endp); // does not set errno for underflows, but unused 189 } 190 else 191 { 192 int res = _atodbl(&r, p); 193 if (res == _UNDERFLOW || res == _OVERFLOW) 194 errno = ERANGE; 195 } 196 } 197 else 198 { 199 auto r = .strtod(p, endp); 200 } 201 version (CRuntime_DigitalMars) __locale_decpoint = save; 202 return r; 203 } 204 205 static real strtold(const(char)* p, char** endp) 206 { 207 version (CRuntime_DigitalMars) 208 { 209 auto save = __locale_decpoint; 210 __locale_decpoint = "."; 211 } 212 213 version (CRuntime_Microsoft) 214 auto r = .strtold_dm(p, endp).r; 215 else 216 auto r = .strtold(p, endp); 217 version (CRuntime_DigitalMars) __locale_decpoint = save; 218 return r; 219 } 220 221 static size_t ld_sprint(char* str, int fmt, real x) 222 { 223 version(CRuntime_Microsoft) 224 { 225 return .ld_sprint(str, fmt, longdouble(x)); 226 } 227 else 228 { 229 if ((cast(real)cast(ulong)x) == x) 230 { 231 // ((1.5 -> 1 -> 1.0) == 1.5) is false 232 // ((1.0 -> 1 -> 1.0) == 1.0) is true 233 // see http://en.cppreference.com/w/cpp/io/c/fprintf 234 char[5] sfmt = "%#Lg\0"; 235 sfmt[3] = cast(char)fmt; 236 return sprintf(str, sfmt.ptr, x); 237 } 238 else 239 { 240 char[4] sfmt = "%Lg\0"; 241 sfmt[2] = cast(char)fmt; 242 return sprintf(str, sfmt.ptr, x); 243 } 244 } 245 } 246 247 static void yl2x_impl(real* x, real* y, real* res) 248 { 249 version(DigitalMars) 250 *res = yl2x(*x, *y); 251 } 252 253 static void yl2xp1_impl(real* x, real* y, real* res) 254 { 255 version(DigitalMars) 256 *res = yl2xp1(*x, *y); 257 } 258 259 // Little endian 260 static void writelongLE(uint value, void* buffer) 261 { 262 auto p = cast(ubyte*)buffer; 263 p[3] = cast(ubyte)(value >> 24); 264 p[2] = cast(ubyte)(value >> 16); 265 p[1] = cast(ubyte)(value >> 8); 266 p[0] = cast(ubyte)(value); 267 } 268 269 // Little endian 270 static uint readlongLE(void* buffer) 271 { 272 auto p = cast(ubyte*)buffer; 273 return (((((p[3] << 8) | p[2]) << 8) | p[1]) << 8) | p[0]; 274 } 275 276 // Big endian 277 static void writelongBE(uint value, void* buffer) 278 { 279 auto p = cast(ubyte*)buffer; 280 p[0] = cast(ubyte)(value >> 24); 281 p[1] = cast(ubyte)(value >> 16); 282 p[2] = cast(ubyte)(value >> 8); 283 p[3] = cast(ubyte)(value); 284 } 285 286 // Big endian 287 static uint readlongBE(void* buffer) 288 { 289 auto p = cast(ubyte*)buffer; 290 return (((((p[0] << 8) | p[1]) << 8) | p[2]) << 8) | p[3]; 291 } 292 293 // Little endian 294 static uint readwordLE(void* buffer) 295 { 296 auto p = cast(ubyte*)buffer; 297 return (p[1] << 8) | p[0]; 298 } 299 300 // Big endian 301 static uint readwordBE(void* buffer) 302 { 303 auto p = cast(ubyte*)buffer; 304 return (p[0] << 8) | p[1]; 305 } 306 307 static void valcpy(void *dst, ulong val, size_t size) 308 { 309 switch (size) 310 { 311 case 1: *cast(ubyte *)dst = cast(ubyte)val; break; 312 case 2: *cast(ushort *)dst = cast(ushort)val; break; 313 case 4: *cast(uint *)dst = cast(uint)val; break; 314 case 8: *cast(ulong *)dst = cast(ulong)val; break; 315 default: assert(0); 316 } 317 } 318 }