ntdll: Handle SIMD exceptions.
[wine] / dlls / ntdll / string.c
1 /*
2  * NTDLL string functions
3  *
4  * Copyright 2000 Alexandre Julliard
5  * Copyright 2000 Jon Griffiths
6  * Copyright 2003 Thomas Mertes
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <ctype.h>
27 #include <stdarg.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <search.h>
32
33 #include "windef.h"
34 #include "winternl.h"
35
36
37 /*********************************************************************
38  *                  memchr   (NTDLL.@)
39  */
40 void * __cdecl NTDLL_memchr( const void *ptr, int c, size_t n )
41 {
42     return memchr( ptr, c, n );
43 }
44
45
46 /*********************************************************************
47  *                  memcmp   (NTDLL.@)
48  */
49 int __cdecl NTDLL_memcmp( const void *ptr1, const void *ptr2, size_t n )
50 {
51     return memcmp( ptr1, ptr2, n );
52 }
53
54
55 /*********************************************************************
56  *                  memcpy   (NTDLL.@)
57  *
58  * NOTES
59  *  Behaves like memmove.
60  */
61 void * __cdecl NTDLL_memcpy( void *dst, const void *src, size_t n )
62 {
63     return memmove( dst, src, n );
64 }
65
66
67 /*********************************************************************
68  *                  memmove   (NTDLL.@)
69  */
70 void * __cdecl NTDLL_memmove( void *dst, const void *src, size_t n )
71 {
72     return memmove( dst, src, n );
73 }
74
75
76 /*********************************************************************
77  *                  memset   (NTDLL.@)
78  */
79 void * __cdecl NTDLL_memset( void *dst, int c, size_t n )
80 {
81     return memset( dst, c, n );
82 }
83
84
85 /*********************************************************************
86  *                  bsearch   (NTDLL.@)
87  */
88 void * __cdecl NTDLL_bsearch( const void *key, const void *base, size_t nmemb,
89                               size_t size, int (*compar)(const void *, const void *) )
90 {
91     return bsearch( key, base, nmemb, size, compar );
92 }
93
94
95 /*********************************************************************
96  *                  qsort   (NTDLL.@)
97  */
98 void __cdecl NTDLL_qsort( void *base, size_t nmemb, size_t size,
99                           int(*compar)(const void *, const void *) )
100 {
101     return qsort( base, nmemb, size, compar );
102 }
103
104
105 /*********************************************************************
106  *                  _lfind   (NTDLL.@)
107  */
108 void * __cdecl _lfind( const void *key, const void *base, unsigned int *nmemb,
109                        unsigned int size, int(*compar)(const void *, const void *) )
110 {
111     return lfind( key, base, nmemb, size, compar );
112 }
113
114
115 /*********************************************************************
116  *                  strcat   (NTDLL.@)
117  */
118 char * __cdecl NTDLL_strcat( char *dst, const char *src )
119 {
120     return strcat( dst, src );
121 }
122
123
124 /*********************************************************************
125  *                  strchr   (NTDLL.@)
126  */
127 char * __cdecl NTDLL_strchr( const char *str, int c )
128 {
129     return strchr( str, c );
130 }
131
132
133 /*********************************************************************
134  *                  strcmp   (NTDLL.@)
135  */
136 int __cdecl NTDLL_strcmp( const char *str1, const char *str2 )
137 {
138     return strcmp( str1, str2 );
139 }
140
141
142 /*********************************************************************
143  *                  strcpy   (NTDLL.@)
144  */
145 char * __cdecl NTDLL_strcpy( char *dst, const char *src )
146 {
147     return strcpy( dst, src );
148 }
149
150
151 /*********************************************************************
152  *                  strcspn   (NTDLL.@)
153  */
154 size_t __cdecl NTDLL_strcspn( const char *str, const char *reject )
155 {
156     return strcspn( str, reject );
157 }
158
159
160 /*********************************************************************
161  *                  strlen   (NTDLL.@)
162  */
163 size_t __cdecl NTDLL_strlen( const char *str )
164 {
165     return strlen( str );
166 }
167
168
169 /*********************************************************************
170  *                  strncat   (NTDLL.@)
171  */
172 char * __cdecl NTDLL_strncat( char *dst, const char *src, size_t len )
173 {
174     return strncat( dst, src, len );
175 }
176
177
178 /*********************************************************************
179  *                  strncmp   (NTDLL.@)
180  */
181 int __cdecl NTDLL_strncmp( const char *str1, const char *str2, size_t len )
182 {
183     return strncmp( str1, str2, len );
184 }
185
186
187 /*********************************************************************
188  *                  strncpy   (NTDLL.@)
189  */
190 char * __cdecl NTDLL_strncpy( char *dst, const char *src, size_t len )
191 {
192     return strncpy( dst, src, len );
193 }
194
195
196 /*********************************************************************
197  *                  strpbrk   (NTDLL.@)
198  */
199 char * __cdecl NTDLL_strpbrk( const char *str, const char *accept )
200 {
201     return strpbrk( str, accept );
202 }
203
204
205 /*********************************************************************
206  *                  strrchr   (NTDLL.@)
207  */
208 char * __cdecl NTDLL_strrchr( const char *str, int c )
209 {
210     return strrchr( str, c );
211 }
212
213
214 /*********************************************************************
215  *                  strspn   (NTDLL.@)
216  */
217 size_t __cdecl NTDLL_strspn( const char *str, const char *accept )
218 {
219     return strspn( str, accept );
220 }
221
222
223 /*********************************************************************
224  *                  strstr   (NTDLL.@)
225  */
226 char * __cdecl NTDLL_strstr( const char *haystack, const char *needle )
227 {
228     return strstr( haystack, needle );
229 }
230
231
232 /*********************************************************************
233  *                  _memccpy   (NTDLL.@)
234  */
235 void * __cdecl _memccpy( void *dst, const void *src, int c, size_t n )
236 {
237     return memccpy( dst, src, c, n );
238 }
239
240
241 /*********************************************************************
242  *                  _memicmp   (NTDLL.@)
243  *
244  * Compare two blocks of memory as strings, ignoring case.
245  *
246  * PARAMS
247  *  s1  [I] First string to compare to s2
248  *  s2  [I] Second string to compare to s1
249  *  len [I] Number of bytes to compare
250  *
251  * RETURNS
252  *  An integer less than, equal to, or greater than zero indicating that
253  *  s1 is less than, equal to or greater than s2 respectively.
254  *
255  * NOTES
256  *  Any Nul characters in s1 or s2 are ignored. This function always
257  *  compares up to len bytes or the first place where s1 and s2 differ.
258  */
259 INT __cdecl _memicmp( LPCSTR s1, LPCSTR s2, DWORD len )
260 {
261     int ret = 0;
262     while (len--)
263     {
264         if ((ret = tolower(*s1) - tolower(*s2))) break;
265         s1++;
266         s2++;
267     }
268     return ret;
269 }
270
271
272 /*********************************************************************
273  *                  _stricmp   (NTDLL.@)
274  *                  _strcmpi   (NTDLL.@)
275  */
276 int __cdecl _stricmp( LPCSTR str1, LPCSTR str2 )
277 {
278     return strcasecmp( str1, str2 );
279 }
280
281
282 /*********************************************************************
283  *                  _strnicmp   (NTDLL.@)
284  */
285 int __cdecl _strnicmp( LPCSTR str1, LPCSTR str2, size_t n )
286 {
287     return strncasecmp( str1, str2, n );
288 }
289
290
291 /*********************************************************************
292  *                  _strupr   (NTDLL.@)
293  *
294  * Convert a string to upper case.
295  *
296  * PARAMS
297  *  str [I/O] String to convert
298  *
299  * RETURNS
300  *  str. There is no error return, if str is NULL or invalid, this
301  *  function will crash.
302  */
303 LPSTR __cdecl _strupr( LPSTR str )
304 {
305     LPSTR ret = str;
306     for ( ; *str; str++) *str = toupper(*str);
307     return ret;
308 }
309
310
311 /*********************************************************************
312  *                  _strlwr   (NTDLL.@)
313  *
314  * Convert a string to lowercase
315  *
316  * PARAMS
317  *  str [I/O] String to convert
318  *
319  * RETURNS
320  *  str. There is no error return, if str is NULL or invalid, this
321  *  function will crash.
322  */
323 LPSTR __cdecl _strlwr( LPSTR str )
324 {
325     LPSTR ret = str;
326     for ( ; *str; str++) *str = tolower(*str);
327     return ret;
328 }
329
330
331 /*********************************************************************
332  *                  tolower   (NTDLL.@)
333  */
334 int __cdecl NTDLL_tolower( int c )
335 {
336     return tolower( c );
337 }
338
339
340 /*********************************************************************
341  *                  toupper   (NTDLL.@)
342  */
343 int __cdecl NTDLL_toupper( int c )
344 {
345     return toupper( c );
346 }
347
348
349 /*********************************************************************
350  *                  isalnum   (NTDLL.@)
351  */
352 int __cdecl NTDLL_isalnum( int c )
353 {
354     return isalnum( c );
355 }
356
357
358 /*********************************************************************
359  *                  isalpha   (NTDLL.@)
360  */
361 int __cdecl NTDLL_isalpha( int c )
362 {
363     return isalpha( c );
364 }
365
366
367 /*********************************************************************
368  *                  iscntrl   (NTDLL.@)
369  */
370 int __cdecl NTDLL_iscntrl( int c )
371 {
372     return iscntrl( c );
373 }
374
375
376 /*********************************************************************
377  *                  isdigit   (NTDLL.@)
378  */
379 int __cdecl NTDLL_isdigit( int c )
380 {
381     return isdigit( c );
382 }
383
384
385 /*********************************************************************
386  *                  isgraph   (NTDLL.@)
387  */
388 int __cdecl NTDLL_isgraph( int c )
389 {
390     return isgraph( c );
391 }
392
393
394 /*********************************************************************
395  *                  islower   (NTDLL.@)
396  */
397 int __cdecl NTDLL_islower( int c )
398 {
399     return islower( c );
400 }
401
402
403 /*********************************************************************
404  *                  isprint   (NTDLL.@)
405  */
406 int __cdecl NTDLL_isprint( int c )
407 {
408     return isprint( c );
409 }
410
411
412 /*********************************************************************
413  *                  ispunct   (NTDLL.@)
414  */
415 int __cdecl NTDLL_ispunct( int c )
416 {
417     return ispunct( c );
418 }
419
420
421 /*********************************************************************
422  *                  isspace   (NTDLL.@)
423  */
424 int __cdecl NTDLL_isspace( int c )
425 {
426     return isspace( c );
427 }
428
429
430 /*********************************************************************
431  *                  isupper   (NTDLL.@)
432  */
433 int __cdecl NTDLL_isupper( int c )
434 {
435     return isupper( c );
436 }
437
438
439 /*********************************************************************
440  *                  isxdigit   (NTDLL.@)
441  */
442 int __cdecl NTDLL_isxdigit( int c )
443 {
444     return isxdigit( c );
445 }
446
447
448 /*********************************************************************
449  *                  strtol   (NTDLL.@)
450  */
451 long __cdecl NTDLL_strtol( const char *nptr, char **endptr, int base )
452 {
453     return strtol( nptr, endptr, base );
454 }
455
456
457 /*********************************************************************
458  *                  strtoul   (NTDLL.@)
459  */
460 unsigned long __cdecl NTDLL_strtoul( const char *nptr, char **endptr, int base )
461 {
462     return strtoul( nptr, endptr, base );
463 }
464
465
466 /*********************************************************************
467  *                  atoi   (NTDLL.@)
468  */
469 int __cdecl NTDLL_atoi( const char *nptr )
470 {
471     return atoi( nptr );
472 }
473
474
475 /*********************************************************************
476  *                  atol   (NTDLL.@)
477  */
478 long __cdecl NTDLL_atol( const char *nptr )
479 {
480     return atol( nptr );
481 }
482
483
484 /*********************************************************************
485  *      _ultoa   (NTDLL.@)
486  *
487  * Convert an unsigned long integer to a string.
488  *
489  * RETURNS
490  *  str.
491  *
492  * NOTES
493  *  - Converts value to a Nul terminated string which is copied to str.
494  *  - The maximum length of the copied str is 33 bytes.
495  *  - Does not check if radix is in the range of 2 to 36.
496  *  - If str is NULL it crashes, as the native function does.
497  */
498 char * __cdecl _ultoa(
499     unsigned long value, /* [I] Value to be converted */
500     char *str,           /* [O] Destination for the converted value */
501     int radix)           /* [I] Number base for conversion */
502 {
503     char buffer[33];
504     char *pos;
505     int digit;
506
507     pos = &buffer[32];
508     *pos = '\0';
509
510     do {
511         digit = value % radix;
512         value = value / radix;
513         if (digit < 10) {
514             *--pos = '0' + digit;
515         } else {
516             *--pos = 'a' + digit - 10;
517         } /* if */
518     } while (value != 0L);
519
520     memcpy(str, pos, &buffer[32] - pos + 1);
521     return str;
522 }
523
524
525 /*********************************************************************
526  *      _ltoa   (NTDLL.@)
527  *
528  * Convert a long integer to a string.
529  *
530  * RETURNS
531  *  str.
532  *
533  * NOTES
534  *  - Converts value to a Nul terminated string which is copied to str.
535  *  - The maximum length of the copied str is 33 bytes. If radix
536  *  is 10 and value is negative, the value is converted with sign.
537  *  - Does not check if radix is in the range of 2 to 36.
538  *  - If str is NULL it crashes, as the native function does.
539  */
540 char * __cdecl _ltoa(
541     long value, /* [I] Value to be converted */
542     char *str,  /* [O] Destination for the converted value */
543     int radix)  /* [I] Number base for conversion */
544 {
545     unsigned long val;
546     int negative;
547     char buffer[33];
548     char *pos;
549     int digit;
550
551     if (value < 0 && radix == 10) {
552         negative = 1;
553         val = -value;
554     } else {
555         negative = 0;
556         val = value;
557     } /* if */
558
559     pos = &buffer[32];
560     *pos = '\0';
561
562     do {
563         digit = val % radix;
564         val = val / radix;
565         if (digit < 10) {
566             *--pos = '0' + digit;
567         } else {
568             *--pos = 'a' + digit - 10;
569         } /* if */
570     } while (val != 0L);
571
572     if (negative) {
573         *--pos = '-';
574     } /* if */
575
576     memcpy(str, pos, &buffer[32] - pos + 1);
577     return str;
578 }
579
580
581 /*********************************************************************
582  *      _itoa    (NTDLL.@)
583  *
584  * Converts an integer to a string.
585  *
586  * RETURNS
587  *  str.
588  *
589  * NOTES
590  *  - Converts value to a '\0' terminated string which is copied to str.
591  *  - The maximum length of the copied str is 33 bytes. If radix
592  *  is 10 and value is negative, the value is converted with sign.
593  *  - Does not check if radix is in the range of 2 to 36.
594  *  - If str is NULL it crashes, as the native function does.
595  */
596 char * __cdecl _itoa(
597     int value, /* [I] Value to be converted */
598     char *str, /* [O] Destination for the converted value */
599     int radix) /* [I] Number base for conversion */
600 {
601     return _ltoa(value, str, radix);
602 }
603
604
605 /*********************************************************************
606  *      _ui64toa   (NTDLL.@)
607  *
608  * Converts a large unsigned integer to a string.
609  *
610  * RETURNS
611  *  str.
612  *
613  * NOTES
614  *  - Converts value to a '\0' terminated string which is copied to str.
615  *  - The maximum length of the copied str is 65 bytes.
616  *  - Does not check if radix is in the range of 2 to 36.
617  *  - If str is NULL it crashes, as the native function does.
618  */
619 char * __cdecl _ui64toa(
620     ULONGLONG value, /* [I] Value to be converted */
621     char *str,       /* [O] Destination for the converted value */
622     int radix)       /* [I] Number base for conversion */
623 {
624     char buffer[65];
625     char *pos;
626     int digit;
627
628     pos = &buffer[64];
629     *pos = '\0';
630
631     do {
632         digit = value % radix;
633         value = value / radix;
634         if (digit < 10) {
635             *--pos = '0' + digit;
636         } else {
637             *--pos = 'a' + digit - 10;
638         } /* if */
639     } while (value != 0L);
640
641     memcpy(str, pos, &buffer[64] - pos + 1);
642     return str;
643 }
644
645
646 /*********************************************************************
647  *      _i64toa   (NTDLL.@)
648  *
649  * Converts a large integer to a string.
650  *
651  * RETURNS
652  *  str.
653  *
654  * NOTES
655  *  - Converts value to a Nul terminated string which is copied to str.
656  *  - The maximum length of the copied str is 65 bytes. If radix
657  *  is 10 and value is negative, the value is converted with sign.
658  *  - Does not check if radix is in the range of 2 to 36.
659  *  - If str is NULL it crashes, as the native function does.
660  *
661  * DIFFERENCES
662  * - The native DLL converts negative values (for base 10) wrong:
663  *|                     -1 is converted to -18446744073709551615
664  *|                     -2 is converted to -18446744073709551614
665  *|   -9223372036854775807 is converted to  -9223372036854775809
666  *|   -9223372036854775808 is converted to  -9223372036854775808
667  *   The native msvcrt _i64toa function and our ntdll _i64toa function
668  *   do not have this bug.
669  */
670 char * __cdecl _i64toa(
671     LONGLONG value, /* [I] Value to be converted */
672     char *str,      /* [O] Destination for the converted value */
673     int radix)      /* [I] Number base for conversion */
674 {
675     ULONGLONG val;
676     int negative;
677     char buffer[65];
678     char *pos;
679     int digit;
680
681     if (value < 0 && radix == 10) {
682         negative = 1;
683         val = -value;
684     } else {
685         negative = 0;
686         val = value;
687     } /* if */
688
689     pos = &buffer[64];
690     *pos = '\0';
691
692     do {
693         digit = val % radix;
694         val = val / radix;
695         if (digit < 10) {
696             *--pos = '0' + digit;
697         } else {
698             *--pos = 'a' + digit - 10;
699         } /* if */
700     } while (val != 0L);
701
702     if (negative) {
703         *--pos = '-';
704     } /* if */
705
706     memcpy(str, pos, &buffer[64] - pos + 1);
707     return str;
708 }
709
710
711 /*********************************************************************
712  *      _atoi64   (NTDLL.@)
713  *
714  * Convert a string to a large integer.
715  *
716  * PARAMS
717  *  str [I] String to be converted
718  *
719  * RETURNS
720  *  Success: The integer value represented by str.
721  *  Failure: 0. Note that this cannot be distinguished from a successful
722  *           return, if the string contains "0".
723  *
724  * NOTES
725  *  - Accepts: {whitespace} [+|-] {digits}
726  *  - No check is made for value overflow, only the lower 64 bits are assigned.
727  *  - If str is NULL it crashes, as the native function does.
728  */
729 LONGLONG __cdecl _atoi64( char *str )
730 {
731     ULONGLONG RunningTotal = 0;
732     char bMinus = 0;
733
734     while (*str == ' ' || (*str >= '\011' && *str <= '\015')) {
735         str++;
736     } /* while */
737
738     if (*str == '+') {
739         str++;
740     } else if (*str == '-') {
741         bMinus = 1;
742         str++;
743     } /* if */
744
745     while (*str >= '0' && *str <= '9') {
746         RunningTotal = RunningTotal * 10 + *str - '0';
747         str++;
748     } /* while */
749
750     return bMinus ? -RunningTotal : RunningTotal;
751 }
752
753
754 /*********************************************************************
755  *                  sprintf   (NTDLL.@)
756  */
757 int __cdecl NTDLL_sprintf( char *str, const char *format, ... )
758 {
759     int ret;
760     va_list valist;
761     va_start( valist, format );
762     ret = vsprintf( str, format, valist );
763     va_end( valist );
764     return ret;
765 }
766
767
768 /*********************************************************************
769  *                  vsprintf   (NTDLL.@)
770  */
771 int __cdecl NTDLL_vsprintf( char *str, const char *format, va_list args )
772 {
773     return vsprintf( str, format, args );
774 }
775
776
777 /*********************************************************************
778  *                  _snprintf   (NTDLL.@)
779  */
780 int __cdecl _snprintf( char *str, size_t len, const char *format, ... )
781 {
782     int ret;
783     va_list valist;
784     va_start( valist, format );
785     ret = vsnprintf( str, len, format, valist );
786     va_end( valist );
787     return ret;
788 }
789
790
791 /*********************************************************************
792  *                  _vsnprintf   (NTDLL.@)
793  */
794 int __cdecl _vsnprintf( char *str, size_t len, const char *format, va_list args )
795 {
796     return vsnprintf( str, len, format, args );
797 }
798
799
800 /*********************************************************************
801  *                  sscanf   (NTDLL.@)
802  */
803 int __cdecl NTDLL_sscanf( const char *str, const char *format, ... )
804 {
805     int ret;
806     va_list valist;
807     va_start( valist, format );
808     ret = vsscanf( str, format, valist );
809     va_end( valist );
810     return ret;
811 }
812
813
814 /*********************************************************************
815  *              _splitpath (NTDLL.@)
816  *
817  * Split a path into its component pieces.
818  *
819  * PARAMS
820  *  inpath [I] Path to split
821  *  drv    [O] Destination for drive component (e.g. "A:"). Must be at least 3 characters.
822  *  dir    [O] Destination for directory component. Should be at least MAX_PATH characters.
823  *  fname  [O] Destination for File name component. Should be at least MAX_PATH characters.
824  *  ext    [O] Destination for file extension component. Should be at least MAX_PATH characters.
825  *
826  * RETURNS
827  *  Nothing.
828  */
829 void __cdecl _splitpath(const char* inpath, char * drv, char * dir,
830                         char* fname, char * ext )
831 {
832     const char *p, *end;
833
834     if (inpath[0] && inpath[1] == ':')
835     {
836         if (drv)
837         {
838             drv[0] = inpath[0];
839             drv[1] = inpath[1];
840             drv[2] = 0;
841         }
842         inpath += 2;
843     }
844     else if (drv) drv[0] = 0;
845
846     /* look for end of directory part */
847     end = NULL;
848     for (p = inpath; *p; p++) if (*p == '/' || *p == '\\') end = p + 1;
849
850     if (end)  /* got a directory */
851     {
852         if (dir)
853         {
854             memcpy( dir, inpath, end - inpath );
855             dir[end - inpath] = 0;
856         }
857         inpath = end;
858     }
859     else if (dir) dir[0] = 0;
860
861     /* look for extension: what's after the last dot */
862     end = NULL;
863     for (p = inpath; *p; p++) if (*p == '.') end = p;
864
865     if (!end) end = p; /* there's no extension */
866
867     if (fname)
868     {
869         memcpy( fname, inpath, end - inpath );
870         fname[end - inpath] = 0;
871     }
872     if (ext) strcpy( ext, end );
873 }