1 /**
2  * Portable routines for functions that have different implementations on different platforms.
3  *
4  * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
5  * Authors:   Walter Bright, http://www.digitalmars.com
6  * License:   $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
7  * Source:    $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/port.d, root/_port.d)
8  * Documentation:  https://dlang.org/phobos/dmd_root_port.html
9  * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/root/port.d
10  */
11 
12 module dmd.root.port;
13 
14 import core.stdc.ctype;
15 import core.stdc.errno;
16 import core.stdc..string;
17 import core.stdc.stdio;
18 import core.stdc.stdlib;
19 
20 nothrow @nogc:
21 
22 private extern (C)
23 {
24     version(CRuntime_DigitalMars) __gshared extern const(char)* __locale_decpoint;
25 
26     version(CRuntime_Microsoft)
27     {
28         enum _OVERFLOW  = 3;   /* overflow range error */
29         enum _UNDERFLOW = 4;   /* underflow range error */
30 
31         int _atoflt(float*  value, const(char)* str);
32         int _atodbl(double* value, const(char)* str);
33     }
34 }
35 
36 extern (C++) struct Port
37 {
38     nothrow @nogc:
39 
40     static int memicmp(scope const char* s1, scope const char* s2, size_t n) pure
41     {
42         int result = 0;
43 
44         foreach (i; 0 .. n)
45         {
46             char c1 = s1[i];
47             char c2 = s2[i];
48 
49             result = c1 - c2;
50             if (result)
51             {
52                 result = toupper(c1) - toupper(c2);
53                 if (result)
54                     break;
55             }
56         }
57         return result;
58     }
59 
60     static char* strupr(char* s) pure
61     {
62         char* t = s;
63 
64         while (*s)
65         {
66             *s = cast(char)toupper(*s);
67             s++;
68         }
69 
70         return t;
71     }
72 
73     static bool isFloat32LiteralOutOfRange(scope const(char)* s)
74     {
75         errno = 0;
76         version (CRuntime_DigitalMars)
77         {
78             auto save = __locale_decpoint;
79             __locale_decpoint = ".";
80         }
81         version (CRuntime_Microsoft)
82         {
83             float r;
84             int res = _atoflt(&r, s);
85             if (res == _UNDERFLOW || res == _OVERFLOW)
86                 errno = ERANGE;
87         }
88         else
89         {
90             strtof(s, null);
91         }
92         version (CRuntime_DigitalMars) __locale_decpoint = save;
93         return errno == ERANGE;
94     }
95 
96     static bool isFloat64LiteralOutOfRange(scope const(char)* s)
97     {
98         errno = 0;
99         version (CRuntime_DigitalMars)
100         {
101             auto save = __locale_decpoint;
102             __locale_decpoint = ".";
103         }
104         version (CRuntime_Microsoft)
105         {
106             double r;
107             int res = _atodbl(&r, s);
108             if (res == _UNDERFLOW || res == _OVERFLOW)
109                 errno = ERANGE;
110         }
111         else
112         {
113             strtod(s, null);
114         }
115         version (CRuntime_DigitalMars) __locale_decpoint = save;
116         return errno == ERANGE;
117     }
118 
119     // Little endian
120     static void writelongLE(uint value, scope void* buffer) pure
121     {
122         auto p = cast(ubyte*)buffer;
123         p[3] = cast(ubyte)(value >> 24);
124         p[2] = cast(ubyte)(value >> 16);
125         p[1] = cast(ubyte)(value >> 8);
126         p[0] = cast(ubyte)(value);
127     }
128 
129     // Little endian
130     static uint readlongLE(scope const void* buffer) pure
131     {
132         auto p = cast(const ubyte*)buffer;
133         return (((((p[3] << 8) | p[2]) << 8) | p[1]) << 8) | p[0];
134     }
135 
136     // Big endian
137     static void writelongBE(uint value, scope void* buffer) pure
138     {
139         auto p = cast(ubyte*)buffer;
140         p[0] = cast(ubyte)(value >> 24);
141         p[1] = cast(ubyte)(value >> 16);
142         p[2] = cast(ubyte)(value >> 8);
143         p[3] = cast(ubyte)(value);
144     }
145 
146     // Big endian
147     static uint readlongBE(scope const void* buffer) pure
148     {
149         auto p = cast(const ubyte*)buffer;
150         return (((((p[0] << 8) | p[1]) << 8) | p[2]) << 8) | p[3];
151     }
152 
153     // Little endian
154     static uint readwordLE(scope const void* buffer) pure
155     {
156         auto p = cast(const ubyte*)buffer;
157         return (p[1] << 8) | p[0];
158     }
159 
160     // Big endian
161     static uint readwordBE(scope const void* buffer) pure
162     {
163         auto p = cast(const ubyte*)buffer;
164         return (p[0] << 8) | p[1];
165     }
166 
167     static void valcpy(scope void *dst, ulong val, size_t size) pure
168     {
169         switch (size)
170         {
171             case 1: *cast(ubyte *)dst = cast(ubyte)val; break;
172             case 2: *cast(ushort *)dst = cast(ushort)val; break;
173             case 4: *cast(uint *)dst = cast(uint)val; break;
174             case 8: *cast(ulong *)dst = cast(ulong)val; break;
175             default: assert(0);
176         }
177     }
178 }