1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
/*++
Module Name:
string.cpp
Abstract:
Implementation of the string functions in the C runtime library that are Windows specific.
--*/
#include "pal/palinternal.h"
#include "pal/dbgmsg.h"
#include "pal/cruntime.h"
#include <string.h>
#include <ctype.h>
#include <pthread.h>
#include <errno.h>
#include <limits.h>
#include <unistd.h>
SET_DEFAULT_DEBUG_CHANNEL(CRT);
/*++
Function:
_strnicmp
compare at most count characters from two strings, ignoring case
The strnicmp() function compares, with case insensitivity, at most count
characters from s1 to s2. All uppercase characters from s1 and s2 are
mapped to lowercase for the purposes of doing the comparison.
Returns:
Value Meaning
< 0 s1 is less than s2
0 s1 is equal to s2
> 0 s1 is greater than s2
--*/
int
__cdecl
_strnicmp( const char *s1, const char *s2, size_t count )
{
int ret;
PERF_ENTRY(_strnicmp);
ENTRY("_strnicmp (s1=%p (%s), s2=%p (%s), count=%d)\n", s1?s1:"NULL", s1?s1:"NULL", s2?s2:"NULL", s2?s2:"NULL", count);
ret = strncasecmp(s1, s2, count );
LOGEXIT("_strnicmp returning int %d\n", ret);
PERF_EXIT(_strnicmp);
return ret;
}
/*++
Function:
_stricmp
compare two strings, ignoring case
The stricmp() function compares, with case insensitivity, the string
pointed to by s1 to the string pointed to by s2. All uppercase
characters from s1 and s2 are mapped to lowercase for the purposes of
doing the comparison.
Returns:
Value Meaning
< 0 s1 is less than s2
0 s1 is equal to s2
> 0 s1 is greater than s2
--*/
int
__cdecl
_stricmp(
const char *s1,
const char *s2)
{
int ret;
PERF_ENTRY(_stricmp);
ENTRY("_stricmp (s1=%p (%s), s2=%p (%s))\n", s1?s1:"NULL", s1?s1:"NULL", s2?s2:"NULL", s2?s2:"NULL");
ret = strcasecmp(s1, s2);
LOGEXIT("_stricmp returning int %d\n", ret);
PERF_EXIT(_stricmp);
return ret;
}
/*++
Function:
_strlwr
Convert a string to lowercase.
This function returns a pointer to the converted string. Because the
modification is done in place, the pointer returned is the same as the
pointer passed as the input argument. No return value is reserved to
indicate an error.
Parameter
string Null-terminated string to convert to lowercase
Remarks
The _strlwr function converts any uppercase letters in string to
lowercase as determined by the LC_CTYPE category setting of the
current locale. Other characters are not affected. For more
information on LC_CTYPE, see setlocale.
--*/
char *
__cdecl
_strlwr(
char *str)
{
char *orig = str;
PERF_ENTRY(_strlwr);
ENTRY("_strlwr (str=%p (%s))\n", str?str:"NULL", str?str:"NULL");
while (*str)
{
*str = tolower(*str);
str++;
}
LOGEXIT("_strlwr returning char* %p (%s)\n", orig?orig:"NULL", orig?orig:"NULL");
PERF_EXIT(_strlwr);
return orig;
}
/*++
Function:
PAL_strtoul
Convert string to an unsigned long-integer value.
Return Value
strtoul returns the converted value, if any, or ULONG_MAX on
overflow. It returns 0 if no conversion can be performed. errno is
set to ERANGE if overflow or underflow occurs.
Parameters
szNumber Null-terminated string to convert to a ULONG
pszEnd Pointer to character that stops scan
nBase Number base to use
Remarks
strtoul stops reading the string szNumber at the first character it cannot
recognize as part of a number. This may be the terminating null
character, or it may be the first numeric character greater than or
equal to base. The LC_NUMERIC category setting of the current locale
determines recognition of the radix character in szNumber; for more
information, see setlocale. If pszEnd is not NULL, a pointer to the
character that stopped the scan is stored at the location pointed to
by pszEnd. If no conversion can be performed (no valid digits were
found or an invalid base was specified), the value of szNumber is stored
at the location pointed to by pszEnd.
Notes :
MSDN states that only space and tab are accepted as leading whitespace, but
tests indicate that other whitespace characters (newline, carriage return,
etc) are also accepted. This matches the behavior on Unix systems.
For strtoul, we need to check if the value to be returned
is outside the 32 bit range. If so, the returned value needs to be set
as appropriate, according to the MSDN pages and in all instances errno
must be set to ERANGE (The one exception is converting a string
representing a negative value to unsigned long).
Note that on 64 bit Windows, long's are still 32 bit. Thus, to match
Windows behavior, we must return long's in the 32 bit range.
--*/
/* The use of ULONG is by design, to ensure that a 32 bit value is always
returned from this function. If "unsigned long" is used instead of ULONG,
then a 64 bit value could be returned on 64 bit platforms like HP-UX, thus
breaking Windows behavior. */
ULONG
__cdecl
PAL_strtoul(const char *szNumber, char **pszEnd, int nBase)
{
unsigned long ulResult;
PERF_ENTRY(strtoul);
ENTRY("strtoul (szNumber=%p (%s), pszEnd=%p, nBase=%d)\n",
szNumber?szNumber:"NULL",
szNumber?szNumber:"NULL",
pszEnd,
nBase);
ulResult = strtoul(szNumber, pszEnd, nBase);
#ifdef BIT64
if (ulResult > _UI32_MAX)
{
char ch = *szNumber;
while (isspace(ch))
{
ch = *szNumber++;
}
/* If the string represents a positive number that is greater than
_UI32_MAX, set errno to ERANGE. Otherwise, don't set errno
to match Windows behavior. */
if (ch != '-')
{
ulResult = _UI32_MAX;
errno = ERANGE;
}
}
#endif
LOGEXIT("strtoul returning unsigned long %lu\n", ulResult);
PERF_EXIT(wcstoul);
/* When returning unsigned long res from this function, it will be
implicitly cast to ULONG. This handles situations where a string that
represents a negative number is passed in to strtoul. The Windows
behavior is analogous to taking the binary equivalent of the negative
value and treating it as a positive number. Returning a ULONG from
this function, as opposed to native unsigned long, allows us to match
this behavior. The explicit cast to ULONG below is used to silence any
potential warnings due to the implicit casting. */
return (ULONG)ulResult;
}
/*++
Function:
PAL_atol
Convert string to a long value.
Return Value
atol returns the converted value, if any. In the case of overflow,
the return value is undefined.
Parameters
szNumber Null-terminated string to convert to a LONG
--*/
/* The use of LONG is by design, to ensure that a 32 bit value is always
returned from this function. If "long" is used instead of LONG, then a 64 bit
value could be returned on 64 bit platforms like HP-UX, thus breaking
Windows behavior. */
LONG
__cdecl
PAL_atol(const char *szNumber)
{
long lResult;
PERF_ENTRY(atol);
ENTRY("atol (szNumber=%p (%s))\n",
szNumber?szNumber:"NULL"
);
lResult = atol(szNumber);
LOGEXIT("atol returning long %ld\n", (LONG)lResult);
PERF_EXIT(atol);
/* This explicit cast to LONG is used to silence any potential warnings
due to implicitly casting the native long lResult to LONG when returning. */
return (LONG)lResult;
}
|