hidclass.sys: Break the report descriptor into multiple lines.
[wine.git] / dlls / msvcrt / string.c
blobdde95aca3f78ff348c094ce709add4b0cd16fb46
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(isdigit(*p) ||
368 (base == 16 && ((*p >= 'a' && *p <= 'f') || (*p >= 'A' && *p <= 'F')))) {
369 char c = *p++;
370 int val;
371 found_digit = TRUE;
372 if (isdigit(c))
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(isdigit(*p) ||
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(isdigit(*p) ||
395 (base == 16 && ((*p >= 'a' && *p <= 'f') || (*p >= 'A' && *p <= 'F')))) {
396 char c = *p++;
397 int val;
398 found_digit = TRUE;
399 if (isdigit(c))
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(isdigit(*p) ||
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(isdigit(*p)) {
436 while(isdigit(*p)) {
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 * atof (MSVCRT.@)
502 double CDECL MSVCRT_atof( const char *str )
504 return MSVCRT_strtod_l(str, NULL, NULL);
507 /*********************************************************************
508 * _atof_l (MSVCRT.@)
510 double CDECL MSVCRT__atof_l( const char *str, MSVCRT__locale_t locale)
512 return MSVCRT_strtod_l(str, NULL, locale);
515 /*********************************************************************
516 * _atoflt_l (MSVCRT.@)
518 int CDECL MSVCRT__atoflt_l( MSVCRT__CRT_FLOAT *value, char *str, MSVCRT__locale_t locale)
520 double d;
521 int err;
523 d = strtod_helper(str, NULL, locale, &err);
524 value->f = d;
525 if(isinf(value->f))
526 return MSVCRT__OVERFLOW;
527 if((d!=0 || err) && value->f>-MSVCRT_FLT_MIN && value->f<MSVCRT_FLT_MIN)
528 return MSVCRT__UNDERFLOW;
529 return 0;
532 /*********************************************************************
533 * _atoflt (MSVCR100.@)
535 int CDECL MSVCRT__atoflt(MSVCRT__CRT_FLOAT *value, char *str)
537 return MSVCRT__atoflt_l(value, str, NULL);
540 /*********************************************************************
541 * _atodbl_l (MSVCRT.@)
543 int CDECL MSVCRT__atodbl_l(MSVCRT__CRT_DOUBLE *value, char *str, MSVCRT__locale_t locale)
545 int err;
547 value->x = strtod_helper(str, NULL, locale, &err);
548 if(isinf(value->x))
549 return MSVCRT__OVERFLOW;
550 if((value->x!=0 || err) && value->x>-MSVCRT_DBL_MIN && value->x<MSVCRT_DBL_MIN)
551 return MSVCRT__UNDERFLOW;
552 return 0;
555 /*********************************************************************
556 * _atodbl (MSVCRT.@)
558 int CDECL MSVCRT__atodbl(MSVCRT__CRT_DOUBLE *value, char *str)
560 return MSVCRT__atodbl_l(value, str, NULL);
563 /*********************************************************************
564 * _strcoll_l (MSVCRT.@)
566 int CDECL MSVCRT_strcoll_l( const char* str1, const char* str2, MSVCRT__locale_t locale )
568 MSVCRT_pthreadlocinfo locinfo;
570 if(!locale)
571 locinfo = get_locinfo();
572 else
573 locinfo = locale->locinfo;
575 if(!locinfo->lc_handle[MSVCRT_LC_COLLATE])
576 return strcmp(str1, str2);
577 return CompareStringA(locinfo->lc_handle[MSVCRT_LC_COLLATE], 0, str1, -1, str2, -1)-CSTR_EQUAL;
580 /*********************************************************************
581 * strcoll (MSVCRT.@)
583 int CDECL MSVCRT_strcoll( const char* str1, const char* str2 )
585 return MSVCRT_strcoll_l(str1, str2, NULL);
588 /*********************************************************************
589 * _stricoll_l (MSVCRT.@)
591 int CDECL MSVCRT__stricoll_l( const char* str1, const char* str2, MSVCRT__locale_t locale )
593 MSVCRT_pthreadlocinfo locinfo;
595 if(!locale)
596 locinfo = get_locinfo();
597 else
598 locinfo = locale->locinfo;
600 if(!locinfo->lc_handle[MSVCRT_LC_COLLATE])
601 return strcasecmp(str1, str2);
602 return CompareStringA(locinfo->lc_handle[MSVCRT_LC_COLLATE], NORM_IGNORECASE,
603 str1, -1, str2, -1)-CSTR_EQUAL;
606 /*********************************************************************
607 * _stricoll (MSVCRT.@)
609 int CDECL MSVCRT__stricoll( const char* str1, const char* str2 )
611 return MSVCRT__stricoll_l(str1, str2, NULL);
614 /*********************************************************************
615 * _strncoll_l (MSVCRT.@)
617 int CDECL MSVCRT__strncoll_l( const char* str1, const char* str2, MSVCRT_size_t count, MSVCRT__locale_t locale )
619 MSVCRT_pthreadlocinfo locinfo;
621 if(!locale)
622 locinfo = get_locinfo();
623 else
624 locinfo = locale->locinfo;
626 if(!locinfo->lc_handle[MSVCRT_LC_COLLATE])
627 return strncmp(str1, str2, count);
628 return CompareStringA(locinfo->lc_handle[MSVCRT_LC_COLLATE], 0, str1, count, str2, count)-CSTR_EQUAL;
631 /*********************************************************************
632 * _strncoll (MSVCRT.@)
634 int CDECL MSVCRT__strncoll( const char* str1, const char* str2, MSVCRT_size_t count )
636 return MSVCRT__strncoll_l(str1, str2, count, NULL);
639 /*********************************************************************
640 * _strnicoll_l (MSVCRT.@)
642 int CDECL MSVCRT__strnicoll_l( const char* str1, const char* str2, MSVCRT_size_t count, MSVCRT__locale_t locale )
644 MSVCRT_pthreadlocinfo locinfo;
646 if(!locale)
647 locinfo = get_locinfo();
648 else
649 locinfo = locale->locinfo;
651 if(!locinfo->lc_handle[MSVCRT_LC_COLLATE])
652 return strncasecmp(str1, str2, count);
653 return CompareStringA(locinfo->lc_handle[MSVCRT_LC_COLLATE], NORM_IGNORECASE,
654 str1, count, str2, count)-CSTR_EQUAL;
657 /*********************************************************************
658 * _strnicoll (MSVCRT.@)
660 int CDECL MSVCRT__strnicoll( const char* str1, const char* str2, MSVCRT_size_t count )
662 return MSVCRT__strnicoll_l(str1, str2, count, NULL);
665 /*********************************************************************
666 * strncpy (MSVCRT.@)
668 char* __cdecl MSVCRT_strncpy(char *dst, const char *src, MSVCRT_size_t len)
670 MSVCRT_size_t i;
672 for(i=0; i<len; i++)
673 if((dst[i] = src[i]) == '\0') break;
675 while (i < len) dst[i++] = 0;
677 return dst;
680 /*********************************************************************
681 * strcpy_s (MSVCRT.@)
683 int CDECL MSVCRT_strcpy_s( char* dst, MSVCRT_size_t elem, const char* src )
685 MSVCRT_size_t i;
686 if(!elem) return MSVCRT_EINVAL;
687 if(!dst) return MSVCRT_EINVAL;
688 if(!src)
690 dst[0] = '\0';
691 return MSVCRT_EINVAL;
694 for(i = 0; i < elem; i++)
696 if((dst[i] = src[i]) == '\0') return 0;
698 dst[0] = '\0';
699 return MSVCRT_ERANGE;
702 /*********************************************************************
703 * strcat_s (MSVCRT.@)
705 int CDECL MSVCRT_strcat_s( char* dst, MSVCRT_size_t elem, const char* src )
707 MSVCRT_size_t i, j;
708 if(!dst) return MSVCRT_EINVAL;
709 if(elem == 0) return MSVCRT_EINVAL;
710 if(!src)
712 dst[0] = '\0';
713 return MSVCRT_EINVAL;
716 for(i = 0; i < elem; i++)
718 if(dst[i] == '\0')
720 for(j = 0; (j + i) < elem; j++)
722 if((dst[j + i] = src[j]) == '\0') return 0;
726 /* Set the first element to 0, not the first element after the skipped part */
727 dst[0] = '\0';
728 return MSVCRT_ERANGE;
731 /*********************************************************************
732 * strncat_s (MSVCRT.@)
734 int CDECL MSVCRT_strncat_s( char* dst, MSVCRT_size_t elem, const char* src, MSVCRT_size_t count )
736 MSVCRT_size_t i, j;
738 if (!MSVCRT_CHECK_PMT(dst != 0)) return MSVCRT_EINVAL;
739 if (!MSVCRT_CHECK_PMT(elem != 0)) return MSVCRT_EINVAL;
740 if (!MSVCRT_CHECK_PMT(src != 0))
742 dst[0] = '\0';
743 return MSVCRT_EINVAL;
746 for(i = 0; i < elem; i++)
748 if(dst[i] == '\0')
750 for(j = 0; (j + i) < elem; j++)
752 if(count == MSVCRT__TRUNCATE && j + i == elem - 1)
754 dst[j + i] = '\0';
755 return MSVCRT_STRUNCATE;
757 if(j == count || (dst[j + i] = src[j]) == '\0')
759 dst[j + i] = '\0';
760 return 0;
765 /* Set the first element to 0, not the first element after the skipped part */
766 dst[0] = '\0';
767 return MSVCRT_ERANGE;
770 /*********************************************************************
771 * strncat (MSVCRT.@)
773 char* __cdecl MSVCRT_strncat(char *dst, const char *src, MSVCRT_size_t len)
775 return strncat(dst, src, len);
778 /*********************************************************************
779 * _strxfrm_l (MSVCRT.@)
781 MSVCRT_size_t CDECL MSVCRT__strxfrm_l( char *dest, const char *src,
782 MSVCRT_size_t len, MSVCRT__locale_t locale )
784 MSVCRT_pthreadlocinfo locinfo;
785 int ret;
787 if(!MSVCRT_CHECK_PMT(src)) return INT_MAX;
788 if(!MSVCRT_CHECK_PMT(dest || !len)) return INT_MAX;
790 if(len > INT_MAX) {
791 FIXME("len > INT_MAX not supported\n");
792 len = INT_MAX;
795 if(!locale)
796 locinfo = get_locinfo();
797 else
798 locinfo = locale->locinfo;
800 if(!locinfo->lc_handle[MSVCRT_LC_COLLATE]) {
801 MSVCRT_strncpy(dest, src, len);
802 return strlen(src);
805 ret = LCMapStringA(locinfo->lc_handle[MSVCRT_LC_COLLATE],
806 LCMAP_SORTKEY, src, -1, NULL, 0);
807 if(!ret) {
808 if(len) dest[0] = 0;
809 *MSVCRT__errno() = MSVCRT_EILSEQ;
810 return INT_MAX;
812 if(!len) return ret-1;
814 if(ret > len) {
815 dest[0] = 0;
816 *MSVCRT__errno() = MSVCRT_ERANGE;
817 return ret-1;
820 return LCMapStringA(locinfo->lc_handle[MSVCRT_LC_COLLATE],
821 LCMAP_SORTKEY, src, -1, dest, len) - 1;
824 /*********************************************************************
825 * strxfrm (MSVCRT.@)
827 MSVCRT_size_t CDECL MSVCRT_strxfrm( char *dest, const char *src, MSVCRT_size_t len )
829 return MSVCRT__strxfrm_l(dest, src, len, NULL);
832 /********************************************************************
833 * _atoldbl (MSVCRT.@)
835 int CDECL MSVCRT__atoldbl(MSVCRT__LDOUBLE *value, const char *str)
837 /* FIXME needs error checking for huge/small values */
838 #ifdef HAVE_STRTOLD
839 long double ld;
840 TRACE("str %s value %p\n",str,value);
841 ld = strtold(str,0);
842 memcpy(value, &ld, 10);
843 #else
844 FIXME("stub, str %s value %p\n",str,value);
845 #endif
846 return 0;
849 /********************************************************************
850 * __STRINGTOLD (MSVCRT.@)
852 int CDECL __STRINGTOLD( MSVCRT__LDOUBLE *value, char **endptr, const char *str, int flags )
854 #ifdef HAVE_STRTOLD
855 long double ld;
856 FIXME("%p %p %s %x partial stub\n", value, endptr, str, flags );
857 ld = strtold(str,0);
858 memcpy(value, &ld, 10);
859 #else
860 FIXME("%p %p %s %x stub\n", value, endptr, str, flags );
861 #endif
862 return 0;
865 /*********************************************************************
866 * strlen (MSVCRT.@)
868 MSVCRT_size_t __cdecl MSVCRT_strlen(const char *str)
870 return strlen(str);
873 /******************************************************************
874 * strnlen (MSVCRT.@)
876 MSVCRT_size_t CDECL MSVCRT_strnlen(const char *s, MSVCRT_size_t maxlen)
878 MSVCRT_size_t i;
880 for(i=0; i<maxlen; i++)
881 if(!s[i]) break;
883 return i;
886 /*********************************************************************
887 * _strtoi64_l (MSVCRT.@)
889 * FIXME: locale parameter is ignored
891 __int64 CDECL MSVCRT_strtoi64_l(const char *nptr, char **endptr, int base, MSVCRT__locale_t locale)
893 const char *p = nptr;
894 BOOL negative = FALSE;
895 BOOL got_digit = FALSE;
896 __int64 ret = 0;
898 TRACE("(%s %p %d %p)\n", debugstr_a(nptr), endptr, base, locale);
900 if (!MSVCRT_CHECK_PMT(nptr != NULL)) return 0;
901 if (!MSVCRT_CHECK_PMT(base == 0 || base >= 2)) return 0;
902 if (!MSVCRT_CHECK_PMT(base <= 36)) return 0;
904 while(isspace(*nptr)) nptr++;
906 if(*nptr == '-') {
907 negative = TRUE;
908 nptr++;
909 } else if(*nptr == '+')
910 nptr++;
912 if((base==0 || base==16) && *nptr=='0' && tolower(*(nptr+1))=='x') {
913 base = 16;
914 nptr += 2;
917 if(base == 0) {
918 if(*nptr=='0')
919 base = 8;
920 else
921 base = 10;
924 while(*nptr) {
925 char cur = tolower(*nptr);
926 int v;
928 if(isdigit(cur)) {
929 if(cur >= '0'+base)
930 break;
931 v = cur-'0';
932 } else {
933 if(cur<'a' || cur>='a'+base-10)
934 break;
935 v = cur-'a'+10;
937 got_digit = TRUE;
939 if(negative)
940 v = -v;
942 nptr++;
944 if(!negative && (ret>MSVCRT_I64_MAX/base || ret*base>MSVCRT_I64_MAX-v)) {
945 ret = MSVCRT_I64_MAX;
946 *MSVCRT__errno() = MSVCRT_ERANGE;
947 } else if(negative && (ret<MSVCRT_I64_MIN/base || ret*base<MSVCRT_I64_MIN-v)) {
948 ret = MSVCRT_I64_MIN;
949 *MSVCRT__errno() = MSVCRT_ERANGE;
950 } else
951 ret = ret*base + v;
954 if(endptr)
955 *endptr = (char*)(got_digit ? nptr : p);
957 return ret;
960 /*********************************************************************
961 * _strtoi64 (MSVCRT.@)
963 __int64 CDECL MSVCRT_strtoi64(const char *nptr, char **endptr, int base)
965 return MSVCRT_strtoi64_l(nptr, endptr, base, NULL);
968 /*********************************************************************
969 * _atoi_l (MSVCRT.@)
971 int __cdecl MSVCRT__atoi_l(const char *str, MSVCRT__locale_t locale)
973 __int64 ret = MSVCRT_strtoi64_l(str, NULL, 10, locale);
975 if(ret > INT_MAX) {
976 ret = INT_MAX;
977 *MSVCRT__errno() = MSVCRT_ERANGE;
978 } else if(ret < INT_MIN) {
979 ret = INT_MIN;
980 *MSVCRT__errno() = MSVCRT_ERANGE;
982 return ret;
985 /*********************************************************************
986 * atoi (MSVCRT.@)
988 #if _MSVCR_VER == 0
989 int __cdecl MSVCRT_atoi(const char *str)
991 BOOL minus = FALSE;
992 int ret = 0;
994 if(!str)
995 return 0;
997 while(isspace(*str)) str++;
999 if(*str == '+') {
1000 str++;
1001 }else if(*str == '-') {
1002 minus = TRUE;
1003 str++;
1006 while(*str>='0' && *str<='9') {
1007 ret = ret*10+*str-'0';
1008 str++;
1011 return minus ? -ret : ret;
1013 #else
1014 int CDECL MSVCRT_atoi(const char *str)
1016 return MSVCRT__atoi_l(str, NULL);
1018 #endif
1020 /******************************************************************
1021 * strtol (MSVCRT.@)
1023 MSVCRT_long CDECL MSVCRT_strtol(const char* nptr, char** end, int base)
1025 __int64 ret = MSVCRT_strtoi64_l(nptr, end, base, NULL);
1027 if(ret > MSVCRT_LONG_MAX) {
1028 ret = MSVCRT_LONG_MAX;
1029 *MSVCRT__errno() = MSVCRT_ERANGE;
1030 } else if(ret < MSVCRT_LONG_MIN) {
1031 ret = MSVCRT_LONG_MIN;
1032 *MSVCRT__errno() = MSVCRT_ERANGE;
1035 return ret;
1038 /******************************************************************
1039 * _strtoul_l (MSVCRT.@)
1041 MSVCRT_ulong CDECL MSVCRT_strtoul_l(const char* nptr, char** end, int base, MSVCRT__locale_t locale)
1043 __int64 ret = MSVCRT_strtoi64_l(nptr, end, base, locale);
1045 if(ret > MSVCRT_ULONG_MAX) {
1046 ret = MSVCRT_ULONG_MAX;
1047 *MSVCRT__errno() = MSVCRT_ERANGE;
1048 }else if(ret < -(__int64)MSVCRT_ULONG_MAX) {
1049 ret = 1;
1050 *MSVCRT__errno() = MSVCRT_ERANGE;
1053 return ret;
1056 /******************************************************************
1057 * strtoul (MSVCRT.@)
1059 MSVCRT_ulong CDECL MSVCRT_strtoul(const char* nptr, char** end, int base)
1061 return MSVCRT_strtoul_l(nptr, end, base, NULL);
1064 /*********************************************************************
1065 * _strtoui64_l (MSVCRT.@)
1067 * FIXME: locale parameter is ignored
1069 unsigned __int64 CDECL MSVCRT_strtoui64_l(const char *nptr, char **endptr, int base, MSVCRT__locale_t locale)
1071 const char *p = nptr;
1072 BOOL negative = FALSE;
1073 BOOL got_digit = FALSE;
1074 unsigned __int64 ret = 0;
1076 TRACE("(%s %p %d %p)\n", debugstr_a(nptr), endptr, base, locale);
1078 if (!MSVCRT_CHECK_PMT(nptr != NULL)) return 0;
1079 if (!MSVCRT_CHECK_PMT(base == 0 || base >= 2)) return 0;
1080 if (!MSVCRT_CHECK_PMT(base <= 36)) return 0;
1082 while(isspace(*nptr)) nptr++;
1084 if(*nptr == '-') {
1085 negative = TRUE;
1086 nptr++;
1087 } else if(*nptr == '+')
1088 nptr++;
1090 if((base==0 || base==16) && *nptr=='0' && tolower(*(nptr+1))=='x') {
1091 base = 16;
1092 nptr += 2;
1095 if(base == 0) {
1096 if(*nptr=='0')
1097 base = 8;
1098 else
1099 base = 10;
1102 while(*nptr) {
1103 char cur = tolower(*nptr);
1104 int v;
1106 if(isdigit(cur)) {
1107 if(cur >= '0'+base)
1108 break;
1109 v = *nptr-'0';
1110 } else {
1111 if(cur<'a' || cur>='a'+base-10)
1112 break;
1113 v = cur-'a'+10;
1115 got_digit = TRUE;
1117 nptr++;
1119 if(ret>MSVCRT_UI64_MAX/base || ret*base>MSVCRT_UI64_MAX-v) {
1120 ret = MSVCRT_UI64_MAX;
1121 *MSVCRT__errno() = MSVCRT_ERANGE;
1122 } else
1123 ret = ret*base + v;
1126 if(endptr)
1127 *endptr = (char*)(got_digit ? nptr : p);
1129 return negative ? -ret : ret;
1132 /*********************************************************************
1133 * _strtoui64 (MSVCRT.@)
1135 unsigned __int64 CDECL MSVCRT_strtoui64(const char *nptr, char **endptr, int base)
1137 return MSVCRT_strtoui64_l(nptr, endptr, base, NULL);
1140 static int ltoa_helper(MSVCRT_long value, char *str, MSVCRT_size_t size, int radix)
1142 MSVCRT_ulong val;
1143 unsigned int digit;
1144 BOOL is_negative;
1145 char buffer[33], *pos;
1146 size_t len;
1148 if (value < 0 && radix == 10)
1150 is_negative = TRUE;
1151 val = -value;
1153 else
1155 is_negative = FALSE;
1156 val = value;
1159 pos = buffer + 32;
1160 *pos = '\0';
1164 digit = val % radix;
1165 val /= radix;
1167 if (digit < 10)
1168 *--pos = '0' + digit;
1169 else
1170 *--pos = 'a' + digit - 10;
1172 while (val != 0);
1174 if (is_negative)
1175 *--pos = '-';
1177 len = buffer + 33 - pos;
1178 if (len > size)
1180 size_t i;
1181 char *p = str;
1183 /* Copy the temporary buffer backwards up to the available number of
1184 * characters. Don't copy the negative sign if present. */
1186 if (is_negative)
1188 p++;
1189 size--;
1192 for (pos = buffer + 31, i = 0; i < size; i++)
1193 *p++ = *pos--;
1195 str[0] = '\0';
1196 MSVCRT_INVALID_PMT("str[size] is too small", MSVCRT_ERANGE);
1197 return MSVCRT_ERANGE;
1200 memcpy(str, pos, len);
1201 return 0;
1204 /*********************************************************************
1205 * _ltoa_s (MSVCRT.@)
1207 int CDECL MSVCRT__ltoa_s(MSVCRT_long value, char *str, MSVCRT_size_t size, int radix)
1209 if (!MSVCRT_CHECK_PMT(str != NULL)) return MSVCRT_EINVAL;
1210 if (!MSVCRT_CHECK_PMT(size > 0)) return MSVCRT_EINVAL;
1211 if (!MSVCRT_CHECK_PMT(radix >= 2 && radix <= 36))
1213 str[0] = '\0';
1214 return MSVCRT_EINVAL;
1217 return ltoa_helper(value, str, size, radix);
1220 /*********************************************************************
1221 * _ltow_s (MSVCRT.@)
1223 int CDECL MSVCRT__ltow_s(MSVCRT_long value, MSVCRT_wchar_t *str, MSVCRT_size_t size, int radix)
1225 MSVCRT_ulong val;
1226 unsigned int digit;
1227 BOOL is_negative;
1228 MSVCRT_wchar_t buffer[33], *pos;
1229 size_t len;
1231 if (!MSVCRT_CHECK_PMT(str != NULL)) return MSVCRT_EINVAL;
1232 if (!MSVCRT_CHECK_PMT(size > 0)) return MSVCRT_EINVAL;
1233 if (!MSVCRT_CHECK_PMT(radix >= 2 && radix <= 36))
1235 str[0] = '\0';
1236 return MSVCRT_EINVAL;
1239 if (value < 0 && radix == 10)
1241 is_negative = TRUE;
1242 val = -value;
1244 else
1246 is_negative = FALSE;
1247 val = value;
1250 pos = buffer + 32;
1251 *pos = '\0';
1255 digit = val % radix;
1256 val /= radix;
1258 if (digit < 10)
1259 *--pos = '0' + digit;
1260 else
1261 *--pos = 'a' + digit - 10;
1263 while (val != 0);
1265 if (is_negative)
1266 *--pos = '-';
1268 len = buffer + 33 - pos;
1269 if (len > size)
1271 size_t i;
1272 MSVCRT_wchar_t *p = str;
1274 /* Copy the temporary buffer backwards up to the available number of
1275 * characters. Don't copy the negative sign if present. */
1277 if (is_negative)
1279 p++;
1280 size--;
1283 for (pos = buffer + 31, i = 0; i < size; i++)
1284 *p++ = *pos--;
1286 str[0] = '\0';
1287 MSVCRT_INVALID_PMT("str[size] is too small", MSVCRT_ERANGE);
1288 return MSVCRT_ERANGE;
1291 memcpy(str, pos, len * sizeof(MSVCRT_wchar_t));
1292 return 0;
1295 /*********************************************************************
1296 * _itoa_s (MSVCRT.@)
1298 int CDECL MSVCRT__itoa_s(int value, char *str, MSVCRT_size_t size, int radix)
1300 return MSVCRT__ltoa_s(value, str, size, radix);
1303 /*********************************************************************
1304 * _itoa (MSVCRT.@)
1306 char* CDECL MSVCRT__itoa(int value, char *str, int radix)
1308 return ltoa_helper(value, str, MSVCRT_SIZE_MAX, radix) ? NULL : str;
1311 /*********************************************************************
1312 * _itow_s (MSVCRT.@)
1314 int CDECL MSVCRT__itow_s(int value, MSVCRT_wchar_t *str, MSVCRT_size_t size, int radix)
1316 return MSVCRT__ltow_s(value, str, size, radix);
1319 /*********************************************************************
1320 * _ui64toa_s (MSVCRT.@)
1322 int CDECL MSVCRT__ui64toa_s(unsigned __int64 value, char *str,
1323 MSVCRT_size_t size, int radix)
1325 char buffer[65], *pos;
1326 int digit;
1328 if (!MSVCRT_CHECK_PMT(str != NULL)) return MSVCRT_EINVAL;
1329 if (!MSVCRT_CHECK_PMT(size > 0)) return MSVCRT_EINVAL;
1330 if (!MSVCRT_CHECK_PMT(radix >= 2 && radix <= 36))
1332 str[0] = '\0';
1333 return MSVCRT_EINVAL;
1336 pos = buffer+64;
1337 *pos = '\0';
1339 do {
1340 digit = value%radix;
1341 value /= radix;
1343 if(digit < 10)
1344 *--pos = '0'+digit;
1345 else
1346 *--pos = 'a'+digit-10;
1347 }while(value != 0);
1349 if(buffer-pos+65 > size) {
1350 MSVCRT_INVALID_PMT("str[size] is too small", MSVCRT_EINVAL);
1351 return MSVCRT_EINVAL;
1354 memcpy(str, pos, buffer-pos+65);
1355 return 0;
1358 /*********************************************************************
1359 * _ui64tow_s (MSVCRT.@)
1361 int CDECL MSVCRT__ui64tow_s( unsigned __int64 value, MSVCRT_wchar_t *str,
1362 MSVCRT_size_t size, int radix )
1364 MSVCRT_wchar_t buffer[65], *pos;
1365 int digit;
1367 if (!MSVCRT_CHECK_PMT(str != NULL)) return MSVCRT_EINVAL;
1368 if (!MSVCRT_CHECK_PMT(size > 0)) return MSVCRT_EINVAL;
1369 if (!MSVCRT_CHECK_PMT(radix >= 2 && radix <= 36))
1371 str[0] = '\0';
1372 return MSVCRT_EINVAL;
1375 pos = &buffer[64];
1376 *pos = '\0';
1378 do {
1379 digit = value % radix;
1380 value = value / radix;
1381 if (digit < 10)
1382 *--pos = '0' + digit;
1383 else
1384 *--pos = 'a' + digit - 10;
1385 } while (value != 0);
1387 if(buffer-pos+65 > size) {
1388 MSVCRT_INVALID_PMT("str[size] is too small", MSVCRT_EINVAL);
1389 return MSVCRT_EINVAL;
1392 memcpy(str, pos, (buffer-pos+65)*sizeof(MSVCRT_wchar_t));
1393 return 0;
1396 /*********************************************************************
1397 * _ultoa_s (MSVCRT.@)
1399 int CDECL MSVCRT__ultoa_s(MSVCRT_ulong value, char *str, MSVCRT_size_t size, int radix)
1401 MSVCRT_ulong digit;
1402 char buffer[33], *pos;
1403 size_t len;
1405 if (!str || !size || radix < 2 || radix > 36)
1407 if (str && size)
1408 str[0] = '\0';
1410 *MSVCRT__errno() = MSVCRT_EINVAL;
1411 return MSVCRT_EINVAL;
1414 pos = buffer + 32;
1415 *pos = '\0';
1419 digit = value % radix;
1420 value /= radix;
1422 if (digit < 10)
1423 *--pos = '0' + digit;
1424 else
1425 *--pos = 'a' + digit - 10;
1427 while (value != 0);
1429 len = buffer + 33 - pos;
1430 if (len > size)
1432 size_t i;
1433 char *p = str;
1435 /* Copy the temporary buffer backwards up to the available number of
1436 * characters. */
1438 for (pos = buffer + 31, i = 0; i < size; i++)
1439 *p++ = *pos--;
1441 str[0] = '\0';
1442 *MSVCRT__errno() = MSVCRT_ERANGE;
1443 return MSVCRT_ERANGE;
1446 memcpy(str, pos, len);
1447 return 0;
1450 /*********************************************************************
1451 * _ultow_s (MSVCRT.@)
1453 int CDECL MSVCRT__ultow_s(MSVCRT_ulong value, MSVCRT_wchar_t *str, MSVCRT_size_t size, int radix)
1455 MSVCRT_ulong digit;
1456 WCHAR buffer[33], *pos;
1457 size_t len;
1459 if (!str || !size || radix < 2 || radix > 36)
1461 if (str && size)
1462 str[0] = '\0';
1464 *MSVCRT__errno() = MSVCRT_EINVAL;
1465 return MSVCRT_EINVAL;
1468 pos = buffer + 32;
1469 *pos = '\0';
1473 digit = value % radix;
1474 value /= radix;
1476 if (digit < 10)
1477 *--pos = '0' + digit;
1478 else
1479 *--pos = 'a' + digit - 10;
1481 while (value != 0);
1483 len = buffer + 33 - pos;
1484 if (len > size)
1486 size_t i;
1487 WCHAR *p = str;
1489 /* Copy the temporary buffer backwards up to the available number of
1490 * characters. */
1492 for (pos = buffer + 31, i = 0; i < size; i++)
1493 *p++ = *pos--;
1495 str[0] = '\0';
1496 *MSVCRT__errno() = MSVCRT_ERANGE;
1497 return MSVCRT_ERANGE;
1500 memcpy(str, pos, len * sizeof(MSVCRT_wchar_t));
1501 return 0;
1504 /*********************************************************************
1505 * _i64toa_s (MSVCRT.@)
1507 int CDECL MSVCRT__i64toa_s(__int64 value, char *str, MSVCRT_size_t size, int radix)
1509 unsigned __int64 val;
1510 unsigned int digit;
1511 BOOL is_negative;
1512 char buffer[65], *pos;
1513 size_t len;
1515 if (!MSVCRT_CHECK_PMT(str != NULL)) return MSVCRT_EINVAL;
1516 if (!MSVCRT_CHECK_PMT(size > 0)) return MSVCRT_EINVAL;
1517 if (!MSVCRT_CHECK_PMT(radix >= 2 && radix <= 36))
1519 str[0] = '\0';
1520 return MSVCRT_EINVAL;
1523 if (value < 0 && radix == 10)
1525 is_negative = TRUE;
1526 val = -value;
1528 else
1530 is_negative = FALSE;
1531 val = value;
1534 pos = buffer + 64;
1535 *pos = '\0';
1539 digit = val % radix;
1540 val /= radix;
1542 if (digit < 10)
1543 *--pos = '0' + digit;
1544 else
1545 *--pos = 'a' + digit - 10;
1547 while (val != 0);
1549 if (is_negative)
1550 *--pos = '-';
1552 len = buffer + 65 - pos;
1553 if (len > size)
1555 size_t i;
1556 char *p = str;
1558 /* Copy the temporary buffer backwards up to the available number of
1559 * characters. Don't copy the negative sign if present. */
1561 if (is_negative)
1563 p++;
1564 size--;
1567 for (pos = buffer + 63, i = 0; i < size; i++)
1568 *p++ = *pos--;
1570 str[0] = '\0';
1571 MSVCRT_INVALID_PMT("str[size] is too small", MSVCRT_ERANGE);
1572 return MSVCRT_ERANGE;
1575 memcpy(str, pos, len);
1576 return 0;
1579 /*********************************************************************
1580 * _i64tow_s (MSVCRT.@)
1582 int CDECL MSVCRT__i64tow_s(__int64 value, MSVCRT_wchar_t *str, MSVCRT_size_t size, int radix)
1584 unsigned __int64 val;
1585 unsigned int digit;
1586 BOOL is_negative;
1587 MSVCRT_wchar_t buffer[65], *pos;
1588 size_t len;
1590 if (!MSVCRT_CHECK_PMT(str != NULL)) return MSVCRT_EINVAL;
1591 if (!MSVCRT_CHECK_PMT(size > 0)) return MSVCRT_EINVAL;
1592 if (!MSVCRT_CHECK_PMT(radix >= 2 && radix <= 36))
1594 str[0] = '\0';
1595 return MSVCRT_EINVAL;
1598 if (value < 0 && radix == 10)
1600 is_negative = TRUE;
1601 val = -value;
1603 else
1605 is_negative = FALSE;
1606 val = value;
1609 pos = buffer + 64;
1610 *pos = '\0';
1614 digit = val % radix;
1615 val /= radix;
1617 if (digit < 10)
1618 *--pos = '0' + digit;
1619 else
1620 *--pos = 'a' + digit - 10;
1622 while (val != 0);
1624 if (is_negative)
1625 *--pos = '-';
1627 len = buffer + 65 - pos;
1628 if (len > size)
1630 size_t i;
1631 MSVCRT_wchar_t *p = str;
1633 /* Copy the temporary buffer backwards up to the available number of
1634 * characters. Don't copy the negative sign if present. */
1636 if (is_negative)
1638 p++;
1639 size--;
1642 for (pos = buffer + 63, i = 0; i < size; i++)
1643 *p++ = *pos--;
1645 str[0] = '\0';
1646 MSVCRT_INVALID_PMT("str[size] is too small", MSVCRT_ERANGE);
1647 return MSVCRT_ERANGE;
1650 memcpy(str, pos, len * sizeof(MSVCRT_wchar_t));
1651 return 0;
1654 #define I10_OUTPUT_MAX_PREC 21
1655 /* Internal structure used by $I10_OUTPUT */
1656 struct _I10_OUTPUT_DATA {
1657 short pos;
1658 char sign;
1659 BYTE len;
1660 char str[I10_OUTPUT_MAX_PREC+1]; /* add space for '\0' */
1663 /*********************************************************************
1664 * $I10_OUTPUT (MSVCRT.@)
1665 * ld80 - long double (Intel 80 bit FP in 12 bytes) to be printed to data
1666 * prec - precision of part, we're interested in
1667 * flag - 0 for first prec digits, 1 for fractional part
1668 * data - data to be populated
1670 * return value
1671 * 0 if given double is NaN or INF
1672 * 1 otherwise
1674 * FIXME
1675 * Native sets last byte of data->str to '0' or '9', I don't know what
1676 * it means. Current implementation sets it always to '0'.
1678 int CDECL MSVCRT_I10_OUTPUT(MSVCRT__LDOUBLE ld80, int prec, int flag, struct _I10_OUTPUT_DATA *data)
1680 static const char inf_str[] = "1#INF";
1681 static const char nan_str[] = "1#QNAN";
1683 /* MS' long double type wants 12 bytes for Intel's 80 bit FP format.
1684 * Some UNIX have sizeof(long double) == 16, yet only 80 bit are used.
1685 * Assume long double uses 80 bit FP, never seen 128 bit FP. */
1686 long double ld = 0;
1687 double d;
1688 char format[8];
1689 char buf[I10_OUTPUT_MAX_PREC+9]; /* 9 = strlen("0.e+0000") + '\0' */
1690 char *p;
1692 memcpy(&ld, &ld80, 10);
1693 d = ld;
1694 TRACE("(%lf %d %x %p)\n", d, prec, flag, data);
1696 if(d<0) {
1697 data->sign = '-';
1698 d = -d;
1699 } else
1700 data->sign = ' ';
1702 if(isinf(d)) {
1703 data->pos = 1;
1704 data->len = 5;
1705 memcpy(data->str, inf_str, sizeof(inf_str));
1707 return 0;
1710 if(isnan(d)) {
1711 data->pos = 1;
1712 data->len = 6;
1713 memcpy(data->str, nan_str, sizeof(nan_str));
1715 return 0;
1718 if(flag&1) {
1719 int exp = 1+floor(log10(d));
1721 prec += exp;
1722 if(exp < 0)
1723 prec--;
1725 prec--;
1727 if(prec+1 > I10_OUTPUT_MAX_PREC)
1728 prec = I10_OUTPUT_MAX_PREC-1;
1729 else if(prec < 0) {
1730 d = 0.0;
1731 prec = 0;
1734 sprintf(format, "%%.%dle", prec);
1735 sprintf(buf, format, d);
1737 buf[1] = buf[0];
1738 data->pos = atoi(buf+prec+3);
1739 if(buf[1] != '0')
1740 data->pos++;
1742 for(p = buf+prec+1; p>buf+1 && *p=='0'; p--);
1743 data->len = p-buf;
1745 memcpy(data->str, buf+1, data->len);
1746 data->str[data->len] = '\0';
1748 if(buf[1]!='0' && prec-data->len+1>0)
1749 memcpy(data->str+data->len+1, buf+data->len+1, prec-data->len+1);
1751 return 1;
1753 #undef I10_OUTPUT_MAX_PREC
1755 /*********************************************************************
1756 * memcmp (MSVCRT.@)
1758 int __cdecl MSVCRT_memcmp(const void *ptr1, const void *ptr2, MSVCRT_size_t n)
1760 return memcmp(ptr1, ptr2, n);
1763 /*********************************************************************
1764 * memcpy (MSVCRT.@)
1766 void * __cdecl MSVCRT_memcpy(void *dst, const void *src, MSVCRT_size_t n)
1768 return memmove(dst, src, n);
1771 /*********************************************************************
1772 * memmove (MSVCRT.@)
1774 void * __cdecl MSVCRT_memmove(void *dst, const void *src, MSVCRT_size_t n)
1776 return memmove(dst, src, n);
1779 /*********************************************************************
1780 * memset (MSVCRT.@)
1782 void* __cdecl MSVCRT_memset(void *dst, int c, MSVCRT_size_t n)
1784 return memset(dst, c, n);
1787 /*********************************************************************
1788 * strchr (MSVCRT.@)
1790 char* __cdecl MSVCRT_strchr(const char *str, int c)
1792 return strchr(str, c);
1795 /*********************************************************************
1796 * strrchr (MSVCRT.@)
1798 char* __cdecl MSVCRT_strrchr(const char *str, int c)
1800 return strrchr(str, c);
1803 /*********************************************************************
1804 * memchr (MSVCRT.@)
1806 void* __cdecl MSVCRT_memchr(const void *ptr, int c, MSVCRT_size_t n)
1808 return memchr(ptr, c, n);
1811 /*********************************************************************
1812 * strcmp (MSVCRT.@)
1814 int __cdecl MSVCRT_strcmp(const char *str1, const char *str2)
1816 return strcmp(str1, str2);
1819 /*********************************************************************
1820 * strncmp (MSVCRT.@)
1822 int __cdecl MSVCRT_strncmp(const char *str1, const char *str2, MSVCRT_size_t len)
1824 return strncmp(str1, str2, len);
1827 /*********************************************************************
1828 * _strnicmp_l (MSVCRT.@)
1830 int __cdecl MSVCRT__strnicmp_l(const char *s1, const char *s2,
1831 MSVCRT_size_t count, MSVCRT__locale_t locale)
1833 MSVCRT_pthreadlocinfo locinfo;
1834 int c1, c2;
1836 if(s1==NULL || s2==NULL)
1837 return MSVCRT__NLSCMPERROR;
1839 if(!count)
1840 return 0;
1842 if(!locale)
1843 locinfo = get_locinfo();
1844 else
1845 locinfo = locale->locinfo;
1847 if(!locinfo->lc_handle[MSVCRT_LC_CTYPE])
1848 return strncasecmp(s1, s2, count);
1850 do {
1851 c1 = MSVCRT__tolower_l(*s1++, locale);
1852 c2 = MSVCRT__tolower_l(*s2++, locale);
1853 }while(--count && c1 && c1==c2);
1855 return c1-c2;
1858 /*********************************************************************
1859 * _stricmp_l (MSVCRT.@)
1861 int __cdecl MSVCRT__stricmp_l(const char *s1, const char *s2, MSVCRT__locale_t locale)
1863 return MSVCRT__strnicmp_l(s1, s2, -1, locale);
1866 /*********************************************************************
1867 * _strnicmp (MSVCRT.@)
1869 int __cdecl MSVCRT__strnicmp(const char *s1, const char *s2, MSVCRT_size_t count)
1871 return MSVCRT__strnicmp_l(s1, s2, count, NULL);
1874 /*********************************************************************
1875 * _stricmp (MSVCRT.@)
1877 int __cdecl MSVCRT__stricmp(const char *s1, const char *s2)
1879 return MSVCRT__strnicmp_l(s1, s2, -1, NULL);
1882 /*********************************************************************
1883 * strstr (MSVCRT.@)
1885 char* __cdecl MSVCRT_strstr(const char *haystack, const char *needle)
1887 return strstr(haystack, needle);