msi/tests: Test for error control flag handling.
[wine.git] / dlls / msvcrt / string.c
blob85f09adc46194e0abc37bd8903bf54d0981d0e8e
1 /*
2 * MSVCRT string functions
4 * Copyright 1996,1998 Marcus Meissner
5 * Copyright 1996 Jukka Iivonen
6 * Copyright 1997,2000 Uwe Bonnes
7 * Copyright 2000 Jon Griffiths
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #define _ISOC99_SOURCE
25 #include "config.h"
26 #include "wine/port.h"
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <math.h>
31 #include <limits.h>
32 #include <errno.h>
33 #include "msvcrt.h"
34 #include "winnls.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
39 /*********************************************************************
40 * _mbsdup (MSVCRT.@)
41 * _strdup (MSVCRT.@)
43 char* CDECL MSVCRT__strdup(const char* str)
45 if(str)
47 char * ret = MSVCRT_malloc(strlen(str)+1);
48 if (ret) strcpy( ret, str );
49 return ret;
51 else return 0;
54 /*********************************************************************
55 * _strlwr_s_l (MSVCRT.@)
57 int CDECL MSVCRT__strlwr_s_l(char *str, MSVCRT_size_t len, MSVCRT__locale_t locale)
59 char *ptr = str;
61 if (!str || !len)
63 *MSVCRT__errno() = MSVCRT_EINVAL;
64 return MSVCRT_EINVAL;
67 while (len && *ptr)
69 len--;
70 ptr++;
73 if (!len)
75 str[0] = '\0';
76 *MSVCRT__errno() = MSVCRT_EINVAL;
77 return MSVCRT_EINVAL;
80 while (*str)
82 *str = MSVCRT__tolower_l((unsigned char)*str, locale);
83 str++;
86 return 0;
89 /*********************************************************************
90 * _strlwr_s (MSVCRT.@)
92 int CDECL MSVCRT__strlwr_s(char *str, MSVCRT_size_t len)
94 return MSVCRT__strlwr_s_l(str, len, NULL);
97 /*********************************************************************
98 * _strlwr_l (MSVCRT.@)
100 char* CDECL _strlwr_l(char *str, MSVCRT__locale_t locale)
102 MSVCRT__strlwr_s_l(str, -1, locale);
103 return str;
106 /*********************************************************************
107 * _strlwr (MSVCRT.@)
109 char* CDECL MSVCRT__strlwr(char *str)
111 MSVCRT__strlwr_s_l(str, -1, NULL);
112 return str;
115 /*********************************************************************
116 * _strupr_s_l (MSVCRT.@)
118 int CDECL MSVCRT__strupr_s_l(char *str, MSVCRT_size_t len, MSVCRT__locale_t locale)
120 char *ptr = str;
122 if (!str || !len)
124 *MSVCRT__errno() = MSVCRT_EINVAL;
125 return MSVCRT_EINVAL;
128 while (len && *ptr)
130 len--;
131 ptr++;
134 if (!len)
136 str[0] = '\0';
137 *MSVCRT__errno() = MSVCRT_EINVAL;
138 return MSVCRT_EINVAL;
141 while (*str)
143 *str = MSVCRT__toupper_l((unsigned char)*str, locale);
144 str++;
147 return 0;
150 /*********************************************************************
151 * _strupr_s (MSVCRT.@)
153 int CDECL MSVCRT__strupr_s(char *str, MSVCRT_size_t len)
155 return MSVCRT__strupr_s_l(str, len, NULL);
158 /*********************************************************************
159 * _strupr_l (MSVCRT.@)
161 char* CDECL MSVCRT__strupr_l(char *str, MSVCRT__locale_t locale)
163 MSVCRT__strupr_s_l(str, -1, locale);
164 return str;
167 /*********************************************************************
168 * _strupr (MSVCRT.@)
170 char* CDECL MSVCRT__strupr(char *str)
172 MSVCRT__strupr_s_l(str, -1, NULL);
173 return str;
176 /*********************************************************************
177 * _strnset_s (MSVCRT.@)
179 int CDECL MSVCRT__strnset_s(char *str, MSVCRT_size_t size, int c, MSVCRT_size_t count)
181 MSVCRT_size_t i;
183 if(!str && !size && !count) return 0;
184 if(!MSVCRT_CHECK_PMT(str != NULL)) return MSVCRT_EINVAL;
185 if(!MSVCRT_CHECK_PMT(size > 0)) return MSVCRT_EINVAL;
187 for(i=0; i<size-1 && i<count; i++) {
188 if(!str[i]) return 0;
189 str[i] = c;
191 for(; i<size; i++)
192 if(!str[i]) return 0;
194 str[0] = 0;
195 MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
196 *MSVCRT__errno() = MSVCRT_EINVAL;
197 return MSVCRT_EINVAL;
200 /*********************************************************************
201 * _strnset (MSVCRT.@)
203 char* CDECL MSVCRT__strnset(char* str, int value, MSVCRT_size_t len)
205 if (len > 0 && str)
206 while (*str && len--)
207 *str++ = value;
208 return str;
211 /*********************************************************************
212 * _strrev (MSVCRT.@)
214 char* CDECL MSVCRT__strrev(char* str)
216 char * p1;
217 char * p2;
219 if (str && *str)
220 for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2)
222 *p1 ^= *p2;
223 *p2 ^= *p1;
224 *p1 ^= *p2;
227 return str;
230 /*********************************************************************
231 * _strset (MSVCRT.@)
233 char* CDECL _strset(char* str, int value)
235 char *ptr = str;
236 while (*ptr)
237 *ptr++ = value;
239 return str;
242 /*********************************************************************
243 * strtok (MSVCRT.@)
245 char * CDECL MSVCRT_strtok( char *str, const char *delim )
247 thread_data_t *data = msvcrt_get_thread_data();
248 char *ret;
250 if (!str)
251 if (!(str = data->strtok_next)) return NULL;
253 while (*str && strchr( delim, *str )) str++;
254 if (!*str) return NULL;
255 ret = str++;
256 while (*str && !strchr( delim, *str )) str++;
257 if (*str) *str++ = 0;
258 data->strtok_next = str;
259 return ret;
262 /*********************************************************************
263 * strtok_s (MSVCRT.@)
265 char * CDECL MSVCRT_strtok_s(char *str, const char *delim, char **ctx)
267 if (!MSVCRT_CHECK_PMT(delim != NULL)) return NULL;
268 if (!MSVCRT_CHECK_PMT(ctx != NULL)) return NULL;
269 if (!MSVCRT_CHECK_PMT(str != NULL || *ctx != NULL)) return NULL;
271 if(!str)
272 str = *ctx;
274 while(*str && strchr(delim, *str))
275 str++;
276 if(!*str)
277 return NULL;
279 *ctx = str+1;
280 while(**ctx && !strchr(delim, **ctx))
281 (*ctx)++;
282 if(**ctx)
283 *(*ctx)++ = 0;
285 return str;
288 /*********************************************************************
289 * _swab (MSVCRT.@)
291 void CDECL MSVCRT__swab(char* src, char* dst, int len)
293 if (len > 1)
295 len = (unsigned)len >> 1;
297 while (len--) {
298 char s0 = src[0];
299 char s1 = src[1];
300 *dst++ = s1;
301 *dst++ = s0;
302 src = src + 2;
307 static double strtod_helper(const char *str, char **end, MSVCRT__locale_t locale, int *err)
309 MSVCRT_pthreadlocinfo locinfo;
310 unsigned __int64 d=0, hlp;
311 unsigned fpcontrol;
312 int exp=0, sign=1;
313 const char *p;
314 double ret;
315 long double lret=1, expcnt = 10;
316 BOOL found_digit = FALSE, negexp;
317 int base = 10;
319 if(err)
320 *err = 0;
321 else if(!MSVCRT_CHECK_PMT(str != NULL)) {
322 if (end)
323 *end = NULL;
324 return 0;
327 if(!locale)
328 locinfo = get_locinfo();
329 else
330 locinfo = locale->locinfo;
332 /* FIXME: use *_l functions */
333 p = str;
334 while(isspace(*p))
335 p++;
337 if(*p == '-') {
338 sign = -1;
339 p++;
340 } else if(*p == '+')
341 p++;
343 #if _MSVCR_VER >= 140
344 if(tolower(p[0]) == 'i' && tolower(p[1]) == 'n' && tolower(p[2]) == 'f') {
345 if(end)
346 *end = (char*) &p[3];
347 if(tolower(p[3]) == 'i' && tolower(p[4]) == 'n' && tolower(p[5]) == 'i' &&
348 tolower(p[6]) == 't' && tolower(p[7]) == 'y' && end)
349 *end = (char*) &p[8];
350 return sign*INFINITY;
352 if(tolower(p[0]) == 'n' &&
353 tolower(p[1]) == 'a' &&
354 tolower(p[2]) == 'n') {
355 if(end)
356 *end = (char*) &p[3];
357 return NAN;
360 if(p[0] == '0' && tolower(p[1]) == 'x') {
361 base = 16;
362 expcnt = 2;
363 p += 2;
365 #endif
367 while((*p>='0' && *p<='9') ||
368 (base == 16 && ((*p >= 'a' && *p <= 'f') || (*p >= 'A' && *p <= 'F')))) {
369 char c = *p++;
370 int val;
371 found_digit = TRUE;
372 if (c>='0' && c<='9')
373 val = c - '0';
374 else if (c >= 'a' && c <= 'f')
375 val = 10 + c - 'a';
376 else
377 val = 10 + c - 'A';
378 hlp = d*base+val;
379 if(d>MSVCRT_UI64_MAX/base || hlp<d) {
380 exp++;
381 break;
382 } else
383 d = hlp;
385 while((*p>='0' && *p<='9') ||
386 (base == 16 && ((*p >= 'a' && *p <= 'f') || (*p >= 'A' && *p <= 'F')))) {
387 exp++;
388 p++;
391 if(*p == *locinfo->lconv->decimal_point)
392 p++;
394 while((*p>='0' && *p<='9') ||
395 (base == 16 && ((*p >= 'a' && *p <= 'f') || (*p >= 'A' && *p <= 'F')))) {
396 char c = *p++;
397 int val;
398 found_digit = TRUE;
399 if (c>='0' && c<='9')
400 val = c - '0';
401 else if (c >= 'a' && c <= 'f')
402 val = 10 + c - 'a';
403 else
404 val = 10 + c - 'A';
405 hlp = d*base+val;
406 if(d>MSVCRT_UI64_MAX/base || hlp<d)
407 break;
408 d = hlp;
409 exp--;
411 while((*p>='0' && *p<='9') ||
412 (base == 16 && ((*p >= 'a' && *p <= 'f') || (*p >= 'A' && *p <= 'F'))))
413 p++;
415 if(!found_digit) {
416 if(end)
417 *end = (char*)str;
418 return 0.0;
421 if(base == 16)
422 exp *= 4;
424 if((base == 10 && (*p=='e' || *p=='E' || *p=='d' || *p=='D')) ||
425 (base == 16 && (*p=='p' || *p=='P'))) {
426 int e=0, s=1;
428 p++;
429 if(*p == '-') {
430 s = -1;
431 p++;
432 } else if(*p == '+')
433 p++;
435 if(*p>='0' && *p<='9') {
436 while(*p>='0' && *p<='9') {
437 if(e>INT_MAX/10 || (e=e*10+*p-'0')<0)
438 e = INT_MAX;
439 p++;
441 e *= s;
443 if(exp<0 && e<0 && exp+e>=0) exp = INT_MIN;
444 else if(exp>0 && e>0 && exp+e<0) exp = INT_MAX;
445 else exp += e;
446 } else {
447 if(*p=='-' || *p=='+')
448 p--;
449 p--;
453 fpcontrol = _control87(0, 0);
454 _control87(MSVCRT__EM_DENORMAL|MSVCRT__EM_INVALID|MSVCRT__EM_ZERODIVIDE
455 |MSVCRT__EM_OVERFLOW|MSVCRT__EM_UNDERFLOW|MSVCRT__EM_INEXACT, 0xffffffff);
457 negexp = (exp < 0);
458 if(negexp)
459 exp = -exp;
460 while(exp) {
461 if(exp & 1)
462 lret *= expcnt;
463 exp /= 2;
464 expcnt = expcnt*expcnt;
466 ret = (long double)sign * (negexp ? d/lret : d*lret);
468 _control87(fpcontrol, 0xffffffff);
470 if((d && ret==0.0) || isinf(ret)) {
471 if(err)
472 *err = MSVCRT_ERANGE;
473 else
474 *MSVCRT__errno() = MSVCRT_ERANGE;
477 if(end)
478 *end = (char*)p;
480 return ret;
483 /*********************************************************************
484 * strtod_l (MSVCRT.@)
486 double CDECL MSVCRT_strtod_l(const char *str, char **end, MSVCRT__locale_t locale)
488 return strtod_helper(str, end, locale, NULL);
491 /*********************************************************************
492 * strtod (MSVCRT.@)
494 double CDECL MSVCRT_strtod( const char *str, char **end )
496 return MSVCRT_strtod_l( str, end, NULL );
499 /*********************************************************************
500 * strtof_l (MSVCR120.@)
502 float CDECL MSVCRT__strtof_l( const char *str, char **end, MSVCRT__locale_t locale )
504 return MSVCRT_strtod_l(str, end, locale);
507 /*********************************************************************
508 * strtof (MSVCR120.@)
510 float CDECL MSVCRT_strtof( const char *str, char **end )
512 return MSVCRT__strtof_l(str, end, NULL);
515 /*********************************************************************
516 * atof (MSVCRT.@)
518 double CDECL MSVCRT_atof( const char *str )
520 return MSVCRT_strtod_l(str, NULL, NULL);
523 /*********************************************************************
524 * _atof_l (MSVCRT.@)
526 double CDECL MSVCRT__atof_l( const char *str, MSVCRT__locale_t locale)
528 return MSVCRT_strtod_l(str, NULL, locale);
531 /*********************************************************************
532 * _atoflt_l (MSVCRT.@)
534 int CDECL MSVCRT__atoflt_l( MSVCRT__CRT_FLOAT *value, char *str, MSVCRT__locale_t locale)
536 double d;
537 int err;
539 d = strtod_helper(str, NULL, locale, &err);
540 value->f = d;
541 if(isinf(value->f))
542 return MSVCRT__OVERFLOW;
543 if((d!=0 || err) && value->f>-MSVCRT_FLT_MIN && value->f<MSVCRT_FLT_MIN)
544 return MSVCRT__UNDERFLOW;
545 return 0;
548 /*********************************************************************
549 * _atoflt (MSVCR100.@)
551 int CDECL MSVCRT__atoflt(MSVCRT__CRT_FLOAT *value, char *str)
553 return MSVCRT__atoflt_l(value, str, NULL);
556 /*********************************************************************
557 * _atodbl_l (MSVCRT.@)
559 int CDECL MSVCRT__atodbl_l(MSVCRT__CRT_DOUBLE *value, char *str, MSVCRT__locale_t locale)
561 int err;
563 value->x = strtod_helper(str, NULL, locale, &err);
564 if(isinf(value->x))
565 return MSVCRT__OVERFLOW;
566 if((value->x!=0 || err) && value->x>-MSVCRT_DBL_MIN && value->x<MSVCRT_DBL_MIN)
567 return MSVCRT__UNDERFLOW;
568 return 0;
571 /*********************************************************************
572 * _atodbl (MSVCRT.@)
574 int CDECL MSVCRT__atodbl(MSVCRT__CRT_DOUBLE *value, char *str)
576 return MSVCRT__atodbl_l(value, str, NULL);
579 /*********************************************************************
580 * _strcoll_l (MSVCRT.@)
582 int CDECL MSVCRT_strcoll_l( const char* str1, const char* str2, MSVCRT__locale_t locale )
584 MSVCRT_pthreadlocinfo locinfo;
586 if(!locale)
587 locinfo = get_locinfo();
588 else
589 locinfo = locale->locinfo;
591 if(!locinfo->lc_handle[MSVCRT_LC_COLLATE])
592 return strcmp(str1, str2);
593 return CompareStringA(locinfo->lc_handle[MSVCRT_LC_COLLATE], 0, str1, -1, str2, -1)-CSTR_EQUAL;
596 /*********************************************************************
597 * strcoll (MSVCRT.@)
599 int CDECL MSVCRT_strcoll( const char* str1, const char* str2 )
601 return MSVCRT_strcoll_l(str1, str2, NULL);
604 /*********************************************************************
605 * _stricoll_l (MSVCRT.@)
607 int CDECL MSVCRT__stricoll_l( const char* str1, const char* str2, MSVCRT__locale_t locale )
609 MSVCRT_pthreadlocinfo locinfo;
611 if(!locale)
612 locinfo = get_locinfo();
613 else
614 locinfo = locale->locinfo;
616 if(!locinfo->lc_handle[MSVCRT_LC_COLLATE])
617 return strcasecmp(str1, str2);
618 return CompareStringA(locinfo->lc_handle[MSVCRT_LC_COLLATE], NORM_IGNORECASE,
619 str1, -1, str2, -1)-CSTR_EQUAL;
622 /*********************************************************************
623 * _stricoll (MSVCRT.@)
625 int CDECL MSVCRT__stricoll( const char* str1, const char* str2 )
627 return MSVCRT__stricoll_l(str1, str2, NULL);
630 /*********************************************************************
631 * _strncoll_l (MSVCRT.@)
633 int CDECL MSVCRT__strncoll_l( const char* str1, const char* str2, MSVCRT_size_t count, MSVCRT__locale_t locale )
635 MSVCRT_pthreadlocinfo locinfo;
637 if(!locale)
638 locinfo = get_locinfo();
639 else
640 locinfo = locale->locinfo;
642 if(!locinfo->lc_handle[MSVCRT_LC_COLLATE])
643 return strncmp(str1, str2, count);
644 return CompareStringA(locinfo->lc_handle[MSVCRT_LC_COLLATE], 0, str1, count, str2, count)-CSTR_EQUAL;
647 /*********************************************************************
648 * _strncoll (MSVCRT.@)
650 int CDECL MSVCRT__strncoll( const char* str1, const char* str2, MSVCRT_size_t count )
652 return MSVCRT__strncoll_l(str1, str2, count, NULL);
655 /*********************************************************************
656 * _strnicoll_l (MSVCRT.@)
658 int CDECL MSVCRT__strnicoll_l( const char* str1, const char* str2, MSVCRT_size_t count, MSVCRT__locale_t locale )
660 MSVCRT_pthreadlocinfo locinfo;
662 if(!locale)
663 locinfo = get_locinfo();
664 else
665 locinfo = locale->locinfo;
667 if(!locinfo->lc_handle[MSVCRT_LC_COLLATE])
668 return strncasecmp(str1, str2, count);
669 return CompareStringA(locinfo->lc_handle[MSVCRT_LC_COLLATE], NORM_IGNORECASE,
670 str1, count, str2, count)-CSTR_EQUAL;
673 /*********************************************************************
674 * _strnicoll (MSVCRT.@)
676 int CDECL MSVCRT__strnicoll( const char* str1, const char* str2, MSVCRT_size_t count )
678 return MSVCRT__strnicoll_l(str1, str2, count, NULL);
681 /*********************************************************************
682 * strncpy (MSVCRT.@)
684 char* __cdecl MSVCRT_strncpy(char *dst, const char *src, MSVCRT_size_t len)
686 MSVCRT_size_t i;
688 for(i=0; i<len; i++)
689 if((dst[i] = src[i]) == '\0') break;
691 while (i < len) dst[i++] = 0;
693 return dst;
696 /*********************************************************************
697 * strcpy_s (MSVCRT.@)
699 int CDECL MSVCRT_strcpy_s( char* dst, MSVCRT_size_t elem, const char* src )
701 MSVCRT_size_t i;
702 if(!elem) return MSVCRT_EINVAL;
703 if(!dst) return MSVCRT_EINVAL;
704 if(!src)
706 dst[0] = '\0';
707 return MSVCRT_EINVAL;
710 for(i = 0; i < elem; i++)
712 if((dst[i] = src[i]) == '\0') return 0;
714 dst[0] = '\0';
715 return MSVCRT_ERANGE;
718 /*********************************************************************
719 * strcat_s (MSVCRT.@)
721 int CDECL MSVCRT_strcat_s( char* dst, MSVCRT_size_t elem, const char* src )
723 MSVCRT_size_t i, j;
724 if(!dst) return MSVCRT_EINVAL;
725 if(elem == 0) return MSVCRT_EINVAL;
726 if(!src)
728 dst[0] = '\0';
729 return MSVCRT_EINVAL;
732 for(i = 0; i < elem; i++)
734 if(dst[i] == '\0')
736 for(j = 0; (j + i) < elem; j++)
738 if((dst[j + i] = src[j]) == '\0') return 0;
742 /* Set the first element to 0, not the first element after the skipped part */
743 dst[0] = '\0';
744 return MSVCRT_ERANGE;
747 /*********************************************************************
748 * strncat_s (MSVCRT.@)
750 int CDECL MSVCRT_strncat_s( char* dst, MSVCRT_size_t elem, const char* src, MSVCRT_size_t count )
752 MSVCRT_size_t i, j;
754 if (!MSVCRT_CHECK_PMT(dst != 0)) return MSVCRT_EINVAL;
755 if (!MSVCRT_CHECK_PMT(elem != 0)) return MSVCRT_EINVAL;
756 if (!MSVCRT_CHECK_PMT(src != 0))
758 dst[0] = '\0';
759 return MSVCRT_EINVAL;
762 for(i = 0; i < elem; i++)
764 if(dst[i] == '\0')
766 for(j = 0; (j + i) < elem; j++)
768 if(count == MSVCRT__TRUNCATE && j + i == elem - 1)
770 dst[j + i] = '\0';
771 return MSVCRT_STRUNCATE;
773 if(j == count || (dst[j + i] = src[j]) == '\0')
775 dst[j + i] = '\0';
776 return 0;
781 /* Set the first element to 0, not the first element after the skipped part */
782 dst[0] = '\0';
783 return MSVCRT_ERANGE;
786 /*********************************************************************
787 * strncat (MSVCRT.@)
789 char* __cdecl MSVCRT_strncat(char *dst, const char *src, MSVCRT_size_t len)
791 return strncat(dst, src, len);
794 /*********************************************************************
795 * _strxfrm_l (MSVCRT.@)
797 MSVCRT_size_t CDECL MSVCRT__strxfrm_l( char *dest, const char *src,
798 MSVCRT_size_t len, MSVCRT__locale_t locale )
800 MSVCRT_pthreadlocinfo locinfo;
801 int ret;
803 if(!MSVCRT_CHECK_PMT(src)) return INT_MAX;
804 if(!MSVCRT_CHECK_PMT(dest || !len)) return INT_MAX;
806 if(len > INT_MAX) {
807 FIXME("len > INT_MAX not supported\n");
808 len = INT_MAX;
811 if(!locale)
812 locinfo = get_locinfo();
813 else
814 locinfo = locale->locinfo;
816 if(!locinfo->lc_handle[MSVCRT_LC_COLLATE]) {
817 MSVCRT_strncpy(dest, src, len);
818 return strlen(src);
821 ret = LCMapStringA(locinfo->lc_handle[MSVCRT_LC_COLLATE],
822 LCMAP_SORTKEY, src, -1, NULL, 0);
823 if(!ret) {
824 if(len) dest[0] = 0;
825 *MSVCRT__errno() = MSVCRT_EILSEQ;
826 return INT_MAX;
828 if(!len) return ret-1;
830 if(ret > len) {
831 dest[0] = 0;
832 *MSVCRT__errno() = MSVCRT_ERANGE;
833 return ret-1;
836 return LCMapStringA(locinfo->lc_handle[MSVCRT_LC_COLLATE],
837 LCMAP_SORTKEY, src, -1, dest, len) - 1;
840 /*********************************************************************
841 * strxfrm (MSVCRT.@)
843 MSVCRT_size_t CDECL MSVCRT_strxfrm( char *dest, const char *src, MSVCRT_size_t len )
845 return MSVCRT__strxfrm_l(dest, src, len, NULL);
848 /********************************************************************
849 * _atoldbl (MSVCRT.@)
851 int CDECL MSVCRT__atoldbl(MSVCRT__LDOUBLE *value, const char *str)
853 /* FIXME needs error checking for huge/small values */
854 #ifdef HAVE_STRTOLD
855 long double ld;
856 TRACE("str %s value %p\n",str,value);
857 ld = strtold(str,0);
858 memcpy(value, &ld, 10);
859 #else
860 FIXME("stub, str %s value %p\n",str,value);
861 #endif
862 return 0;
865 /********************************************************************
866 * __STRINGTOLD (MSVCRT.@)
868 int CDECL __STRINGTOLD( MSVCRT__LDOUBLE *value, char **endptr, const char *str, int flags )
870 #ifdef HAVE_STRTOLD
871 long double ld;
872 FIXME("%p %p %s %x partial stub\n", value, endptr, str, flags );
873 ld = strtold(str,0);
874 memcpy(value, &ld, 10);
875 #else
876 FIXME("%p %p %s %x stub\n", value, endptr, str, flags );
877 #endif
878 return 0;
881 /*********************************************************************
882 * strlen (MSVCRT.@)
884 MSVCRT_size_t __cdecl MSVCRT_strlen(const char *str)
886 return strlen(str);
889 /******************************************************************
890 * strnlen (MSVCRT.@)
892 MSVCRT_size_t CDECL MSVCRT_strnlen(const char *s, MSVCRT_size_t maxlen)
894 MSVCRT_size_t i;
896 for(i=0; i<maxlen; i++)
897 if(!s[i]) break;
899 return i;
902 /*********************************************************************
903 * _strtoi64_l (MSVCRT.@)
905 * FIXME: locale parameter is ignored
907 __int64 CDECL MSVCRT_strtoi64_l(const char *nptr, char **endptr, int base, MSVCRT__locale_t locale)
909 const char *p = nptr;
910 BOOL negative = FALSE;
911 BOOL got_digit = FALSE;
912 __int64 ret = 0;
914 TRACE("(%s %p %d %p)\n", debugstr_a(nptr), endptr, base, locale);
916 if (!MSVCRT_CHECK_PMT(nptr != NULL)) return 0;
917 if (!MSVCRT_CHECK_PMT(base == 0 || base >= 2)) return 0;
918 if (!MSVCRT_CHECK_PMT(base <= 36)) return 0;
920 while(isspace(*nptr)) nptr++;
922 if(*nptr == '-') {
923 negative = TRUE;
924 nptr++;
925 } else if(*nptr == '+')
926 nptr++;
928 if((base==0 || base==16) && *nptr=='0' && tolower(*(nptr+1))=='x') {
929 base = 16;
930 nptr += 2;
933 if(base == 0) {
934 if(*nptr=='0')
935 base = 8;
936 else
937 base = 10;
940 while(*nptr) {
941 char cur = tolower(*nptr);
942 int v;
944 if(cur>='0' && cur<='9') {
945 if(cur >= '0'+base)
946 break;
947 v = cur-'0';
948 } else {
949 if(cur<'a' || cur>='a'+base-10)
950 break;
951 v = cur-'a'+10;
953 got_digit = TRUE;
955 if(negative)
956 v = -v;
958 nptr++;
960 if(!negative && (ret>MSVCRT_I64_MAX/base || ret*base>MSVCRT_I64_MAX-v)) {
961 ret = MSVCRT_I64_MAX;
962 *MSVCRT__errno() = MSVCRT_ERANGE;
963 } else if(negative && (ret<MSVCRT_I64_MIN/base || ret*base<MSVCRT_I64_MIN-v)) {
964 ret = MSVCRT_I64_MIN;
965 *MSVCRT__errno() = MSVCRT_ERANGE;
966 } else
967 ret = ret*base + v;
970 if(endptr)
971 *endptr = (char*)(got_digit ? nptr : p);
973 return ret;
976 /*********************************************************************
977 * _strtoi64 (MSVCRT.@)
979 __int64 CDECL MSVCRT_strtoi64(const char *nptr, char **endptr, int base)
981 return MSVCRT_strtoi64_l(nptr, endptr, base, NULL);
984 /*********************************************************************
985 * _atoi_l (MSVCRT.@)
987 int __cdecl MSVCRT__atoi_l(const char *str, MSVCRT__locale_t locale)
989 __int64 ret = MSVCRT_strtoi64_l(str, NULL, 10, locale);
991 if(ret > INT_MAX) {
992 ret = INT_MAX;
993 *MSVCRT__errno() = MSVCRT_ERANGE;
994 } else if(ret < INT_MIN) {
995 ret = INT_MIN;
996 *MSVCRT__errno() = MSVCRT_ERANGE;
998 return ret;
1001 /*********************************************************************
1002 * atoi (MSVCRT.@)
1004 #if _MSVCR_VER == 0
1005 int __cdecl MSVCRT_atoi(const char *str)
1007 BOOL minus = FALSE;
1008 int ret = 0;
1010 if(!str)
1011 return 0;
1013 while(isspace(*str)) str++;
1015 if(*str == '+') {
1016 str++;
1017 }else if(*str == '-') {
1018 minus = TRUE;
1019 str++;
1022 while(*str>='0' && *str<='9') {
1023 ret = ret*10+*str-'0';
1024 str++;
1027 return minus ? -ret : ret;
1029 #else
1030 int CDECL MSVCRT_atoi(const char *str)
1032 return MSVCRT__atoi_l(str, NULL);
1034 #endif
1036 /******************************************************************
1037 * _atoll_l (MSVCR120.@)
1039 MSVCRT_longlong CDECL MSVCRT__atoll_l(const char* str, MSVCRT__locale_t locale)
1041 return MSVCRT_strtoi64_l(str, NULL, 10, locale);
1044 /******************************************************************
1045 * atoll (MSVCR120.@)
1047 MSVCRT_longlong CDECL MSVCRT_atoll(const char* str)
1049 return MSVCRT__atoll_l(str, NULL);
1052 /******************************************************************
1053 * _strtol_l (MSVCRT.@)
1055 MSVCRT_long CDECL MSVCRT__strtol_l(const char* nptr,
1056 char** end, int base, MSVCRT__locale_t locale)
1058 __int64 ret = MSVCRT_strtoi64_l(nptr, end, base, locale);
1060 if(ret > MSVCRT_LONG_MAX) {
1061 ret = MSVCRT_LONG_MAX;
1062 *MSVCRT__errno() = MSVCRT_ERANGE;
1063 } else if(ret < MSVCRT_LONG_MIN) {
1064 ret = MSVCRT_LONG_MIN;
1065 *MSVCRT__errno() = MSVCRT_ERANGE;
1068 return ret;
1071 /******************************************************************
1072 * strtol (MSVCRT.@)
1074 MSVCRT_long CDECL MSVCRT_strtol(const char* nptr, char** end, int base)
1076 return MSVCRT__strtol_l(nptr, end, base, NULL);
1079 /******************************************************************
1080 * _strtoul_l (MSVCRT.@)
1082 MSVCRT_ulong CDECL MSVCRT_strtoul_l(const char* nptr, char** end, int base, MSVCRT__locale_t locale)
1084 __int64 ret = MSVCRT_strtoi64_l(nptr, end, base, locale);
1086 if(ret > MSVCRT_ULONG_MAX) {
1087 ret = MSVCRT_ULONG_MAX;
1088 *MSVCRT__errno() = MSVCRT_ERANGE;
1089 }else if(ret < -(__int64)MSVCRT_ULONG_MAX) {
1090 ret = 1;
1091 *MSVCRT__errno() = MSVCRT_ERANGE;
1094 return ret;
1097 /******************************************************************
1098 * strtoul (MSVCRT.@)
1100 MSVCRT_ulong CDECL MSVCRT_strtoul(const char* nptr, char** end, int base)
1102 return MSVCRT_strtoul_l(nptr, end, base, NULL);
1105 /*********************************************************************
1106 * _strtoui64_l (MSVCRT.@)
1108 * FIXME: locale parameter is ignored
1110 unsigned __int64 CDECL MSVCRT_strtoui64_l(const char *nptr, char **endptr, int base, MSVCRT__locale_t locale)
1112 const char *p = nptr;
1113 BOOL negative = FALSE;
1114 BOOL got_digit = FALSE;
1115 unsigned __int64 ret = 0;
1117 TRACE("(%s %p %d %p)\n", debugstr_a(nptr), endptr, base, locale);
1119 if (!MSVCRT_CHECK_PMT(nptr != NULL)) return 0;
1120 if (!MSVCRT_CHECK_PMT(base == 0 || base >= 2)) return 0;
1121 if (!MSVCRT_CHECK_PMT(base <= 36)) return 0;
1123 while(isspace(*nptr)) nptr++;
1125 if(*nptr == '-') {
1126 negative = TRUE;
1127 nptr++;
1128 } else if(*nptr == '+')
1129 nptr++;
1131 if((base==0 || base==16) && *nptr=='0' && tolower(*(nptr+1))=='x') {
1132 base = 16;
1133 nptr += 2;
1136 if(base == 0) {
1137 if(*nptr=='0')
1138 base = 8;
1139 else
1140 base = 10;
1143 while(*nptr) {
1144 char cur = tolower(*nptr);
1145 int v;
1147 if(cur>='0' && cur<='9') {
1148 if(cur >= '0'+base)
1149 break;
1150 v = *nptr-'0';
1151 } else {
1152 if(cur<'a' || cur>='a'+base-10)
1153 break;
1154 v = cur-'a'+10;
1156 got_digit = TRUE;
1158 nptr++;
1160 if(ret>MSVCRT_UI64_MAX/base || ret*base>MSVCRT_UI64_MAX-v) {
1161 ret = MSVCRT_UI64_MAX;
1162 *MSVCRT__errno() = MSVCRT_ERANGE;
1163 } else
1164 ret = ret*base + v;
1167 if(endptr)
1168 *endptr = (char*)(got_digit ? nptr : p);
1170 return negative ? -ret : ret;
1173 /*********************************************************************
1174 * _strtoui64 (MSVCRT.@)
1176 unsigned __int64 CDECL MSVCRT_strtoui64(const char *nptr, char **endptr, int base)
1178 return MSVCRT_strtoui64_l(nptr, endptr, base, NULL);
1181 static int ltoa_helper(MSVCRT_long value, char *str, MSVCRT_size_t size, int radix)
1183 MSVCRT_ulong val;
1184 unsigned int digit;
1185 BOOL is_negative;
1186 char buffer[33], *pos;
1187 size_t len;
1189 if (value < 0 && radix == 10)
1191 is_negative = TRUE;
1192 val = -value;
1194 else
1196 is_negative = FALSE;
1197 val = value;
1200 pos = buffer + 32;
1201 *pos = '\0';
1205 digit = val % radix;
1206 val /= radix;
1208 if (digit < 10)
1209 *--pos = '0' + digit;
1210 else
1211 *--pos = 'a' + digit - 10;
1213 while (val != 0);
1215 if (is_negative)
1216 *--pos = '-';
1218 len = buffer + 33 - pos;
1219 if (len > size)
1221 size_t i;
1222 char *p = str;
1224 /* Copy the temporary buffer backwards up to the available number of
1225 * characters. Don't copy the negative sign if present. */
1227 if (is_negative)
1229 p++;
1230 size--;
1233 for (pos = buffer + 31, i = 0; i < size; i++)
1234 *p++ = *pos--;
1236 str[0] = '\0';
1237 MSVCRT_INVALID_PMT("str[size] is too small", MSVCRT_ERANGE);
1238 return MSVCRT_ERANGE;
1241 memcpy(str, pos, len);
1242 return 0;
1245 /*********************************************************************
1246 * _ltoa_s (MSVCRT.@)
1248 int CDECL MSVCRT__ltoa_s(MSVCRT_long value, char *str, MSVCRT_size_t size, int radix)
1250 if (!MSVCRT_CHECK_PMT(str != NULL)) return MSVCRT_EINVAL;
1251 if (!MSVCRT_CHECK_PMT(size > 0)) return MSVCRT_EINVAL;
1252 if (!MSVCRT_CHECK_PMT(radix >= 2 && radix <= 36))
1254 str[0] = '\0';
1255 return MSVCRT_EINVAL;
1258 return ltoa_helper(value, str, size, radix);
1261 /*********************************************************************
1262 * _ltow_s (MSVCRT.@)
1264 int CDECL MSVCRT__ltow_s(MSVCRT_long value, MSVCRT_wchar_t *str, MSVCRT_size_t size, int radix)
1266 MSVCRT_ulong val;
1267 unsigned int digit;
1268 BOOL is_negative;
1269 MSVCRT_wchar_t buffer[33], *pos;
1270 size_t len;
1272 if (!MSVCRT_CHECK_PMT(str != NULL)) return MSVCRT_EINVAL;
1273 if (!MSVCRT_CHECK_PMT(size > 0)) return MSVCRT_EINVAL;
1274 if (!MSVCRT_CHECK_PMT(radix >= 2 && radix <= 36))
1276 str[0] = '\0';
1277 return MSVCRT_EINVAL;
1280 if (value < 0 && radix == 10)
1282 is_negative = TRUE;
1283 val = -value;
1285 else
1287 is_negative = FALSE;
1288 val = value;
1291 pos = buffer + 32;
1292 *pos = '\0';
1296 digit = val % radix;
1297 val /= radix;
1299 if (digit < 10)
1300 *--pos = '0' + digit;
1301 else
1302 *--pos = 'a' + digit - 10;
1304 while (val != 0);
1306 if (is_negative)
1307 *--pos = '-';
1309 len = buffer + 33 - pos;
1310 if (len > size)
1312 size_t i;
1313 MSVCRT_wchar_t *p = str;
1315 /* Copy the temporary buffer backwards up to the available number of
1316 * characters. Don't copy the negative sign if present. */
1318 if (is_negative)
1320 p++;
1321 size--;
1324 for (pos = buffer + 31, i = 0; i < size; i++)
1325 *p++ = *pos--;
1327 str[0] = '\0';
1328 MSVCRT_INVALID_PMT("str[size] is too small", MSVCRT_ERANGE);
1329 return MSVCRT_ERANGE;
1332 memcpy(str, pos, len * sizeof(MSVCRT_wchar_t));
1333 return 0;
1336 /*********************************************************************
1337 * _itoa_s (MSVCRT.@)
1339 int CDECL MSVCRT__itoa_s(int value, char *str, MSVCRT_size_t size, int radix)
1341 return MSVCRT__ltoa_s(value, str, size, radix);
1344 /*********************************************************************
1345 * _itoa (MSVCRT.@)
1347 char* CDECL MSVCRT__itoa(int value, char *str, int radix)
1349 return ltoa_helper(value, str, MSVCRT_SIZE_MAX, radix) ? NULL : str;
1352 /*********************************************************************
1353 * _itow_s (MSVCRT.@)
1355 int CDECL MSVCRT__itow_s(int value, MSVCRT_wchar_t *str, MSVCRT_size_t size, int radix)
1357 return MSVCRT__ltow_s(value, str, size, radix);
1360 /*********************************************************************
1361 * _ui64toa_s (MSVCRT.@)
1363 int CDECL MSVCRT__ui64toa_s(unsigned __int64 value, char *str,
1364 MSVCRT_size_t size, int radix)
1366 char buffer[65], *pos;
1367 int digit;
1369 if (!MSVCRT_CHECK_PMT(str != NULL)) return MSVCRT_EINVAL;
1370 if (!MSVCRT_CHECK_PMT(size > 0)) return MSVCRT_EINVAL;
1371 if (!MSVCRT_CHECK_PMT(radix >= 2 && radix <= 36))
1373 str[0] = '\0';
1374 return MSVCRT_EINVAL;
1377 pos = buffer+64;
1378 *pos = '\0';
1380 do {
1381 digit = value%radix;
1382 value /= radix;
1384 if(digit < 10)
1385 *--pos = '0'+digit;
1386 else
1387 *--pos = 'a'+digit-10;
1388 }while(value != 0);
1390 if(buffer-pos+65 > size) {
1391 MSVCRT_INVALID_PMT("str[size] is too small", MSVCRT_EINVAL);
1392 return MSVCRT_EINVAL;
1395 memcpy(str, pos, buffer-pos+65);
1396 return 0;
1399 /*********************************************************************
1400 * _ui64tow_s (MSVCRT.@)
1402 int CDECL MSVCRT__ui64tow_s( unsigned __int64 value, MSVCRT_wchar_t *str,
1403 MSVCRT_size_t size, int radix )
1405 MSVCRT_wchar_t buffer[65], *pos;
1406 int digit;
1408 if (!MSVCRT_CHECK_PMT(str != NULL)) return MSVCRT_EINVAL;
1409 if (!MSVCRT_CHECK_PMT(size > 0)) return MSVCRT_EINVAL;
1410 if (!MSVCRT_CHECK_PMT(radix >= 2 && radix <= 36))
1412 str[0] = '\0';
1413 return MSVCRT_EINVAL;
1416 pos = &buffer[64];
1417 *pos = '\0';
1419 do {
1420 digit = value % radix;
1421 value = value / radix;
1422 if (digit < 10)
1423 *--pos = '0' + digit;
1424 else
1425 *--pos = 'a' + digit - 10;
1426 } while (value != 0);
1428 if(buffer-pos+65 > size) {
1429 MSVCRT_INVALID_PMT("str[size] is too small", MSVCRT_EINVAL);
1430 return MSVCRT_EINVAL;
1433 memcpy(str, pos, (buffer-pos+65)*sizeof(MSVCRT_wchar_t));
1434 return 0;
1437 /*********************************************************************
1438 * _ultoa_s (MSVCRT.@)
1440 int CDECL MSVCRT__ultoa_s(MSVCRT_ulong value, char *str, MSVCRT_size_t size, int radix)
1442 MSVCRT_ulong digit;
1443 char buffer[33], *pos;
1444 size_t len;
1446 if (!str || !size || radix < 2 || radix > 36)
1448 if (str && size)
1449 str[0] = '\0';
1451 *MSVCRT__errno() = MSVCRT_EINVAL;
1452 return MSVCRT_EINVAL;
1455 pos = buffer + 32;
1456 *pos = '\0';
1460 digit = value % radix;
1461 value /= radix;
1463 if (digit < 10)
1464 *--pos = '0' + digit;
1465 else
1466 *--pos = 'a' + digit - 10;
1468 while (value != 0);
1470 len = buffer + 33 - pos;
1471 if (len > size)
1473 size_t i;
1474 char *p = str;
1476 /* Copy the temporary buffer backwards up to the available number of
1477 * characters. */
1479 for (pos = buffer + 31, i = 0; i < size; i++)
1480 *p++ = *pos--;
1482 str[0] = '\0';
1483 *MSVCRT__errno() = MSVCRT_ERANGE;
1484 return MSVCRT_ERANGE;
1487 memcpy(str, pos, len);
1488 return 0;
1491 /*********************************************************************
1492 * _ultow_s (MSVCRT.@)
1494 int CDECL MSVCRT__ultow_s(MSVCRT_ulong value, MSVCRT_wchar_t *str, MSVCRT_size_t size, int radix)
1496 MSVCRT_ulong digit;
1497 WCHAR buffer[33], *pos;
1498 size_t len;
1500 if (!str || !size || radix < 2 || radix > 36)
1502 if (str && size)
1503 str[0] = '\0';
1505 *MSVCRT__errno() = MSVCRT_EINVAL;
1506 return MSVCRT_EINVAL;
1509 pos = buffer + 32;
1510 *pos = '\0';
1514 digit = value % radix;
1515 value /= radix;
1517 if (digit < 10)
1518 *--pos = '0' + digit;
1519 else
1520 *--pos = 'a' + digit - 10;
1522 while (value != 0);
1524 len = buffer + 33 - pos;
1525 if (len > size)
1527 size_t i;
1528 WCHAR *p = str;
1530 /* Copy the temporary buffer backwards up to the available number of
1531 * characters. */
1533 for (pos = buffer + 31, i = 0; i < size; i++)
1534 *p++ = *pos--;
1536 str[0] = '\0';
1537 *MSVCRT__errno() = MSVCRT_ERANGE;
1538 return MSVCRT_ERANGE;
1541 memcpy(str, pos, len * sizeof(MSVCRT_wchar_t));
1542 return 0;
1545 /*********************************************************************
1546 * _i64toa_s (MSVCRT.@)
1548 int CDECL MSVCRT__i64toa_s(__int64 value, char *str, MSVCRT_size_t size, int radix)
1550 unsigned __int64 val;
1551 unsigned int digit;
1552 BOOL is_negative;
1553 char buffer[65], *pos;
1554 size_t len;
1556 if (!MSVCRT_CHECK_PMT(str != NULL)) return MSVCRT_EINVAL;
1557 if (!MSVCRT_CHECK_PMT(size > 0)) return MSVCRT_EINVAL;
1558 if (!MSVCRT_CHECK_PMT(radix >= 2 && radix <= 36))
1560 str[0] = '\0';
1561 return MSVCRT_EINVAL;
1564 if (value < 0 && radix == 10)
1566 is_negative = TRUE;
1567 val = -value;
1569 else
1571 is_negative = FALSE;
1572 val = value;
1575 pos = buffer + 64;
1576 *pos = '\0';
1580 digit = val % radix;
1581 val /= radix;
1583 if (digit < 10)
1584 *--pos = '0' + digit;
1585 else
1586 *--pos = 'a' + digit - 10;
1588 while (val != 0);
1590 if (is_negative)
1591 *--pos = '-';
1593 len = buffer + 65 - pos;
1594 if (len > size)
1596 size_t i;
1597 char *p = str;
1599 /* Copy the temporary buffer backwards up to the available number of
1600 * characters. Don't copy the negative sign if present. */
1602 if (is_negative)
1604 p++;
1605 size--;
1608 for (pos = buffer + 63, i = 0; i < size; i++)
1609 *p++ = *pos--;
1611 str[0] = '\0';
1612 MSVCRT_INVALID_PMT("str[size] is too small", MSVCRT_ERANGE);
1613 return MSVCRT_ERANGE;
1616 memcpy(str, pos, len);
1617 return 0;
1620 /*********************************************************************
1621 * _i64tow_s (MSVCRT.@)
1623 int CDECL MSVCRT__i64tow_s(__int64 value, MSVCRT_wchar_t *str, MSVCRT_size_t size, int radix)
1625 unsigned __int64 val;
1626 unsigned int digit;
1627 BOOL is_negative;
1628 MSVCRT_wchar_t buffer[65], *pos;
1629 size_t len;
1631 if (!MSVCRT_CHECK_PMT(str != NULL)) return MSVCRT_EINVAL;
1632 if (!MSVCRT_CHECK_PMT(size > 0)) return MSVCRT_EINVAL;
1633 if (!MSVCRT_CHECK_PMT(radix >= 2 && radix <= 36))
1635 str[0] = '\0';
1636 return MSVCRT_EINVAL;
1639 if (value < 0 && radix == 10)
1641 is_negative = TRUE;
1642 val = -value;
1644 else
1646 is_negative = FALSE;
1647 val = value;
1650 pos = buffer + 64;
1651 *pos = '\0';
1655 digit = val % radix;
1656 val /= radix;
1658 if (digit < 10)
1659 *--pos = '0' + digit;
1660 else
1661 *--pos = 'a' + digit - 10;
1663 while (val != 0);
1665 if (is_negative)
1666 *--pos = '-';
1668 len = buffer + 65 - pos;
1669 if (len > size)
1671 size_t i;
1672 MSVCRT_wchar_t *p = str;
1674 /* Copy the temporary buffer backwards up to the available number of
1675 * characters. Don't copy the negative sign if present. */
1677 if (is_negative)
1679 p++;
1680 size--;
1683 for (pos = buffer + 63, i = 0; i < size; i++)
1684 *p++ = *pos--;
1686 str[0] = '\0';
1687 MSVCRT_INVALID_PMT("str[size] is too small", MSVCRT_ERANGE);
1688 return MSVCRT_ERANGE;
1691 memcpy(str, pos, len * sizeof(MSVCRT_wchar_t));
1692 return 0;
1695 #define I10_OUTPUT_MAX_PREC 21
1696 /* Internal structure used by $I10_OUTPUT */
1697 struct _I10_OUTPUT_DATA {
1698 short pos;
1699 char sign;
1700 BYTE len;
1701 char str[I10_OUTPUT_MAX_PREC+1]; /* add space for '\0' */
1704 /*********************************************************************
1705 * $I10_OUTPUT (MSVCRT.@)
1706 * ld80 - long double (Intel 80 bit FP in 12 bytes) to be printed to data
1707 * prec - precision of part, we're interested in
1708 * flag - 0 for first prec digits, 1 for fractional part
1709 * data - data to be populated
1711 * return value
1712 * 0 if given double is NaN or INF
1713 * 1 otherwise
1715 * FIXME
1716 * Native sets last byte of data->str to '0' or '9', I don't know what
1717 * it means. Current implementation sets it always to '0'.
1719 int CDECL MSVCRT_I10_OUTPUT(MSVCRT__LDOUBLE ld80, int prec, int flag, struct _I10_OUTPUT_DATA *data)
1721 static const char inf_str[] = "1#INF";
1722 static const char nan_str[] = "1#QNAN";
1724 /* MS' long double type wants 12 bytes for Intel's 80 bit FP format.
1725 * Some UNIX have sizeof(long double) == 16, yet only 80 bit are used.
1726 * Assume long double uses 80 bit FP, never seen 128 bit FP. */
1727 long double ld = 0;
1728 double d;
1729 char format[8];
1730 char buf[I10_OUTPUT_MAX_PREC+9]; /* 9 = strlen("0.e+0000") + '\0' */
1731 char *p;
1733 memcpy(&ld, &ld80, 10);
1734 d = ld;
1735 TRACE("(%lf %d %x %p)\n", d, prec, flag, data);
1737 if(d<0) {
1738 data->sign = '-';
1739 d = -d;
1740 } else
1741 data->sign = ' ';
1743 if(isinf(d)) {
1744 data->pos = 1;
1745 data->len = 5;
1746 memcpy(data->str, inf_str, sizeof(inf_str));
1748 return 0;
1751 if(isnan(d)) {
1752 data->pos = 1;
1753 data->len = 6;
1754 memcpy(data->str, nan_str, sizeof(nan_str));
1756 return 0;
1759 if(flag&1) {
1760 int exp = 1+floor(log10(d));
1762 prec += exp;
1763 if(exp < 0)
1764 prec--;
1766 prec--;
1768 if(prec+1 > I10_OUTPUT_MAX_PREC)
1769 prec = I10_OUTPUT_MAX_PREC-1;
1770 else if(prec < 0) {
1771 d = 0.0;
1772 prec = 0;
1775 sprintf(format, "%%.%dle", prec);
1776 sprintf(buf, format, d);
1778 buf[1] = buf[0];
1779 data->pos = atoi(buf+prec+3);
1780 if(buf[1] != '0')
1781 data->pos++;
1783 for(p = buf+prec+1; p>buf+1 && *p=='0'; p--);
1784 data->len = p-buf;
1786 memcpy(data->str, buf+1, data->len);
1787 data->str[data->len] = '\0';
1789 if(buf[1]!='0' && prec-data->len+1>0)
1790 memcpy(data->str+data->len+1, buf+data->len+1, prec-data->len+1);
1792 return 1;
1794 #undef I10_OUTPUT_MAX_PREC
1796 /*********************************************************************
1797 * memcmp (MSVCRT.@)
1799 int __cdecl MSVCRT_memcmp(const void *ptr1, const void *ptr2, MSVCRT_size_t n)
1801 return memcmp(ptr1, ptr2, n);
1804 /*********************************************************************
1805 * memcpy (MSVCRT.@)
1807 void * __cdecl MSVCRT_memcpy(void *dst, const void *src, MSVCRT_size_t n)
1809 return memmove(dst, src, n);
1812 /*********************************************************************
1813 * memmove (MSVCRT.@)
1815 void * __cdecl MSVCRT_memmove(void *dst, const void *src, MSVCRT_size_t n)
1817 return memmove(dst, src, n);
1820 /*********************************************************************
1821 * memset (MSVCRT.@)
1823 void* __cdecl MSVCRT_memset(void *dst, int c, MSVCRT_size_t n)
1825 return memset(dst, c, n);
1828 /*********************************************************************
1829 * strchr (MSVCRT.@)
1831 char* __cdecl MSVCRT_strchr(const char *str, int c)
1833 return strchr(str, c);
1836 /*********************************************************************
1837 * strrchr (MSVCRT.@)
1839 char* __cdecl MSVCRT_strrchr(const char *str, int c)
1841 return strrchr(str, c);
1844 /*********************************************************************
1845 * memchr (MSVCRT.@)
1847 void* __cdecl MSVCRT_memchr(const void *ptr, int c, MSVCRT_size_t n)
1849 return memchr(ptr, c, n);
1852 /*********************************************************************
1853 * strcmp (MSVCRT.@)
1855 int __cdecl MSVCRT_strcmp(const char *str1, const char *str2)
1857 return strcmp(str1, str2);
1860 /*********************************************************************
1861 * strncmp (MSVCRT.@)
1863 int __cdecl MSVCRT_strncmp(const char *str1, const char *str2, MSVCRT_size_t len)
1865 return strncmp(str1, str2, len);
1868 /*********************************************************************
1869 * _strnicmp_l (MSVCRT.@)
1871 int __cdecl MSVCRT__strnicmp_l(const char *s1, const char *s2,
1872 MSVCRT_size_t count, MSVCRT__locale_t locale)
1874 MSVCRT_pthreadlocinfo locinfo;
1875 int c1, c2;
1877 if(s1==NULL || s2==NULL)
1878 return MSVCRT__NLSCMPERROR;
1880 if(!count)
1881 return 0;
1883 if(!locale)
1884 locinfo = get_locinfo();
1885 else
1886 locinfo = locale->locinfo;
1888 if(!locinfo->lc_handle[MSVCRT_LC_CTYPE])
1889 return strncasecmp(s1, s2, count);
1891 do {
1892 c1 = MSVCRT__tolower_l(*s1++, locale);
1893 c2 = MSVCRT__tolower_l(*s2++, locale);
1894 }while(--count && c1 && c1==c2);
1896 return c1-c2;
1899 /*********************************************************************
1900 * _stricmp_l (MSVCRT.@)
1902 int __cdecl MSVCRT__stricmp_l(const char *s1, const char *s2, MSVCRT__locale_t locale)
1904 return MSVCRT__strnicmp_l(s1, s2, -1, locale);
1907 /*********************************************************************
1908 * _strnicmp (MSVCRT.@)
1910 int __cdecl MSVCRT__strnicmp(const char *s1, const char *s2, MSVCRT_size_t count)
1912 return MSVCRT__strnicmp_l(s1, s2, count, NULL);
1915 /*********************************************************************
1916 * _stricmp (MSVCRT.@)
1918 int __cdecl MSVCRT__stricmp(const char *s1, const char *s2)
1920 return MSVCRT__strnicmp_l(s1, s2, -1, NULL);
1923 /*********************************************************************
1924 * strstr (MSVCRT.@)
1926 char* __cdecl MSVCRT_strstr(const char *haystack, const char *needle)
1928 return strstr(haystack, needle);