1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5/*++
6
7
8
9Module Name:
10
11 cruntime/misc.cpp
12
13Abstract:
14
15 Implementation of C runtime functions that don't fit anywhere else.
16
17
18
19--*/
20
21#include "pal/thread.hpp"
22#include "pal/threadsusp.hpp"
23#include "pal/palinternal.h"
24#include "pal/dbgmsg.h"
25#include "pal/misc.h"
26
27#include <errno.h>
28/* <stdarg.h> needs to be included after "palinternal.h" to avoid name
29 collision for va_start and va_end */
30#include <stdarg.h>
31#include <time.h>
32#include <limits.h>
33
34#if defined(_AMD64_) || defined(_x86_)
35#include <xmmintrin.h>
36#endif // defined(_AMD64_) || defined(_x86_)
37#if defined(_DEBUG)
38#include <assert.h>
39#endif //defined(_DEBUG)
40
41SET_DEFAULT_DEBUG_CHANNEL(CRT);
42
43using namespace CorUnix;
44
45/*++
46Function:
47 _gcvt_s
48
49See MSDN doc.
50--*/
51char *
52__cdecl
53_gcvt_s( char * buffer, int iSize, double value, int digits )
54{
55 PERF_ENTRY(_gcvt);
56 ENTRY( "_gcvt( value:%f digits=%d, buffer=%p )\n", value, digits, buffer );
57
58 if ( !buffer )
59 {
60 ERROR( "buffer was an invalid pointer.\n" );
61 }
62
63 switch ( digits )
64 {
65 case 7 :
66 /* Fall through */
67 case 8 :
68 /* Fall through */
69 case 15 :
70 /* Fall through */
71 case 17 :
72
73 sprintf_s( buffer, iSize, "%.*g", digits, value );
74 break;
75
76 default :
77 ASSERT( "Only the digits 7, 8, 15, and 17 are valid.\n" );
78 *buffer = '\0';
79 }
80
81 LOGEXIT( "_gcvt returns %p (%s)\n", buffer , buffer );
82 PERF_EXIT(_gcvt);
83 return buffer;
84}
85
86
87/*++
88Function :
89
90 __iscsym
91
92See MSDN for more details.
93--*/
94int
95__cdecl
96__iscsym( int c )
97{
98 PERF_ENTRY(__iscsym);
99 ENTRY( "__iscsym( c=%d )\n", c );
100
101 if ( isalnum( c ) || c == '_' )
102 {
103 LOGEXIT( "__iscsym returning 1\n" );
104 PERF_EXIT(__iscsym);
105 return 1;
106 }
107
108 LOGEXIT( "__iscsym returning 0\n" );
109 PERF_EXIT(__iscsym);
110 return 0;
111}
112
113
114/*++
115
116Function :
117
118 PAL_errno
119
120 Returns the address of the errno.
121
122--*/
123int * __cdecl PAL_errno( int caller )
124{
125 int *retval;
126 PERF_ENTRY(errno);
127 ENTRY( "PAL_errno( void )\n" );
128 retval = (INT*)(&errno);
129 LOGEXIT("PAL_errno returns %p\n",retval);
130 PERF_EXIT(errno);
131 return retval;
132}
133
134/*++
135Function:
136
137 mktime
138
139See MSDN for more details.
140--*/
141
142PAL_time_t
143__cdecl
144PAL_mktime(struct PAL_tm *tm)
145{
146 time_t result;
147 struct tm tmpTm;
148
149 PERF_ENTRY(mktime);
150 ENTRY( "mktime( tm=%p )\n",tm );
151
152 /*copy the value of Windows struct into BSD struct*/
153 tmpTm.tm_sec = tm->tm_sec;
154 tmpTm.tm_min = tm->tm_min;
155 tmpTm.tm_hour = tm->tm_hour;
156 tmpTm.tm_mday = tm->tm_mday;
157 tmpTm.tm_mon = tm->tm_mon;
158 tmpTm.tm_year = tm->tm_year;
159 tmpTm.tm_wday = tm->tm_wday;
160 tmpTm.tm_yday = tm->tm_yday;
161 tmpTm.tm_isdst = tm->tm_isdst;
162
163 result = mktime(&tmpTm);
164
165 LOGEXIT( "mktime returned %#lx\n",result );
166 PERF_EXIT(mktime);
167 return result;
168}
169
170/*++
171Function:
172
173 rand
174
175 The RAND_MAX value can vary by platform.
176
177See MSDN for more details.
178--*/
179int
180__cdecl
181PAL_rand(void)
182{
183 int ret;
184 PERF_ENTRY(rand);
185 ENTRY("rand(void)\n");
186
187 ret = (rand() % (PAL_RAND_MAX + 1));
188
189 LOGEXIT("rand() returning %d\n", ret);
190 PERF_EXIT(rand);
191 return ret;
192}
193
194
195/*++
196Function:
197
198 time
199
200See MSDN for more details.
201--*/
202PAL_time_t
203__cdecl
204PAL_time(PAL_time_t *tloc)
205{
206 time_t result;
207
208 PERF_ENTRY(time);
209 ENTRY( "time( tloc=%p )\n",tloc );
210
211 result = time(tloc);
212
213 LOGEXIT( "time returning %#lx\n",result );
214 PERF_EXIT(time);
215 return result;
216}
217
218
219PALIMPORT
220void __cdecl
221PAL_qsort(void *base, size_t nmemb, size_t size,
222 int (__cdecl *compar )(const void *, const void *))
223{
224 PERF_ENTRY(qsort);
225 ENTRY("qsort(base=%p, nmemb=%lu, size=%lu, compar=%p\n",
226 base,(unsigned long) nmemb,(unsigned long) size, compar);
227
228/* reset ENTRY nesting level back to zero, qsort will invoke app-defined
229 callbacks and we want their entry traces... */
230#if _ENABLE_DEBUG_MESSAGES_
231{
232 int old_level;
233 old_level = DBG_change_entrylevel(0);
234#endif /* _ENABLE_DEBUG_MESSAGES_ */
235
236 qsort(base,nmemb,size,compar);
237
238/* ...and set nesting level back to what it was */
239#if _ENABLE_DEBUG_MESSAGES_
240 DBG_change_entrylevel(old_level);
241}
242#endif /* _ENABLE_DEBUG_MESSAGES_ */
243
244 LOGEXIT("qsort returns\n");
245 PERF_EXIT(qsort);
246}
247
248PALIMPORT
249void * __cdecl
250PAL_bsearch(const void *key, const void *base, size_t nmemb, size_t size,
251 int (__cdecl *compar)(const void *, const void *))
252{
253 void *retval;
254
255 PERF_ENTRY(bsearch);
256 ENTRY("bsearch(key=%p, base=%p, nmemb=%lu, size=%lu, compar=%p\n",
257 key, base, (unsigned long) nmemb, (unsigned long) size, compar);
258
259/* reset ENTRY nesting level back to zero, bsearch will invoke app-defined
260 callbacks and we want their entry traces... */
261#if _ENABLE_DEBUG_MESSAGES_
262{
263 int old_level;
264 old_level = DBG_change_entrylevel(0);
265#endif /* _ENABLE_DEBUG_MESSAGES_ */
266
267 retval = bsearch(key,base,nmemb,size,compar);
268
269/* ...and set nesting level back to what it was */
270#if _ENABLE_DEBUG_MESSAGES_
271 DBG_change_entrylevel(old_level);
272}
273#endif /* _ENABLE_DEBUG_MESSAGES_ */
274
275 LOGEXIT("bsearch returns %p\n",retval);
276 PERF_EXIT(bsearch);
277 return retval;
278}
279
280#ifdef _AMD64_
281
282PALIMPORT
283unsigned int PAL__mm_getcsr(void)
284{
285 return _mm_getcsr();
286}
287
288PALIMPORT
289void PAL__mm_setcsr(unsigned int i)
290{
291 _mm_setcsr(i);
292}
293
294#endif // _AMD64_
295
296/*++
297Function:
298PAL_memcpy
299
300Overlapping buffer-safe version of memcpy.
301See MSDN doc for memcpy
302--*/
303EXTERN_C
304PALIMPORT
305void *PAL_memcpy (void *dest, const void *src, size_t count)
306{
307 UINT_PTR x = (UINT_PTR)dest, y = (UINT_PTR)src;
308 _ASSERTE((x + count <= y) || (y + count <= x));
309
310 void *ret;
311 #undef memcpy
312 ret = memcpy(dest, src, count);
313 return ret;
314}
315