msvcrt: Remove MSVCRT_lconv type.
[wine.git] / dlls / msvcrt / string.c
blob3c394f0a3ca367ae622a9167d57cb16d6206bc44
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 #include <assert.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <math.h>
28 #include <limits.h>
29 #include <locale.h>
30 #include <errno.h>
31 #include "msvcrt.h"
32 #include "bnum.h"
33 #include "winnls.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
38 /*********************************************************************
39 * _mbsdup (MSVCRT.@)
40 * _strdup (MSVCRT.@)
42 char* CDECL MSVCRT__strdup(const char* str)
44 if(str)
46 char * ret = MSVCRT_malloc(strlen(str)+1);
47 if (ret) strcpy( ret, str );
48 return ret;
50 else return 0;
53 /*********************************************************************
54 * _strlwr_s_l (MSVCRT.@)
56 int CDECL MSVCRT__strlwr_s_l(char *str, MSVCRT_size_t len, MSVCRT__locale_t locale)
58 MSVCRT_pthreadlocinfo locinfo;
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 if(!locale)
81 locinfo = get_locinfo();
82 else
83 locinfo = locale->locinfo;
85 if(!locinfo->lc_handle[MSVCRT_LC_CTYPE])
87 while (*str)
89 if (*str >= 'A' && *str <= 'Z')
90 *str -= 'A' - 'a';
91 str++;
94 else
96 while (*str)
98 *str = MSVCRT__tolower_l((unsigned char)*str, locale);
99 str++;
103 return 0;
106 /*********************************************************************
107 * _strlwr_s (MSVCRT.@)
109 int CDECL MSVCRT__strlwr_s(char *str, MSVCRT_size_t len)
111 return MSVCRT__strlwr_s_l(str, len, NULL);
114 /*********************************************************************
115 * _strlwr_l (MSVCRT.@)
117 char* CDECL _strlwr_l(char *str, MSVCRT__locale_t locale)
119 MSVCRT__strlwr_s_l(str, -1, locale);
120 return str;
123 /*********************************************************************
124 * _strlwr (MSVCRT.@)
126 char* CDECL MSVCRT__strlwr(char *str)
128 MSVCRT__strlwr_s_l(str, -1, NULL);
129 return str;
132 /*********************************************************************
133 * _strupr_s_l (MSVCRT.@)
135 int CDECL MSVCRT__strupr_s_l(char *str, MSVCRT_size_t len, MSVCRT__locale_t locale)
137 MSVCRT_pthreadlocinfo locinfo;
138 char *ptr = str;
140 if (!str || !len)
142 *MSVCRT__errno() = MSVCRT_EINVAL;
143 return MSVCRT_EINVAL;
146 while (len && *ptr)
148 len--;
149 ptr++;
152 if (!len)
154 str[0] = '\0';
155 *MSVCRT__errno() = MSVCRT_EINVAL;
156 return MSVCRT_EINVAL;
159 if(!locale)
160 locinfo = get_locinfo();
161 else
162 locinfo = locale->locinfo;
164 if(!locinfo->lc_handle[MSVCRT_LC_CTYPE])
166 while (*str)
168 if (*str >= 'a' && *str <= 'z')
169 *str -= 'a' - 'A';
170 str++;
173 else
175 while (*str)
177 *str = MSVCRT__toupper_l((unsigned char)*str, locale);
178 str++;
182 return 0;
185 /*********************************************************************
186 * _strupr_s (MSVCRT.@)
188 int CDECL MSVCRT__strupr_s(char *str, MSVCRT_size_t len)
190 return MSVCRT__strupr_s_l(str, len, NULL);
193 /*********************************************************************
194 * _strupr_l (MSVCRT.@)
196 char* CDECL MSVCRT__strupr_l(char *str, MSVCRT__locale_t locale)
198 MSVCRT__strupr_s_l(str, -1, locale);
199 return str;
202 /*********************************************************************
203 * _strupr (MSVCRT.@)
205 char* CDECL MSVCRT__strupr(char *str)
207 MSVCRT__strupr_s_l(str, -1, NULL);
208 return str;
211 /*********************************************************************
212 * _strnset_s (MSVCRT.@)
214 int CDECL MSVCRT__strnset_s(char *str, MSVCRT_size_t size, int c, MSVCRT_size_t count)
216 MSVCRT_size_t i;
218 if(!str && !size && !count) return 0;
219 if(!MSVCRT_CHECK_PMT(str != NULL)) return MSVCRT_EINVAL;
220 if(!MSVCRT_CHECK_PMT(size > 0)) return MSVCRT_EINVAL;
222 for(i=0; i<size-1 && i<count; i++) {
223 if(!str[i]) return 0;
224 str[i] = c;
226 for(; i<size; i++)
227 if(!str[i]) return 0;
229 str[0] = 0;
230 MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
231 *MSVCRT__errno() = MSVCRT_EINVAL;
232 return MSVCRT_EINVAL;
235 /*********************************************************************
236 * _strnset (MSVCRT.@)
238 char* CDECL MSVCRT__strnset(char* str, int value, MSVCRT_size_t len)
240 if (len > 0 && str)
241 while (*str && len--)
242 *str++ = value;
243 return str;
246 /*********************************************************************
247 * _strrev (MSVCRT.@)
249 char* CDECL MSVCRT__strrev(char* str)
251 char * p1;
252 char * p2;
254 if (str && *str)
255 for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2)
257 *p1 ^= *p2;
258 *p2 ^= *p1;
259 *p1 ^= *p2;
262 return str;
265 /*********************************************************************
266 * _strset (MSVCRT.@)
268 char* CDECL _strset(char* str, int value)
270 char *ptr = str;
271 while (*ptr)
272 *ptr++ = value;
274 return str;
277 /*********************************************************************
278 * strtok (MSVCRT.@)
280 char * CDECL MSVCRT_strtok( char *str, const char *delim )
282 thread_data_t *data = msvcrt_get_thread_data();
283 char *ret;
285 if (!str)
286 if (!(str = data->strtok_next)) return NULL;
288 while (*str && strchr( delim, *str )) str++;
289 if (!*str) return NULL;
290 ret = str++;
291 while (*str && !strchr( delim, *str )) str++;
292 if (*str) *str++ = 0;
293 data->strtok_next = str;
294 return ret;
297 /*********************************************************************
298 * strtok_s (MSVCRT.@)
300 char * CDECL MSVCRT_strtok_s(char *str, const char *delim, char **ctx)
302 if (!MSVCRT_CHECK_PMT(delim != NULL)) return NULL;
303 if (!MSVCRT_CHECK_PMT(ctx != NULL)) return NULL;
304 if (!MSVCRT_CHECK_PMT(str != NULL || *ctx != NULL)) return NULL;
306 if(!str)
307 str = *ctx;
309 while(*str && strchr(delim, *str))
310 str++;
311 if(!*str)
313 *ctx = str;
314 return NULL;
317 *ctx = str+1;
318 while(**ctx && !strchr(delim, **ctx))
319 (*ctx)++;
320 if(**ctx)
321 *(*ctx)++ = 0;
323 return str;
326 /*********************************************************************
327 * _swab (MSVCRT.@)
329 void CDECL MSVCRT__swab(char* src, char* dst, int len)
331 if (len > 1)
333 len = (unsigned)len >> 1;
335 while (len--) {
336 char s0 = src[0];
337 char s1 = src[1];
338 *dst++ = s1;
339 *dst++ = s0;
340 src = src + 2;
345 static struct fpnum fpnum(int sign, int exp, ULONGLONG m, enum fpmod mod)
347 struct fpnum ret;
349 ret.sign = sign;
350 ret.exp = exp;
351 ret.m = m;
352 ret.mod = mod;
353 return ret;
356 int fpnum_double(struct fpnum *fp, double *d)
358 ULONGLONG bits = 0;
360 if (fp->mod == FP_VAL_INFINITY)
362 *d = fp->sign * INFINITY;
363 return 0;
366 if (fp->mod == FP_VAL_NAN)
368 bits = ~0;
369 if (fp->sign == 1)
370 bits &= ~((ULONGLONG)1 << (MANT_BITS + EXP_BITS - 1));
371 *d = *(double*)&bits;
372 return 0;
375 TRACE("%c %s *2^%d (round %d)\n", fp->sign == -1 ? '-' : '+',
376 wine_dbgstr_longlong(fp->m), fp->exp, fp->mod);
377 if (!fp->m)
379 *d = fp->sign * 0.0;
380 return 0;
383 /* make sure that we don't overflow modifying exponent */
384 if (fp->exp > 1<<EXP_BITS)
386 *d = fp->sign * INFINITY;
387 return MSVCRT_ERANGE;
389 if (fp->exp < -(1<<EXP_BITS))
391 *d = fp->sign * 0.0;
392 return MSVCRT_ERANGE;
394 fp->exp += MANT_BITS - 1;
396 /* normalize mantissa */
397 while(fp->m < (ULONGLONG)1 << (MANT_BITS-1))
399 fp->m <<= 1;
400 fp->exp--;
402 while(fp->m >= (ULONGLONG)1 << MANT_BITS)
404 if (fp->m & 1 || fp->mod != FP_ROUND_ZERO)
406 if (!(fp->m & 1)) fp->mod = FP_ROUND_DOWN;
407 else if(fp->mod == FP_ROUND_ZERO) fp->mod = FP_ROUND_EVEN;
408 else fp->mod = FP_ROUND_UP;
410 fp->m >>= 1;
411 fp->exp++;
413 fp->exp += (1 << (EXP_BITS-1)) - 1;
415 /* handle subnormals */
416 if (fp->exp <= 0)
418 if (fp->m & 1 && fp->mod == FP_ROUND_ZERO) fp->mod = FP_ROUND_EVEN;
419 else if (fp->m & 1) fp->mod = FP_ROUND_UP;
420 else if (fp->mod != FP_ROUND_ZERO) fp->mod = FP_ROUND_DOWN;
421 fp->m >>= 1;
423 while(fp->m && fp->exp<0)
425 if (fp->m & 1 && fp->mod == FP_ROUND_ZERO) fp->mod = FP_ROUND_EVEN;
426 else if (fp->m & 1) fp->mod = FP_ROUND_UP;
427 else if (fp->mod != FP_ROUND_ZERO) fp->mod = FP_ROUND_DOWN;
428 fp->m >>= 1;
429 fp->exp++;
432 /* round mantissa */
433 if (fp->mod == FP_ROUND_UP || (fp->mod == FP_ROUND_EVEN && fp->m & 1))
435 fp->m++;
437 /* handle subnormal that falls into regular range due to rounding */
438 if (fp->m == (ULONGLONG)1 << (MANT_BITS - 1))
440 fp->exp++;
442 else if (fp->m >= (ULONGLONG)1 << MANT_BITS)
444 fp->exp++;
445 fp->m >>= 1;
449 if (fp->exp >= (1<<EXP_BITS)-1)
451 *d = fp->sign * INFINITY;
452 return MSVCRT_ERANGE;
454 if (!fp->m || fp->exp < 0)
456 *d = fp->sign * 0.0;
457 return MSVCRT_ERANGE;
460 if (fp->sign == -1)
461 bits |= (ULONGLONG)1 << (MANT_BITS + EXP_BITS - 1);
462 bits |= (ULONGLONG)fp->exp << (MANT_BITS - 1);
463 bits |= fp->m & (((ULONGLONG)1 << (MANT_BITS - 1)) - 1);
465 TRACE("returning %s\n", wine_dbgstr_longlong(bits));
466 *d = *(double*)&bits;
467 return 0;
470 #define LDBL_EXP_BITS 15
471 #define LDBL_MANT_BITS 64
472 int fpnum_ldouble(struct fpnum *fp, MSVCRT__LDOUBLE *d)
474 if (fp->mod == FP_VAL_INFINITY)
476 d->x80[0] = 0;
477 d->x80[1] = 0x80000000;
478 d->x80[2] = (1 << LDBL_EXP_BITS) - 1;
479 if (fp->sign == -1)
480 d->x80[2] |= 1 << LDBL_EXP_BITS;
481 return 0;
484 if (fp->mod == FP_VAL_NAN)
486 d->x80[0] = ~0;
487 d->x80[1] = ~0;
488 d->x80[2] = (1 << LDBL_EXP_BITS) - 1;
489 if (fp->sign == -1)
490 d->x80[2] |= 1 << LDBL_EXP_BITS;
491 return 0;
494 TRACE("%c %s *2^%d (round %d)\n", fp->sign == -1 ? '-' : '+',
495 wine_dbgstr_longlong(fp->m), fp->exp, fp->mod);
496 if (!fp->m)
498 d->x80[0] = 0;
499 d->x80[1] = 0;
500 d->x80[2] = 0;
501 if (fp->sign == -1)
502 d->x80[2] |= 1 << LDBL_EXP_BITS;
503 return 0;
506 /* make sure that we don't overflow modifying exponent */
507 if (fp->exp > 1<<LDBL_EXP_BITS)
509 d->x80[0] = 0;
510 d->x80[1] = 0x80000000;
511 d->x80[2] = (1 << LDBL_EXP_BITS) - 1;
512 if (fp->sign == -1)
513 d->x80[2] |= 1 << LDBL_EXP_BITS;
514 return MSVCRT_ERANGE;
516 if (fp->exp < -(1<<LDBL_EXP_BITS))
518 d->x80[0] = 0;
519 d->x80[1] = 0;
520 d->x80[2] = 0;
521 if (fp->sign == -1)
522 d->x80[2] |= 1 << LDBL_EXP_BITS;
523 return MSVCRT_ERANGE;
525 fp->exp += LDBL_MANT_BITS - 1;
527 /* normalize mantissa */
528 while(fp->m < (ULONGLONG)1 << (LDBL_MANT_BITS-1))
530 fp->m <<= 1;
531 fp->exp--;
533 fp->exp += (1 << (LDBL_EXP_BITS-1)) - 1;
535 /* handle subnormals */
536 if (fp->exp <= 0)
538 if (fp->m & 1 && fp->mod == FP_ROUND_ZERO) fp->mod = FP_ROUND_EVEN;
539 else if (fp->m & 1) fp->mod = FP_ROUND_UP;
540 else if (fp->mod != FP_ROUND_ZERO) fp->mod = FP_ROUND_DOWN;
541 fp->m >>= 1;
543 while(fp->m && fp->exp<0)
545 if (fp->m & 1 && fp->mod == FP_ROUND_ZERO) fp->mod = FP_ROUND_EVEN;
546 else if (fp->m & 1) fp->mod = FP_ROUND_UP;
547 else if (fp->mod != FP_ROUND_ZERO) fp->mod = FP_ROUND_DOWN;
548 fp->m >>= 1;
549 fp->exp++;
552 /* round mantissa */
553 if (fp->mod == FP_ROUND_UP || (fp->mod == FP_ROUND_EVEN && fp->m & 1))
555 if (fp->m == MSVCRT_UI64_MAX)
557 fp->m = (ULONGLONG)1 << (LDBL_MANT_BITS - 1);
558 fp->exp++;
560 else
562 fp->m++;
564 /* handle subnormal that falls into regular range due to rounding */
565 if ((fp->m ^ (fp->m - 1)) & ((ULONGLONG)1 << (LDBL_MANT_BITS - 1))) fp->exp++;
569 if (fp->exp >= (1<<LDBL_EXP_BITS)-1)
571 d->x80[0] = 0;
572 d->x80[1] = 0x80000000;
573 d->x80[2] = (1 << LDBL_EXP_BITS) - 1;
574 if (fp->sign == -1)
575 d->x80[2] |= 1 << LDBL_EXP_BITS;
576 return MSVCRT_ERANGE;
578 if (!fp->m || fp->exp < 0)
580 d->x80[0] = 0;
581 d->x80[1] = 0;
582 d->x80[2] = 0;
583 if (fp->sign == -1)
584 d->x80[2] |= 1 << LDBL_EXP_BITS;
585 return MSVCRT_ERANGE;
588 d->x80[0] = fp->m;
589 d->x80[1] = fp->m >> 32;
590 d->x80[2] = fp->exp;
591 if (fp->sign == -1)
592 d->x80[2] |= 1 << LDBL_EXP_BITS;
593 return 0;
596 #if _MSVCR_VER >= 140
598 static inline int hex2int(char c)
600 if (c >= '0' && c <= '9')
601 return c - '0';
602 else if (c >= 'a' && c <= 'f')
603 return c - 'a' + 10;
604 else if (c >= 'A' && c <= 'F')
605 return c - 'A' + 10;
606 return -1;
609 static struct fpnum fpnum_parse16(MSVCRT_wchar_t get(void *ctx), void unget(void *ctx),
610 void *ctx, int sign, MSVCRT_pthreadlocinfo locinfo)
612 BOOL found_digit = FALSE, found_dp = FALSE;
613 enum fpmod round = FP_ROUND_ZERO;
614 MSVCRT_wchar_t nch;
615 ULONGLONG m = 0;
616 int val, exp = 0;
618 nch = get(ctx);
619 while(m < MSVCRT_UI64_MAX/16)
621 val = hex2int(nch);
622 if (val == -1) break;
623 found_digit = TRUE;
624 nch = get(ctx);
626 m = m*16 + val;
628 while(1)
630 val = hex2int(nch);
631 if (val == -1) break;
632 nch = get(ctx);
633 exp += 4;
635 if (val || round != FP_ROUND_ZERO)
637 if (val < 8) round = FP_ROUND_DOWN;
638 else if (val == 8 && round == FP_ROUND_ZERO) round = FP_ROUND_EVEN;
639 else round = FP_ROUND_UP;
643 if(nch == *locinfo->lconv->decimal_point)
645 found_dp = TRUE;
646 nch = get(ctx);
648 else if (!found_digit)
650 if(nch!=MSVCRT_WEOF) unget(ctx);
651 unget(ctx);
652 return fpnum(0, 0, 0, 0);
655 while(m <= MSVCRT_UI64_MAX/16)
657 val = hex2int(nch);
658 if (val == -1) break;
659 found_digit = TRUE;
660 nch = get(ctx);
662 m = m*16 + val;
663 exp -= 4;
665 while(1)
667 val = hex2int(nch);
668 if (val == -1) break;
669 nch = get(ctx);
671 if (val || round != FP_ROUND_ZERO)
673 if (val < 8) round = FP_ROUND_DOWN;
674 else if (val == 8 && round == FP_ROUND_ZERO) round = FP_ROUND_EVEN;
675 else round = FP_ROUND_UP;
679 if (!found_digit)
681 if (nch != MSVCRT_WEOF) unget(ctx);
682 if (found_dp) unget(ctx);
683 unget(ctx);
684 return fpnum(0, 0, 0, 0);
687 if(nch=='p' || nch=='P') {
688 BOOL found_sign = FALSE;
689 int e=0, s=1;
691 nch = get(ctx);
692 if(nch == '-') {
693 found_sign = TRUE;
694 s = -1;
695 nch = get(ctx);
696 } else if(nch == '+') {
697 found_sign = TRUE;
698 nch = get(ctx);
700 if(nch>='0' && nch<='9') {
701 while(nch>='0' && nch<='9') {
702 if(e>INT_MAX/10 || e*10>INT_MAX-nch+'0')
703 e = INT_MAX;
704 else
705 e = e*10+nch-'0';
706 nch = get(ctx);
708 if((nch!=MSVCRT_WEOF) && (nch < '0' || nch > '9')) unget(ctx);
709 e *= s;
711 if(e<0 && exp<INT_MIN-e) exp = INT_MIN;
712 else if(e>0 && exp>INT_MAX-e) exp = INT_MAX;
713 else exp += e;
714 } else {
715 if(nch != MSVCRT_WEOF) unget(ctx);
716 if(found_sign) unget(ctx);
717 unget(ctx);
721 return fpnum(sign, exp, m, round);
723 #endif
725 /* Converts first 3 limbs to ULONGLONG */
726 /* Return FALSE on overflow */
727 static inline BOOL bnum_to_mant(struct bnum *b, ULONGLONG *m)
729 if(MSVCRT_UI64_MAX / LIMB_MAX / LIMB_MAX < b->data[bnum_idx(b, b->e-1)]) return FALSE;
730 *m = (ULONGLONG)b->data[bnum_idx(b, b->e-1)] * LIMB_MAX * LIMB_MAX;
731 if(b->b == b->e-1) return TRUE;
732 if(MSVCRT_UI64_MAX - *m < (ULONGLONG)b->data[bnum_idx(b, b->e-2)] * LIMB_MAX) return FALSE;
733 *m += (ULONGLONG)b->data[bnum_idx(b, b->e-2)] * LIMB_MAX;
734 if(b->b == b->e-2) return TRUE;
735 if(MSVCRT_UI64_MAX - *m < b->data[bnum_idx(b, b->e-3)]) return FALSE;
736 *m += b->data[bnum_idx(b, b->e-3)];
737 return TRUE;
740 static struct fpnum fpnum_parse_bnum(MSVCRT_wchar_t (*get)(void *ctx), void (*unget)(void *ctx),
741 void *ctx, MSVCRT_pthreadlocinfo locinfo, BOOL ldouble, struct bnum *b)
743 #if _MSVCR_VER >= 140
744 MSVCRT_wchar_t _infinity[] = { 'i', 'n', 'f', 'i', 'n', 'i', 't', 'y', 0 };
745 MSVCRT_wchar_t _nan[] = { 'n', 'a', 'n', 0 };
746 MSVCRT_wchar_t *str_match = NULL;
747 int matched=0;
748 #endif
749 BOOL found_digit = FALSE, found_dp = FALSE, found_sign = FALSE;
750 int e2 = 0, dp=0, sign=1, off, limb_digits = 0, i;
751 enum fpmod round = FP_ROUND_ZERO;
752 MSVCRT_wchar_t nch;
753 ULONGLONG m;
755 nch = get(ctx);
756 if(nch == '-') {
757 found_sign = TRUE;
758 sign = -1;
759 nch = get(ctx);
760 } else if(nch == '+') {
761 found_sign = TRUE;
762 nch = get(ctx);
765 #if _MSVCR_VER >= 140
766 if(nch == _infinity[0] || nch == MSVCRT__toupper(_infinity[0]))
767 str_match = _infinity;
768 if(nch == _nan[0] || nch == MSVCRT__toupper(_nan[0]))
769 str_match = _nan;
770 while(str_match && nch != MSVCRT_WEOF &&
771 (nch == str_match[matched] || nch == MSVCRT__toupper(str_match[matched]))) {
772 nch = get(ctx);
773 matched++;
775 if(str_match) {
776 int keep = 0;
777 if(matched >= 8) keep = 8;
778 else if(matched >= 3) keep = 3;
779 if(nch != MSVCRT_WEOF) unget(ctx);
780 for (; matched > keep; matched--) {
781 unget(ctx);
783 if(keep) {
784 if (str_match == _infinity)
785 return fpnum(sign, 0, 0, FP_VAL_INFINITY);
786 if (str_match == _nan)
787 return fpnum(sign, 0, 0, FP_VAL_NAN);
788 } else if(found_sign) {
789 unget(ctx);
792 return fpnum(0, 0, 0, 0);
795 if(nch == '0') {
796 found_digit = TRUE;
797 nch = get(ctx);
798 if(nch == 'x' || nch == 'X')
799 return fpnum_parse16(get, unget, ctx, sign, locinfo);
801 #endif
803 while(nch == '0') {
804 found_digit = TRUE;
805 nch = get(ctx);
808 b->b = 0;
809 b->e = 1;
810 b->data[0] = 0;
811 while(nch>='0' && nch<='9') {
812 found_digit = TRUE;
813 if(limb_digits == LIMB_DIGITS) {
814 if(bnum_idx(b, b->b-1) == bnum_idx(b, b->e)) break;
815 else {
816 b->b--;
817 b->data[bnum_idx(b, b->b)] = 0;
818 limb_digits = 0;
822 b->data[bnum_idx(b, b->b)] = b->data[bnum_idx(b, b->b)] * 10 + nch - '0';
823 limb_digits++;
824 nch = get(ctx);
825 dp++;
827 while(nch>='0' && nch<='9') {
828 if(nch != '0') b->data[bnum_idx(b, b->b)] |= 1;
829 nch = get(ctx);
830 dp++;
833 if(nch == *locinfo->lconv->decimal_point) {
834 found_dp = TRUE;
835 nch = get(ctx);
838 /* skip leading '0' */
839 if(nch=='0' && !limb_digits && !b->b) {
840 found_digit = TRUE;
841 while(nch == '0') {
842 nch = get(ctx);
843 dp--;
847 while(nch>='0' && nch<='9') {
848 found_digit = TRUE;
849 if(limb_digits == LIMB_DIGITS) {
850 if(bnum_idx(b, b->b-1) == bnum_idx(b, b->e)) break;
851 else {
852 b->b--;
853 b->data[bnum_idx(b, b->b)] = 0;
854 limb_digits = 0;
858 b->data[bnum_idx(b, b->b)] = b->data[bnum_idx(b, b->b)] * 10 + nch - '0';
859 limb_digits++;
860 nch = get(ctx);
862 while(nch>='0' && nch<='9') {
863 if(nch != '0') b->data[bnum_idx(b, b->b)] |= 1;
864 nch = get(ctx);
867 if(!found_digit) {
868 if(nch != MSVCRT_WEOF) unget(ctx);
869 if(found_dp) unget(ctx);
870 if(found_sign) unget(ctx);
871 return fpnum(0, 0, 0, 0);
874 if(nch=='e' || nch=='E' || nch=='d' || nch=='D') {
875 int e=0, s=1;
877 nch = get(ctx);
878 if(nch == '-') {
879 found_sign = TRUE;
880 s = -1;
881 nch = get(ctx);
882 } else if(nch == '+') {
883 found_sign = TRUE;
884 nch = get(ctx);
885 } else {
886 found_sign = FALSE;
889 if(nch>='0' && nch<='9') {
890 while(nch>='0' && nch<='9') {
891 if(e>INT_MAX/10 || e*10>INT_MAX-nch+'0')
892 e = INT_MAX;
893 else
894 e = e*10+nch-'0';
895 nch = get(ctx);
897 if(nch != MSVCRT_WEOF) unget(ctx);
898 e *= s;
900 if(e<0 && dp<INT_MIN-e) dp = INT_MIN;
901 else if(e>0 && dp>INT_MAX-e) dp = INT_MAX;
902 else dp += e;
903 } else {
904 if(nch != MSVCRT_WEOF) unget(ctx);
905 if(found_sign) unget(ctx);
906 unget(ctx);
908 } else if(nch != MSVCRT_WEOF) {
909 unget(ctx);
912 if(!b->data[bnum_idx(b, b->e-1)])
913 return fpnum(sign, 0, 0, 0);
915 /* Fill last limb with 0 if needed */
916 if(b->b+1 != b->e) {
917 for(; limb_digits != LIMB_DIGITS; limb_digits++)
918 b->data[bnum_idx(b, b->b)] *= 10;
920 for(; bnum_idx(b, b->b) < bnum_idx(b, b->e); b->b++) {
921 if(b->data[bnum_idx(b, b->b)]) break;
924 /* move decimal point to limb boundary */
925 if(limb_digits==dp && b->b==b->e-1)
926 return fpnum(sign, 0, b->data[bnum_idx(b, b->e-1)], FP_ROUND_ZERO);
927 off = (dp - limb_digits) % LIMB_DIGITS;
928 if(off < 0) off += LIMB_DIGITS;
929 if(off) bnum_mult(b, p10s[off]);
931 if(dp-1 > (ldouble ? DBL80_MAX_10_EXP : MSVCRT_DBL_MAX_10_EXP))
932 return fpnum(sign, INT_MAX, 1, FP_ROUND_ZERO);
933 /* Count part of exponent stored in denormalized mantissa. */
934 /* Increase exponent range to handle subnormals. */
935 if(dp-1 < (ldouble ? DBL80_MIN_10_EXP : MSVCRT_DBL_MIN_10_EXP-MSVCRT_DBL_DIG-18))
936 return fpnum(sign, INT_MIN, 1, FP_ROUND_ZERO);
938 while(dp > 3*LIMB_DIGITS) {
939 if(bnum_rshift(b, 9)) dp -= LIMB_DIGITS;
940 e2 += 9;
942 while(dp <= 2*LIMB_DIGITS) {
943 if(bnum_lshift(b, 29)) dp += LIMB_DIGITS;
944 e2 -= 29;
946 /* Make sure most significant mantissa bit will be set */
947 while(b->data[bnum_idx(b, b->e-1)] <= 9) {
948 bnum_lshift(b, 1);
949 e2--;
951 while(!bnum_to_mant(b, &m)) {
952 bnum_rshift(b, 1);
953 e2++;
956 if(b->e-4 >= b->b && b->data[bnum_idx(b, b->e-4)]) {
957 if(b->data[bnum_idx(b, b->e-4)] > LIMB_MAX/2) round = FP_ROUND_UP;
958 else if(b->data[bnum_idx(b, b->e-4)] == LIMB_MAX/2) round = FP_ROUND_EVEN;
959 else round = FP_ROUND_DOWN;
961 if(round == FP_ROUND_ZERO || round == FP_ROUND_EVEN) {
962 for(i=b->e-5; i>=b->b; i--) {
963 if(!b->data[bnum_idx(b, b->b)]) continue;
964 if(round == FP_ROUND_EVEN) round = FP_ROUND_UP;
965 else round = FP_ROUND_DOWN;
969 return fpnum(sign, e2, m, round);
972 struct fpnum fpnum_parse(MSVCRT_wchar_t (*get)(void *ctx), void (*unget)(void *ctx),
973 void *ctx, MSVCRT_pthreadlocinfo locinfo, BOOL ldouble)
975 if(!ldouble) {
976 BYTE bnum_data[FIELD_OFFSET(struct bnum, data[BNUM_PREC64])];
977 struct bnum *b = (struct bnum*)bnum_data;
979 b->size = BNUM_PREC64;
980 return fpnum_parse_bnum(get, unget, ctx, locinfo, ldouble, b);
981 } else {
982 BYTE bnum_data[FIELD_OFFSET(struct bnum, data[BNUM_PREC80])];
983 struct bnum *b = (struct bnum*)bnum_data;
985 b->size = BNUM_PREC80;
986 return fpnum_parse_bnum(get, unget, ctx, locinfo, ldouble, b);
990 static MSVCRT_wchar_t strtod_str_get(void *ctx)
992 const char **p = ctx;
993 if (!**p) return MSVCRT_WEOF;
994 return *(*p)++;
997 static void strtod_str_unget(void *ctx)
999 const char **p = ctx;
1000 (*p)--;
1003 static inline double strtod_helper(const char *str, char **end, MSVCRT__locale_t locale, int *perr)
1005 MSVCRT_pthreadlocinfo locinfo;
1006 const char *beg, *p;
1007 struct fpnum fp;
1008 double ret;
1009 int err;
1011 if (perr) *perr = 0;
1012 #if _MSVCR_VER == 0
1013 else *MSVCRT__errno() = 0;
1014 #endif
1016 if (!MSVCRT_CHECK_PMT(str != NULL)) {
1017 if (end) *end = NULL;
1018 return 0;
1021 if (!locale)
1022 locinfo = get_locinfo();
1023 else
1024 locinfo = locale->locinfo;
1026 p = str;
1027 while(MSVCRT__isspace_l((unsigned char)*p, locale))
1028 p++;
1029 beg = p;
1031 fp = fpnum_parse(strtod_str_get, strtod_str_unget, &p, locinfo, FALSE);
1032 if (end) *end = (p == beg ? (char*)str : (char*)p);
1034 err = fpnum_double(&fp, &ret);
1035 if (perr) *perr = err;
1036 else if(err) *MSVCRT__errno() = err;
1037 return ret;
1040 /*********************************************************************
1041 * strtod_l (MSVCRT.@)
1043 double CDECL MSVCRT_strtod_l(const char *str, char **end, MSVCRT__locale_t locale)
1045 return strtod_helper(str, end, locale, NULL);
1048 /*********************************************************************
1049 * strtod (MSVCRT.@)
1051 double CDECL MSVCRT_strtod( const char *str, char **end )
1053 return MSVCRT_strtod_l( str, end, NULL );
1056 #if _MSVCR_VER>=120
1058 /*********************************************************************
1059 * strtof_l (MSVCR120.@)
1061 float CDECL MSVCRT__strtof_l( const char *str, char **end, MSVCRT__locale_t locale )
1063 return MSVCRT_strtod_l(str, end, locale);
1066 /*********************************************************************
1067 * strtof (MSVCR120.@)
1069 float CDECL MSVCRT_strtof( const char *str, char **end )
1071 return MSVCRT__strtof_l(str, end, NULL);
1074 #endif /* _MSVCR_VER>=120 */
1076 /*********************************************************************
1077 * atof (MSVCRT.@)
1079 double CDECL MSVCRT_atof( const char *str )
1081 return MSVCRT_strtod_l(str, NULL, NULL);
1084 /*********************************************************************
1085 * _atof_l (MSVCRT.@)
1087 double CDECL MSVCRT__atof_l( const char *str, MSVCRT__locale_t locale)
1089 return MSVCRT_strtod_l(str, NULL, locale);
1092 /*********************************************************************
1093 * _atoflt_l (MSVCRT.@)
1095 int CDECL MSVCRT__atoflt_l( MSVCRT__CRT_FLOAT *value, char *str, MSVCRT__locale_t locale)
1097 double d;
1098 int err;
1100 d = strtod_helper(str, NULL, locale, &err);
1101 value->f = d;
1102 if(isinf(value->f))
1103 return MSVCRT__OVERFLOW;
1104 if((d!=0 || err) && value->f>-MSVCRT_FLT_MIN && value->f<MSVCRT_FLT_MIN)
1105 return MSVCRT__UNDERFLOW;
1106 return 0;
1109 /*********************************************************************
1110 * _atoflt (MSVCR100.@)
1112 int CDECL MSVCRT__atoflt(MSVCRT__CRT_FLOAT *value, char *str)
1114 return MSVCRT__atoflt_l(value, str, NULL);
1117 /*********************************************************************
1118 * _atodbl_l (MSVCRT.@)
1120 int CDECL MSVCRT__atodbl_l(MSVCRT__CRT_DOUBLE *value, char *str, MSVCRT__locale_t locale)
1122 int err;
1124 value->x = strtod_helper(str, NULL, locale, &err);
1125 if(isinf(value->x))
1126 return MSVCRT__OVERFLOW;
1127 if((value->x!=0 || err) && value->x>-MSVCRT_DBL_MIN && value->x<MSVCRT_DBL_MIN)
1128 return MSVCRT__UNDERFLOW;
1129 return 0;
1132 /*********************************************************************
1133 * _atodbl (MSVCRT.@)
1135 int CDECL MSVCRT__atodbl(MSVCRT__CRT_DOUBLE *value, char *str)
1137 return MSVCRT__atodbl_l(value, str, NULL);
1140 /*********************************************************************
1141 * _strcoll_l (MSVCRT.@)
1143 int CDECL MSVCRT_strcoll_l( const char* str1, const char* str2, MSVCRT__locale_t locale )
1145 MSVCRT_pthreadlocinfo locinfo;
1147 if(!locale)
1148 locinfo = get_locinfo();
1149 else
1150 locinfo = locale->locinfo;
1152 if(!locinfo->lc_handle[MSVCRT_LC_COLLATE])
1153 return strcmp(str1, str2);
1154 return CompareStringA(locinfo->lc_handle[MSVCRT_LC_COLLATE], 0, str1, -1, str2, -1)-CSTR_EQUAL;
1157 /*********************************************************************
1158 * strcoll (MSVCRT.@)
1160 int CDECL MSVCRT_strcoll( const char* str1, const char* str2 )
1162 return MSVCRT_strcoll_l(str1, str2, NULL);
1165 /*********************************************************************
1166 * _stricoll_l (MSVCRT.@)
1168 int CDECL MSVCRT__stricoll_l( const char* str1, const char* str2, MSVCRT__locale_t locale )
1170 MSVCRT_pthreadlocinfo locinfo;
1172 if(!locale)
1173 locinfo = get_locinfo();
1174 else
1175 locinfo = locale->locinfo;
1177 if(!locinfo->lc_handle[MSVCRT_LC_COLLATE])
1178 return MSVCRT__stricmp(str1, str2);
1179 return CompareStringA(locinfo->lc_handle[MSVCRT_LC_COLLATE], NORM_IGNORECASE,
1180 str1, -1, str2, -1)-CSTR_EQUAL;
1183 /*********************************************************************
1184 * _stricoll (MSVCRT.@)
1186 int CDECL MSVCRT__stricoll( const char* str1, const char* str2 )
1188 return MSVCRT__stricoll_l(str1, str2, NULL);
1191 /*********************************************************************
1192 * _strncoll_l (MSVCRT.@)
1194 int CDECL MSVCRT__strncoll_l( const char* str1, const char* str2, MSVCRT_size_t count, MSVCRT__locale_t locale )
1196 MSVCRT_pthreadlocinfo locinfo;
1198 if(!locale)
1199 locinfo = get_locinfo();
1200 else
1201 locinfo = locale->locinfo;
1203 if(!locinfo->lc_handle[MSVCRT_LC_COLLATE])
1204 return MSVCRT_strncmp(str1, str2, count);
1205 return CompareStringA(locinfo->lc_handle[MSVCRT_LC_COLLATE], 0,
1206 str1, MSVCRT_strnlen(str1, count),
1207 str2, MSVCRT_strnlen(str2, count))-CSTR_EQUAL;
1210 /*********************************************************************
1211 * _strncoll (MSVCRT.@)
1213 int CDECL MSVCRT__strncoll( const char* str1, const char* str2, MSVCRT_size_t count )
1215 return MSVCRT__strncoll_l(str1, str2, count, NULL);
1218 /*********************************************************************
1219 * _strnicoll_l (MSVCRT.@)
1221 int CDECL MSVCRT__strnicoll_l( const char* str1, const char* str2, MSVCRT_size_t count, MSVCRT__locale_t locale )
1223 MSVCRT_pthreadlocinfo locinfo;
1225 if(!locale)
1226 locinfo = get_locinfo();
1227 else
1228 locinfo = locale->locinfo;
1230 if(!locinfo->lc_handle[MSVCRT_LC_COLLATE])
1231 return MSVCRT__strnicmp(str1, str2, count);
1232 return CompareStringA(locinfo->lc_handle[MSVCRT_LC_COLLATE], NORM_IGNORECASE,
1233 str1, MSVCRT_strnlen(str1, count),
1234 str2, MSVCRT_strnlen(str2, count))-CSTR_EQUAL;
1237 /*********************************************************************
1238 * _strnicoll (MSVCRT.@)
1240 int CDECL MSVCRT__strnicoll( const char* str1, const char* str2, MSVCRT_size_t count )
1242 return MSVCRT__strnicoll_l(str1, str2, count, NULL);
1245 /*********************************************************************
1246 * strncpy (MSVCRT.@)
1248 char* __cdecl MSVCRT_strncpy(char *dst, const char *src, MSVCRT_size_t len)
1250 MSVCRT_size_t i;
1252 for(i=0; i<len; i++)
1253 if((dst[i] = src[i]) == '\0') break;
1255 while (i < len) dst[i++] = 0;
1257 return dst;
1260 /*********************************************************************
1261 * strcpy (MSVCRT.@)
1263 char* CDECL strcpy(char *dst, const char *src)
1265 char *ret = dst;
1266 while ((*dst++ = *src++));
1267 return ret;
1270 /*********************************************************************
1271 * strcpy_s (MSVCRT.@)
1273 int CDECL MSVCRT_strcpy_s( char* dst, MSVCRT_size_t elem, const char* src )
1275 MSVCRT_size_t i;
1276 if(!elem) return MSVCRT_EINVAL;
1277 if(!dst) return MSVCRT_EINVAL;
1278 if(!src)
1280 dst[0] = '\0';
1281 return MSVCRT_EINVAL;
1284 for(i = 0; i < elem; i++)
1286 if((dst[i] = src[i]) == '\0') return 0;
1288 dst[0] = '\0';
1289 return MSVCRT_ERANGE;
1292 /*********************************************************************
1293 * strcat_s (MSVCRT.@)
1295 int CDECL MSVCRT_strcat_s( char* dst, MSVCRT_size_t elem, const char* src )
1297 MSVCRT_size_t i, j;
1298 if(!dst) return MSVCRT_EINVAL;
1299 if(elem == 0) return MSVCRT_EINVAL;
1300 if(!src)
1302 dst[0] = '\0';
1303 return MSVCRT_EINVAL;
1306 for(i = 0; i < elem; i++)
1308 if(dst[i] == '\0')
1310 for(j = 0; (j + i) < elem; j++)
1312 if((dst[j + i] = src[j]) == '\0') return 0;
1316 /* Set the first element to 0, not the first element after the skipped part */
1317 dst[0] = '\0';
1318 return MSVCRT_ERANGE;
1321 /*********************************************************************
1322 * strcat (MSVCRT.@)
1324 char* __cdecl strcat( char *dst, const char *src )
1326 char *d = dst;
1327 while (*d) d++;
1328 while ((*d++ = *src++));
1329 return dst;
1332 /*********************************************************************
1333 * strncat_s (MSVCRT.@)
1335 int CDECL MSVCRT_strncat_s( char* dst, MSVCRT_size_t elem, const char* src, MSVCRT_size_t count )
1337 MSVCRT_size_t i, j;
1339 if (!MSVCRT_CHECK_PMT(dst != 0)) return MSVCRT_EINVAL;
1340 if (!MSVCRT_CHECK_PMT(elem != 0)) return MSVCRT_EINVAL;
1341 if (!MSVCRT_CHECK_PMT(src != 0))
1343 dst[0] = '\0';
1344 return MSVCRT_EINVAL;
1347 for(i = 0; i < elem; i++)
1349 if(dst[i] == '\0')
1351 for(j = 0; (j + i) < elem; j++)
1353 if(count == MSVCRT__TRUNCATE && j + i == elem - 1)
1355 dst[j + i] = '\0';
1356 return MSVCRT_STRUNCATE;
1358 if(j == count || (dst[j + i] = src[j]) == '\0')
1360 dst[j + i] = '\0';
1361 return 0;
1366 /* Set the first element to 0, not the first element after the skipped part */
1367 dst[0] = '\0';
1368 return MSVCRT_ERANGE;
1371 /*********************************************************************
1372 * strncat (MSVCRT.@)
1374 char* __cdecl MSVCRT_strncat(char *dst, const char *src, MSVCRT_size_t len)
1376 char *d = dst;
1377 while (*d) d++;
1378 for ( ; len && *src; d++, src++, len--) *d = *src;
1379 *d = 0;
1380 return dst;
1383 /*********************************************************************
1384 * _strxfrm_l (MSVCRT.@)
1386 MSVCRT_size_t CDECL MSVCRT__strxfrm_l( char *dest, const char *src,
1387 MSVCRT_size_t len, MSVCRT__locale_t locale )
1389 MSVCRT_pthreadlocinfo locinfo;
1390 int ret;
1392 if(!MSVCRT_CHECK_PMT(src)) return INT_MAX;
1393 if(!MSVCRT_CHECK_PMT(dest || !len)) return INT_MAX;
1395 if(len > INT_MAX) {
1396 FIXME("len > INT_MAX not supported\n");
1397 len = INT_MAX;
1400 if(!locale)
1401 locinfo = get_locinfo();
1402 else
1403 locinfo = locale->locinfo;
1405 if(!locinfo->lc_handle[MSVCRT_LC_COLLATE]) {
1406 MSVCRT_strncpy(dest, src, len);
1407 return strlen(src);
1410 ret = LCMapStringA(locinfo->lc_handle[MSVCRT_LC_COLLATE],
1411 LCMAP_SORTKEY, src, -1, NULL, 0);
1412 if(!ret) {
1413 if(len) dest[0] = 0;
1414 *MSVCRT__errno() = MSVCRT_EILSEQ;
1415 return INT_MAX;
1417 if(!len) return ret-1;
1419 if(ret > len) {
1420 dest[0] = 0;
1421 *MSVCRT__errno() = MSVCRT_ERANGE;
1422 return ret-1;
1425 return LCMapStringA(locinfo->lc_handle[MSVCRT_LC_COLLATE],
1426 LCMAP_SORTKEY, src, -1, dest, len) - 1;
1429 /*********************************************************************
1430 * strxfrm (MSVCRT.@)
1432 MSVCRT_size_t CDECL MSVCRT_strxfrm( char *dest, const char *src, MSVCRT_size_t len )
1434 return MSVCRT__strxfrm_l(dest, src, len, NULL);
1437 /********************************************************************
1438 * __STRINGTOLD_L (MSVCR80.@)
1440 int CDECL __STRINGTOLD_L( MSVCRT__LDOUBLE *value, char **endptr,
1441 const char *str, int flags, MSVCRT__locale_t locale )
1443 MSVCRT_pthreadlocinfo locinfo;
1444 const char *beg, *p;
1445 int err, ret = 0;
1446 struct fpnum fp;
1448 if (flags) FIXME("flags not supported: %x\n", flags);
1450 if (!locale)
1451 locinfo = get_locinfo();
1452 else
1453 locinfo = locale->locinfo;
1455 p = str;
1456 while (MSVCRT__isspace_l((unsigned char)*p, locale))
1457 p++;
1458 beg = p;
1460 fp = fpnum_parse(strtod_str_get, strtod_str_unget, &p, locinfo, TRUE);
1461 if (endptr) *endptr = (p == beg ? (char*)str : (char*)p);
1462 if (p == beg) ret = 4;
1464 err = fpnum_ldouble(&fp, value);
1465 if (err) ret = (value->x80[2] & 0x7fff ? 2 : 1);
1466 return ret;
1469 /********************************************************************
1470 * __STRINGTOLD (MSVCRT.@)
1472 int CDECL __STRINGTOLD( MSVCRT__LDOUBLE *value, char **endptr, const char *str, int flags )
1474 return __STRINGTOLD_L( value, endptr, str, flags, NULL );
1477 /********************************************************************
1478 * _atoldbl_l (MSVCRT.@)
1480 int CDECL MSVCRT__atoldbl_l( MSVCRT__LDOUBLE *value, const char *str, MSVCRT__locale_t locale )
1482 char *endptr;
1483 switch(__STRINGTOLD_L( value, &endptr, str, 0, locale ))
1485 case 1: return MSVCRT__UNDERFLOW;
1486 case 2: return MSVCRT__OVERFLOW;
1487 default: return 0;
1491 /********************************************************************
1492 * _atoldbl (MSVCRT.@)
1494 int CDECL MSVCRT__atoldbl(MSVCRT__LDOUBLE *value, const char *str)
1496 return MSVCRT__atoldbl_l( value, str, NULL );
1499 /*********************************************************************
1500 * strlen (MSVCRT.@)
1502 size_t __cdecl strlen(const char *str)
1504 const char *s = str;
1505 while (*s) s++;
1506 return s - str;
1509 /******************************************************************
1510 * strnlen (MSVCRT.@)
1512 MSVCRT_size_t CDECL MSVCRT_strnlen(const char *s, MSVCRT_size_t maxlen)
1514 MSVCRT_size_t i;
1516 for(i=0; i<maxlen; i++)
1517 if(!s[i]) break;
1519 return i;
1522 /*********************************************************************
1523 * _strtoi64_l (MSVCRT.@)
1525 * FIXME: locale parameter is ignored
1527 __int64 CDECL MSVCRT_strtoi64_l(const char *nptr, char **endptr, int base, MSVCRT__locale_t locale)
1529 const char *p = nptr;
1530 BOOL negative = FALSE;
1531 BOOL got_digit = FALSE;
1532 __int64 ret = 0;
1534 TRACE("(%s %p %d %p)\n", debugstr_a(nptr), endptr, base, locale);
1536 if (!MSVCRT_CHECK_PMT(nptr != NULL)) return 0;
1537 if (!MSVCRT_CHECK_PMT(base == 0 || base >= 2)) return 0;
1538 if (!MSVCRT_CHECK_PMT(base <= 36)) return 0;
1540 while(MSVCRT__isspace_l((unsigned char)*nptr, locale)) nptr++;
1542 if(*nptr == '-') {
1543 negative = TRUE;
1544 nptr++;
1545 } else if(*nptr == '+')
1546 nptr++;
1548 if((base==0 || base==16) && *nptr=='0' && MSVCRT__tolower_l(*(nptr+1), locale)=='x') {
1549 base = 16;
1550 nptr += 2;
1553 if(base == 0) {
1554 if(*nptr=='0')
1555 base = 8;
1556 else
1557 base = 10;
1560 while(*nptr) {
1561 char cur = MSVCRT__tolower_l(*nptr, locale);
1562 int v;
1564 if(cur>='0' && cur<='9') {
1565 if(cur >= '0'+base)
1566 break;
1567 v = cur-'0';
1568 } else {
1569 if(cur<'a' || cur>='a'+base-10)
1570 break;
1571 v = cur-'a'+10;
1573 got_digit = TRUE;
1575 if(negative)
1576 v = -v;
1578 nptr++;
1580 if(!negative && (ret>MSVCRT_I64_MAX/base || ret*base>MSVCRT_I64_MAX-v)) {
1581 ret = MSVCRT_I64_MAX;
1582 *MSVCRT__errno() = MSVCRT_ERANGE;
1583 } else if(negative && (ret<MSVCRT_I64_MIN/base || ret*base<MSVCRT_I64_MIN-v)) {
1584 ret = MSVCRT_I64_MIN;
1585 *MSVCRT__errno() = MSVCRT_ERANGE;
1586 } else
1587 ret = ret*base + v;
1590 if(endptr)
1591 *endptr = (char*)(got_digit ? nptr : p);
1593 return ret;
1596 /*********************************************************************
1597 * _strtoi64 (MSVCRT.@)
1599 __int64 CDECL MSVCRT_strtoi64(const char *nptr, char **endptr, int base)
1601 return MSVCRT_strtoi64_l(nptr, endptr, base, NULL);
1604 /*********************************************************************
1605 * _atoi_l (MSVCRT.@)
1607 int __cdecl MSVCRT__atoi_l(const char *str, MSVCRT__locale_t locale)
1609 __int64 ret = MSVCRT_strtoi64_l(str, NULL, 10, locale);
1611 if(ret > INT_MAX) {
1612 ret = INT_MAX;
1613 *MSVCRT__errno() = MSVCRT_ERANGE;
1614 } else if(ret < INT_MIN) {
1615 ret = INT_MIN;
1616 *MSVCRT__errno() = MSVCRT_ERANGE;
1618 return ret;
1621 /*********************************************************************
1622 * atoi (MSVCRT.@)
1624 #if _MSVCR_VER == 0
1625 int __cdecl MSVCRT_atoi(const char *str)
1627 BOOL minus = FALSE;
1628 int ret = 0;
1630 if(!str)
1631 return 0;
1633 while(MSVCRT__isspace_l((unsigned char)*str, NULL)) str++;
1635 if(*str == '+') {
1636 str++;
1637 }else if(*str == '-') {
1638 minus = TRUE;
1639 str++;
1642 while(*str>='0' && *str<='9') {
1643 ret = ret*10+*str-'0';
1644 str++;
1647 return minus ? -ret : ret;
1649 #else
1650 int CDECL MSVCRT_atoi(const char *str)
1652 return MSVCRT__atoi_l(str, NULL);
1654 #endif
1656 /******************************************************************
1657 * _atoi64_l (MSVCRT.@)
1659 __int64 CDECL MSVCRT__atoi64_l(const char *str, MSVCRT__locale_t locale)
1661 return MSVCRT_strtoi64_l(str, NULL, 10, locale);
1664 /******************************************************************
1665 * _atoi64 (MSVCRT.@)
1667 __int64 CDECL MSVCRT__atoi64(const char *str)
1669 return MSVCRT_strtoi64_l(str, NULL, 10, NULL);
1672 /******************************************************************
1673 * _atol_l (MSVCRT.@)
1675 MSVCRT_long CDECL MSVCRT__atol_l(const char *str, MSVCRT__locale_t locale)
1677 __int64 ret = MSVCRT_strtoi64_l(str, NULL, 10, locale);
1679 if(ret > MSVCRT_LONG_MAX) {
1680 ret = MSVCRT_LONG_MAX;
1681 *MSVCRT__errno() = MSVCRT_ERANGE;
1682 } else if(ret < MSVCRT_LONG_MIN) {
1683 ret = MSVCRT_LONG_MIN;
1684 *MSVCRT__errno() = MSVCRT_ERANGE;
1686 return ret;
1689 /******************************************************************
1690 * atol (MSVCRT.@)
1692 MSVCRT_long CDECL MSVCRT_atol(const char *str)
1694 #if _MSVCR_VER == 0
1695 return MSVCRT_atoi(str);
1696 #else
1697 return MSVCRT__atol_l(str, NULL);
1698 #endif
1701 #if _MSVCR_VER>=120
1703 /******************************************************************
1704 * _atoll_l (MSVCR120.@)
1706 MSVCRT_longlong CDECL MSVCRT__atoll_l(const char* str, MSVCRT__locale_t locale)
1708 return MSVCRT_strtoi64_l(str, NULL, 10, locale);
1711 /******************************************************************
1712 * atoll (MSVCR120.@)
1714 MSVCRT_longlong CDECL MSVCRT_atoll(const char* str)
1716 return MSVCRT__atoll_l(str, NULL);
1719 #endif /* if _MSVCR_VER>=120 */
1721 /******************************************************************
1722 * _strtol_l (MSVCRT.@)
1724 MSVCRT_long CDECL MSVCRT__strtol_l(const char* nptr,
1725 char** end, int base, MSVCRT__locale_t locale)
1727 __int64 ret = MSVCRT_strtoi64_l(nptr, end, base, locale);
1729 if(ret > MSVCRT_LONG_MAX) {
1730 ret = MSVCRT_LONG_MAX;
1731 *MSVCRT__errno() = MSVCRT_ERANGE;
1732 } else if(ret < MSVCRT_LONG_MIN) {
1733 ret = MSVCRT_LONG_MIN;
1734 *MSVCRT__errno() = MSVCRT_ERANGE;
1737 return ret;
1740 /******************************************************************
1741 * strtol (MSVCRT.@)
1743 MSVCRT_long CDECL MSVCRT_strtol(const char* nptr, char** end, int base)
1745 return MSVCRT__strtol_l(nptr, end, base, NULL);
1748 /******************************************************************
1749 * _strtoul_l (MSVCRT.@)
1751 MSVCRT_ulong CDECL MSVCRT_strtoul_l(const char* nptr, char** end, int base, MSVCRT__locale_t locale)
1753 __int64 ret = MSVCRT_strtoi64_l(nptr, end, base, locale);
1755 if(ret > MSVCRT_ULONG_MAX) {
1756 ret = MSVCRT_ULONG_MAX;
1757 *MSVCRT__errno() = MSVCRT_ERANGE;
1758 }else if(ret < -(__int64)MSVCRT_ULONG_MAX) {
1759 ret = 1;
1760 *MSVCRT__errno() = MSVCRT_ERANGE;
1763 return ret;
1766 /******************************************************************
1767 * strtoul (MSVCRT.@)
1769 MSVCRT_ulong CDECL MSVCRT_strtoul(const char* nptr, char** end, int base)
1771 return MSVCRT_strtoul_l(nptr, end, base, NULL);
1774 /*********************************************************************
1775 * _strtoui64_l (MSVCRT.@)
1777 * FIXME: locale parameter is ignored
1779 unsigned __int64 CDECL MSVCRT_strtoui64_l(const char *nptr, char **endptr, int base, MSVCRT__locale_t locale)
1781 const char *p = nptr;
1782 BOOL negative = FALSE;
1783 BOOL got_digit = FALSE;
1784 unsigned __int64 ret = 0;
1786 TRACE("(%s %p %d %p)\n", debugstr_a(nptr), endptr, base, locale);
1788 if (!MSVCRT_CHECK_PMT(nptr != NULL)) return 0;
1789 if (!MSVCRT_CHECK_PMT(base == 0 || base >= 2)) return 0;
1790 if (!MSVCRT_CHECK_PMT(base <= 36)) return 0;
1792 while(MSVCRT__isspace_l((unsigned char)*nptr, locale)) nptr++;
1794 if(*nptr == '-') {
1795 negative = TRUE;
1796 nptr++;
1797 } else if(*nptr == '+')
1798 nptr++;
1800 if((base==0 || base==16) && *nptr=='0' && MSVCRT__tolower_l(*(nptr+1), locale)=='x') {
1801 base = 16;
1802 nptr += 2;
1805 if(base == 0) {
1806 if(*nptr=='0')
1807 base = 8;
1808 else
1809 base = 10;
1812 while(*nptr) {
1813 char cur = MSVCRT__tolower_l(*nptr, locale);
1814 int v;
1816 if(cur>='0' && cur<='9') {
1817 if(cur >= '0'+base)
1818 break;
1819 v = *nptr-'0';
1820 } else {
1821 if(cur<'a' || cur>='a'+base-10)
1822 break;
1823 v = cur-'a'+10;
1825 got_digit = TRUE;
1827 nptr++;
1829 if(ret>MSVCRT_UI64_MAX/base || ret*base>MSVCRT_UI64_MAX-v) {
1830 ret = MSVCRT_UI64_MAX;
1831 *MSVCRT__errno() = MSVCRT_ERANGE;
1832 } else
1833 ret = ret*base + v;
1836 if(endptr)
1837 *endptr = (char*)(got_digit ? nptr : p);
1839 return negative ? -ret : ret;
1842 /*********************************************************************
1843 * _strtoui64 (MSVCRT.@)
1845 unsigned __int64 CDECL MSVCRT_strtoui64(const char *nptr, char **endptr, int base)
1847 return MSVCRT_strtoui64_l(nptr, endptr, base, NULL);
1850 static int ltoa_helper(MSVCRT_long value, char *str, MSVCRT_size_t size, int radix)
1852 MSVCRT_ulong val;
1853 unsigned int digit;
1854 BOOL is_negative;
1855 char buffer[33], *pos;
1856 size_t len;
1858 if (value < 0 && radix == 10)
1860 is_negative = TRUE;
1861 val = -value;
1863 else
1865 is_negative = FALSE;
1866 val = value;
1869 pos = buffer + 32;
1870 *pos = '\0';
1874 digit = val % radix;
1875 val /= radix;
1877 if (digit < 10)
1878 *--pos = '0' + digit;
1879 else
1880 *--pos = 'a' + digit - 10;
1882 while (val != 0);
1884 if (is_negative)
1885 *--pos = '-';
1887 len = buffer + 33 - pos;
1888 if (len > size)
1890 size_t i;
1891 char *p = str;
1893 /* Copy the temporary buffer backwards up to the available number of
1894 * characters. Don't copy the negative sign if present. */
1896 if (is_negative)
1898 p++;
1899 size--;
1902 for (pos = buffer + 31, i = 0; i < size; i++)
1903 *p++ = *pos--;
1905 str[0] = '\0';
1906 MSVCRT_INVALID_PMT("str[size] is too small", MSVCRT_ERANGE);
1907 return MSVCRT_ERANGE;
1910 memcpy(str, pos, len);
1911 return 0;
1914 /*********************************************************************
1915 * _ltoa_s (MSVCRT.@)
1917 int CDECL MSVCRT__ltoa_s(MSVCRT_long value, char *str, MSVCRT_size_t size, int radix)
1919 if (!MSVCRT_CHECK_PMT(str != NULL)) return MSVCRT_EINVAL;
1920 if (!MSVCRT_CHECK_PMT(size > 0)) return MSVCRT_EINVAL;
1921 if (!MSVCRT_CHECK_PMT(radix >= 2 && radix <= 36))
1923 str[0] = '\0';
1924 return MSVCRT_EINVAL;
1927 return ltoa_helper(value, str, size, radix);
1930 /*********************************************************************
1931 * _ltow_s (MSVCRT.@)
1933 int CDECL MSVCRT__ltow_s(MSVCRT_long value, MSVCRT_wchar_t *str, MSVCRT_size_t size, int radix)
1935 MSVCRT_ulong val;
1936 unsigned int digit;
1937 BOOL is_negative;
1938 MSVCRT_wchar_t buffer[33], *pos;
1939 size_t len;
1941 if (!MSVCRT_CHECK_PMT(str != NULL)) return MSVCRT_EINVAL;
1942 if (!MSVCRT_CHECK_PMT(size > 0)) return MSVCRT_EINVAL;
1943 if (!MSVCRT_CHECK_PMT(radix >= 2 && radix <= 36))
1945 str[0] = '\0';
1946 return MSVCRT_EINVAL;
1949 if (value < 0 && radix == 10)
1951 is_negative = TRUE;
1952 val = -value;
1954 else
1956 is_negative = FALSE;
1957 val = value;
1960 pos = buffer + 32;
1961 *pos = '\0';
1965 digit = val % radix;
1966 val /= radix;
1968 if (digit < 10)
1969 *--pos = '0' + digit;
1970 else
1971 *--pos = 'a' + digit - 10;
1973 while (val != 0);
1975 if (is_negative)
1976 *--pos = '-';
1978 len = buffer + 33 - pos;
1979 if (len > size)
1981 size_t i;
1982 MSVCRT_wchar_t *p = str;
1984 /* Copy the temporary buffer backwards up to the available number of
1985 * characters. Don't copy the negative sign if present. */
1987 if (is_negative)
1989 p++;
1990 size--;
1993 for (pos = buffer + 31, i = 0; i < size; i++)
1994 *p++ = *pos--;
1996 str[0] = '\0';
1997 MSVCRT_INVALID_PMT("str[size] is too small", MSVCRT_ERANGE);
1998 return MSVCRT_ERANGE;
2001 memcpy(str, pos, len * sizeof(MSVCRT_wchar_t));
2002 return 0;
2005 /*********************************************************************
2006 * _itoa_s (MSVCRT.@)
2008 int CDECL MSVCRT__itoa_s(int value, char *str, MSVCRT_size_t size, int radix)
2010 return MSVCRT__ltoa_s(value, str, size, radix);
2013 /*********************************************************************
2014 * _itoa (MSVCRT.@)
2016 char* CDECL MSVCRT__itoa(int value, char *str, int radix)
2018 return ltoa_helper(value, str, MSVCRT_SIZE_MAX, radix) ? NULL : str;
2021 /*********************************************************************
2022 * _itow_s (MSVCRT.@)
2024 int CDECL MSVCRT__itow_s(int value, MSVCRT_wchar_t *str, MSVCRT_size_t size, int radix)
2026 return MSVCRT__ltow_s(value, str, size, radix);
2029 /*********************************************************************
2030 * _ui64toa_s (MSVCRT.@)
2032 int CDECL MSVCRT__ui64toa_s(unsigned __int64 value, char *str,
2033 MSVCRT_size_t size, int radix)
2035 char buffer[65], *pos;
2036 int digit;
2038 if (!MSVCRT_CHECK_PMT(str != NULL)) return MSVCRT_EINVAL;
2039 if (!MSVCRT_CHECK_PMT(size > 0)) return MSVCRT_EINVAL;
2040 if (!MSVCRT_CHECK_PMT(radix >= 2 && radix <= 36))
2042 str[0] = '\0';
2043 return MSVCRT_EINVAL;
2046 pos = buffer+64;
2047 *pos = '\0';
2049 do {
2050 digit = value%radix;
2051 value /= radix;
2053 if(digit < 10)
2054 *--pos = '0'+digit;
2055 else
2056 *--pos = 'a'+digit-10;
2057 }while(value != 0);
2059 if(buffer-pos+65 > size) {
2060 MSVCRT_INVALID_PMT("str[size] is too small", MSVCRT_EINVAL);
2061 return MSVCRT_EINVAL;
2064 memcpy(str, pos, buffer-pos+65);
2065 return 0;
2068 /*********************************************************************
2069 * _ui64tow_s (MSVCRT.@)
2071 int CDECL MSVCRT__ui64tow_s( unsigned __int64 value, MSVCRT_wchar_t *str,
2072 MSVCRT_size_t size, int radix )
2074 MSVCRT_wchar_t buffer[65], *pos;
2075 int digit;
2077 if (!MSVCRT_CHECK_PMT(str != NULL)) return MSVCRT_EINVAL;
2078 if (!MSVCRT_CHECK_PMT(size > 0)) return MSVCRT_EINVAL;
2079 if (!MSVCRT_CHECK_PMT(radix >= 2 && radix <= 36))
2081 str[0] = '\0';
2082 return MSVCRT_EINVAL;
2085 pos = &buffer[64];
2086 *pos = '\0';
2088 do {
2089 digit = value % radix;
2090 value = value / radix;
2091 if (digit < 10)
2092 *--pos = '0' + digit;
2093 else
2094 *--pos = 'a' + digit - 10;
2095 } while (value != 0);
2097 if(buffer-pos+65 > size) {
2098 MSVCRT_INVALID_PMT("str[size] is too small", MSVCRT_EINVAL);
2099 return MSVCRT_EINVAL;
2102 memcpy(str, pos, (buffer-pos+65)*sizeof(MSVCRT_wchar_t));
2103 return 0;
2106 /*********************************************************************
2107 * _ultoa_s (MSVCRT.@)
2109 int CDECL MSVCRT__ultoa_s(MSVCRT_ulong value, char *str, MSVCRT_size_t size, int radix)
2111 MSVCRT_ulong digit;
2112 char buffer[33], *pos;
2113 size_t len;
2115 if (!str || !size || radix < 2 || radix > 36)
2117 if (str && size)
2118 str[0] = '\0';
2120 *MSVCRT__errno() = MSVCRT_EINVAL;
2121 return MSVCRT_EINVAL;
2124 pos = buffer + 32;
2125 *pos = '\0';
2129 digit = value % radix;
2130 value /= radix;
2132 if (digit < 10)
2133 *--pos = '0' + digit;
2134 else
2135 *--pos = 'a' + digit - 10;
2137 while (value != 0);
2139 len = buffer + 33 - pos;
2140 if (len > size)
2142 size_t i;
2143 char *p = str;
2145 /* Copy the temporary buffer backwards up to the available number of
2146 * characters. */
2148 for (pos = buffer + 31, i = 0; i < size; i++)
2149 *p++ = *pos--;
2151 str[0] = '\0';
2152 *MSVCRT__errno() = MSVCRT_ERANGE;
2153 return MSVCRT_ERANGE;
2156 memcpy(str, pos, len);
2157 return 0;
2160 /*********************************************************************
2161 * _ultow_s (MSVCRT.@)
2163 int CDECL MSVCRT__ultow_s(MSVCRT_ulong value, MSVCRT_wchar_t *str, MSVCRT_size_t size, int radix)
2165 MSVCRT_ulong digit;
2166 WCHAR buffer[33], *pos;
2167 size_t len;
2169 if (!str || !size || radix < 2 || radix > 36)
2171 if (str && size)
2172 str[0] = '\0';
2174 *MSVCRT__errno() = MSVCRT_EINVAL;
2175 return MSVCRT_EINVAL;
2178 pos = buffer + 32;
2179 *pos = '\0';
2183 digit = value % radix;
2184 value /= radix;
2186 if (digit < 10)
2187 *--pos = '0' + digit;
2188 else
2189 *--pos = 'a' + digit - 10;
2191 while (value != 0);
2193 len = buffer + 33 - pos;
2194 if (len > size)
2196 size_t i;
2197 WCHAR *p = str;
2199 /* Copy the temporary buffer backwards up to the available number of
2200 * characters. */
2202 for (pos = buffer + 31, i = 0; i < size; i++)
2203 *p++ = *pos--;
2205 str[0] = '\0';
2206 *MSVCRT__errno() = MSVCRT_ERANGE;
2207 return MSVCRT_ERANGE;
2210 memcpy(str, pos, len * sizeof(MSVCRT_wchar_t));
2211 return 0;
2214 /*********************************************************************
2215 * _i64toa_s (MSVCRT.@)
2217 int CDECL MSVCRT__i64toa_s(__int64 value, char *str, MSVCRT_size_t size, int radix)
2219 unsigned __int64 val;
2220 unsigned int digit;
2221 BOOL is_negative;
2222 char buffer[65], *pos;
2223 size_t len;
2225 if (!MSVCRT_CHECK_PMT(str != NULL)) return MSVCRT_EINVAL;
2226 if (!MSVCRT_CHECK_PMT(size > 0)) return MSVCRT_EINVAL;
2227 if (!MSVCRT_CHECK_PMT(radix >= 2 && radix <= 36))
2229 str[0] = '\0';
2230 return MSVCRT_EINVAL;
2233 if (value < 0 && radix == 10)
2235 is_negative = TRUE;
2236 val = -value;
2238 else
2240 is_negative = FALSE;
2241 val = value;
2244 pos = buffer + 64;
2245 *pos = '\0';
2249 digit = val % radix;
2250 val /= radix;
2252 if (digit < 10)
2253 *--pos = '0' + digit;
2254 else
2255 *--pos = 'a' + digit - 10;
2257 while (val != 0);
2259 if (is_negative)
2260 *--pos = '-';
2262 len = buffer + 65 - pos;
2263 if (len > size)
2265 size_t i;
2266 char *p = str;
2268 /* Copy the temporary buffer backwards up to the available number of
2269 * characters. Don't copy the negative sign if present. */
2271 if (is_negative)
2273 p++;
2274 size--;
2277 for (pos = buffer + 63, i = 0; i < size; i++)
2278 *p++ = *pos--;
2280 str[0] = '\0';
2281 MSVCRT_INVALID_PMT("str[size] is too small", MSVCRT_ERANGE);
2282 return MSVCRT_ERANGE;
2285 memcpy(str, pos, len);
2286 return 0;
2289 /*********************************************************************
2290 * _i64tow_s (MSVCRT.@)
2292 int CDECL MSVCRT__i64tow_s(__int64 value, MSVCRT_wchar_t *str, MSVCRT_size_t size, int radix)
2294 unsigned __int64 val;
2295 unsigned int digit;
2296 BOOL is_negative;
2297 MSVCRT_wchar_t buffer[65], *pos;
2298 size_t len;
2300 if (!MSVCRT_CHECK_PMT(str != NULL)) return MSVCRT_EINVAL;
2301 if (!MSVCRT_CHECK_PMT(size > 0)) return MSVCRT_EINVAL;
2302 if (!MSVCRT_CHECK_PMT(radix >= 2 && radix <= 36))
2304 str[0] = '\0';
2305 return MSVCRT_EINVAL;
2308 if (value < 0 && radix == 10)
2310 is_negative = TRUE;
2311 val = -value;
2313 else
2315 is_negative = FALSE;
2316 val = value;
2319 pos = buffer + 64;
2320 *pos = '\0';
2324 digit = val % radix;
2325 val /= radix;
2327 if (digit < 10)
2328 *--pos = '0' + digit;
2329 else
2330 *--pos = 'a' + digit - 10;
2332 while (val != 0);
2334 if (is_negative)
2335 *--pos = '-';
2337 len = buffer + 65 - pos;
2338 if (len > size)
2340 size_t i;
2341 MSVCRT_wchar_t *p = str;
2343 /* Copy the temporary buffer backwards up to the available number of
2344 * characters. Don't copy the negative sign if present. */
2346 if (is_negative)
2348 p++;
2349 size--;
2352 for (pos = buffer + 63, i = 0; i < size; i++)
2353 *p++ = *pos--;
2355 str[0] = '\0';
2356 MSVCRT_INVALID_PMT("str[size] is too small", MSVCRT_ERANGE);
2357 return MSVCRT_ERANGE;
2360 memcpy(str, pos, len * sizeof(MSVCRT_wchar_t));
2361 return 0;
2364 #define I10_OUTPUT_MAX_PREC 21
2365 /* Internal structure used by $I10_OUTPUT */
2366 struct _I10_OUTPUT_DATA {
2367 short pos;
2368 char sign;
2369 BYTE len;
2370 char str[I10_OUTPUT_MAX_PREC+1]; /* add space for '\0' */
2373 /*********************************************************************
2374 * $I10_OUTPUT (MSVCRT.@)
2375 * ld80 - long double (Intel 80 bit FP in 12 bytes) to be printed to data
2376 * prec - precision of part, we're interested in
2377 * flag - 0 for first prec digits, 1 for fractional part
2378 * data - data to be populated
2380 * return value
2381 * 0 if given double is NaN or INF
2382 * 1 otherwise
2384 * FIXME
2385 * Native sets last byte of data->str to '0' or '9', I don't know what
2386 * it means. Current implementation sets it always to '0'.
2388 int CDECL MSVCRT_I10_OUTPUT(MSVCRT__LDOUBLE ld80, int prec, int flag, struct _I10_OUTPUT_DATA *data)
2390 struct fpnum num;
2391 double d;
2392 char format[8];
2393 char buf[I10_OUTPUT_MAX_PREC+9]; /* 9 = strlen("0.e+0000") + '\0' */
2394 char *p;
2396 if ((ld80.x80[2] & 0x7fff) == 0x7fff)
2398 if (ld80.x80[0] == 0 && ld80.x80[1] == 0x80000000)
2399 strcpy( data->str, "1#INF" );
2400 else
2401 strcpy( data->str, (ld80.x80[1] & 0x40000000) ? "1#QNAN" : "1#SNAN" );
2402 data->pos = 1;
2403 data->sign = (ld80.x80[2] & 0x8000) ? '-' : ' ';
2404 data->len = strlen(data->str);
2405 return 0;
2408 num.sign = (ld80.x80[2] & 0x8000) ? -1 : 1;
2409 num.exp = (ld80.x80[2] & 0x7fff) - 0x3fff - 63;
2410 num.m = ld80.x80[0] | ((ULONGLONG)ld80.x80[1] << 32);
2411 num.mod = FP_ROUND_EVEN;
2412 fpnum_double( &num, &d );
2413 TRACE("(%lf %d %x %p)\n", d, prec, flag, data);
2415 if(d<0) {
2416 data->sign = '-';
2417 d = -d;
2418 } else
2419 data->sign = ' ';
2421 if(flag&1) {
2422 int exp = 1 + MSVCRT_floor(MSVCRT_log10(d));
2424 prec += exp;
2425 if(exp < 0)
2426 prec--;
2428 prec--;
2430 if(prec+1 > I10_OUTPUT_MAX_PREC)
2431 prec = I10_OUTPUT_MAX_PREC-1;
2432 else if(prec < 0) {
2433 d = 0.0;
2434 prec = 0;
2437 MSVCRT_sprintf(format, "%%.%dle", prec);
2438 MSVCRT_sprintf(buf, format, d);
2440 buf[1] = buf[0];
2441 data->pos = MSVCRT_atoi(buf+prec+3);
2442 if(buf[1] != '0')
2443 data->pos++;
2445 for(p = buf+prec+1; p>buf+1 && *p=='0'; p--);
2446 data->len = p-buf;
2448 memcpy(data->str, buf+1, data->len);
2449 data->str[data->len] = '\0';
2451 if(buf[1]!='0' && prec-data->len+1>0)
2452 memcpy(data->str+data->len+1, buf+data->len+1, prec-data->len+1);
2454 return 1;
2456 #undef I10_OUTPUT_MAX_PREC
2458 /*********************************************************************
2459 * memcmp (MSVCRT.@)
2461 int __cdecl memcmp(const void *ptr1, const void *ptr2, size_t n)
2463 const unsigned char *p1, *p2;
2465 for (p1 = ptr1, p2 = ptr2; n; n--, p1++, p2++)
2467 if (*p1 < *p2) return -1;
2468 if (*p1 > *p2) return 1;
2470 return 0;
2473 /*********************************************************************
2474 * memmove (MSVCRT.@)
2476 #ifdef WORDS_BIGENDIAN
2477 # define MERGE(w1, sh1, w2, sh2) ((w1 << sh1) | (w2 >> sh2))
2478 #else
2479 # define MERGE(w1, sh1, w2, sh2) ((w1 >> sh1) | (w2 << sh2))
2480 #endif
2481 void * __cdecl memmove(void *dst, const void *src, size_t n)
2483 unsigned char *d = dst;
2484 const unsigned char *s = src;
2485 int sh1;
2487 if (!n) return dst;
2489 if ((MSVCRT_size_t)dst - (MSVCRT_size_t)src >= n)
2491 for (; (MSVCRT_size_t)d % sizeof(MSVCRT_size_t) && n; n--) *d++ = *s++;
2493 sh1 = 8 * ((MSVCRT_size_t)s % sizeof(MSVCRT_size_t));
2494 if (!sh1)
2496 while (n >= sizeof(MSVCRT_size_t))
2498 *(MSVCRT_size_t*)d = *(MSVCRT_size_t*)s;
2499 s += sizeof(MSVCRT_size_t);
2500 d += sizeof(MSVCRT_size_t);
2501 n -= sizeof(MSVCRT_size_t);
2504 else if (n >= 2 * sizeof(MSVCRT_size_t))
2506 int sh2 = 8 * sizeof(MSVCRT_size_t) - sh1;
2507 MSVCRT_size_t x, y;
2509 s -= sh1 / 8;
2510 x = *(MSVCRT_size_t*)s;
2513 s += sizeof(MSVCRT_size_t);
2514 y = *(MSVCRT_size_t*)s;
2515 *(MSVCRT_size_t*)d = MERGE(x, sh1, y, sh2);
2516 d += sizeof(MSVCRT_size_t);
2518 s += sizeof(MSVCRT_size_t);
2519 x = *(MSVCRT_size_t*)s;
2520 *(MSVCRT_size_t*)d = MERGE(y, sh1, x, sh2);
2521 d += sizeof(MSVCRT_size_t);
2523 n -= 2 * sizeof(MSVCRT_size_t);
2524 } while (n >= 2 * sizeof(MSVCRT_size_t));
2525 s += sh1 / 8;
2527 while (n--) *d++ = *s++;
2528 return dst;
2530 else
2532 d += n;
2533 s += n;
2535 for (; (MSVCRT_size_t)d % sizeof(MSVCRT_size_t) && n; n--) *--d = *--s;
2537 sh1 = 8 * ((MSVCRT_size_t)s % sizeof(MSVCRT_size_t));
2538 if (!sh1)
2540 while (n >= sizeof(MSVCRT_size_t))
2542 s -= sizeof(MSVCRT_size_t);
2543 d -= sizeof(MSVCRT_size_t);
2544 *(MSVCRT_size_t*)d = *(MSVCRT_size_t*)s;
2545 n -= sizeof(MSVCRT_size_t);
2548 else if (n >= 2 * sizeof(MSVCRT_size_t))
2550 int sh2 = 8 * sizeof(MSVCRT_size_t) - sh1;
2551 MSVCRT_size_t x, y;
2553 s -= sh1 / 8;
2554 x = *(MSVCRT_size_t*)s;
2557 s -= sizeof(MSVCRT_size_t);
2558 y = *(MSVCRT_size_t*)s;
2559 d -= sizeof(MSVCRT_size_t);
2560 *(MSVCRT_size_t*)d = MERGE(y, sh1, x, sh2);
2562 s -= sizeof(MSVCRT_size_t);
2563 x = *(MSVCRT_size_t*)s;
2564 d -= sizeof(MSVCRT_size_t);
2565 *(MSVCRT_size_t*)d = MERGE(x, sh1, y, sh2);
2567 n -= 2 * sizeof(MSVCRT_size_t);
2568 } while (n >= 2 * sizeof(MSVCRT_size_t));
2569 s += sh1 / 8;
2571 while (n--) *--d = *--s;
2573 return dst;
2575 #undef MERGE
2577 /*********************************************************************
2578 * memcpy (MSVCRT.@)
2580 void * __cdecl memcpy(void *dst, const void *src, size_t n)
2582 return memmove(dst, src, n);
2585 /*********************************************************************
2586 * memset (MSVCRT.@)
2588 void* __cdecl memset(void *dst, int c, size_t n)
2590 volatile unsigned char *d = dst; /* avoid gcc optimizations */
2591 while (n--) *d++ = c;
2592 return dst;
2595 /*********************************************************************
2596 * strchr (MSVCRT.@)
2598 char* __cdecl strchr(const char *str, int c)
2602 if (*str == (char)c) return (char*)str;
2603 } while (*str++);
2604 return NULL;
2607 /*********************************************************************
2608 * strrchr (MSVCRT.@)
2610 char* __cdecl MSVCRT_strrchr(const char *str, int c)
2612 char *ret = NULL;
2613 do { if (*str == (char)c) ret = (char*)str; } while (*str++);
2614 return ret;
2617 /*********************************************************************
2618 * memchr (MSVCRT.@)
2620 void* __cdecl MSVCRT_memchr(const void *ptr, int c, MSVCRT_size_t n)
2622 const unsigned char *p = ptr;
2624 for (p = ptr; n; n--, p++) if (*p == c) return (void *)(ULONG_PTR)p;
2625 return NULL;
2628 /*********************************************************************
2629 * strcmp (MSVCRT.@)
2631 int __cdecl strcmp(const char *str1, const char *str2)
2633 while (*str1 && *str1 == *str2) { str1++; str2++; }
2634 if ((unsigned char)*str1 > (unsigned char)*str2) return 1;
2635 if ((unsigned char)*str1 < (unsigned char)*str2) return -1;
2636 return 0;
2639 /*********************************************************************
2640 * strncmp (MSVCRT.@)
2642 int __cdecl MSVCRT_strncmp(const char *str1, const char *str2, MSVCRT_size_t len)
2644 if (!len) return 0;
2645 while (--len && *str1 && *str1 == *str2) { str1++; str2++; }
2646 return (unsigned char)*str1 - (unsigned char)*str2;
2649 /*********************************************************************
2650 * _strnicmp_l (MSVCRT.@)
2652 int __cdecl MSVCRT__strnicmp_l(const char *s1, const char *s2,
2653 MSVCRT_size_t count, MSVCRT__locale_t locale)
2655 MSVCRT_pthreadlocinfo locinfo;
2656 int c1, c2;
2658 if(s1==NULL || s2==NULL)
2659 return MSVCRT__NLSCMPERROR;
2661 if(!count)
2662 return 0;
2664 if(!locale)
2665 locinfo = get_locinfo();
2666 else
2667 locinfo = locale->locinfo;
2669 if(!locinfo->lc_handle[MSVCRT_LC_CTYPE])
2671 do {
2672 if ((c1 = *s1++) >= 'A' && c1 <= 'Z')
2673 c1 -= 'A' - 'a';
2674 if ((c2 = *s2++) >= 'A' && c2 <= 'Z')
2675 c2 -= 'A' - 'a';
2676 }while(--count && c1 && c1==c2);
2678 return c1-c2;
2681 do {
2682 c1 = MSVCRT__tolower_l((unsigned char)*s1++, locale);
2683 c2 = MSVCRT__tolower_l((unsigned char)*s2++, locale);
2684 }while(--count && c1 && c1==c2);
2686 return c1-c2;
2689 /*********************************************************************
2690 * _stricmp_l (MSVCRT.@)
2692 int __cdecl MSVCRT__stricmp_l(const char *s1, const char *s2, MSVCRT__locale_t locale)
2694 return MSVCRT__strnicmp_l(s1, s2, -1, locale);
2697 /*********************************************************************
2698 * _strnicmp (MSVCRT.@)
2700 int __cdecl MSVCRT__strnicmp(const char *s1, const char *s2, MSVCRT_size_t count)
2702 return MSVCRT__strnicmp_l(s1, s2, count, NULL);
2705 /*********************************************************************
2706 * _stricmp (MSVCRT.@)
2708 int __cdecl MSVCRT__stricmp(const char *s1, const char *s2)
2710 return MSVCRT__strnicmp_l(s1, s2, -1, NULL);
2713 /*********************************************************************
2714 * strstr (MSVCRT.@)
2716 char* __cdecl MSVCRT_strstr(const char *haystack, const char *needle)
2718 MSVCRT_size_t i, j, len, needle_len, lps_len;
2719 BYTE lps[256];
2721 needle_len = strlen(needle);
2722 if (!needle_len) return (char*)haystack;
2723 lps_len = needle_len > ARRAY_SIZE(lps) ? ARRAY_SIZE(lps) : needle_len;
2725 lps[0] = 0;
2726 len = 0;
2727 i = 1;
2728 while (i < lps_len)
2730 if (needle[i] == needle[len]) lps[i++] = ++len;
2731 else if (len) len = lps[len-1];
2732 else lps[i++] = 0;
2735 i = j = 0;
2736 while (haystack[i])
2738 while (j < lps_len && haystack[i] && haystack[i] == needle[j])
2740 i++;
2741 j++;
2744 if (j == needle_len) return (char*)haystack + i - j;
2745 else if (j)
2747 if (j == ARRAY_SIZE(lps) && !MSVCRT_strncmp(haystack + i, needle + j, needle_len - j))
2748 return (char*)haystack + i - j;
2749 j = lps[j-1];
2751 else if (haystack[i]) i++;
2753 return NULL;
2756 /*********************************************************************
2757 * _memicmp_l (MSVCRT.@)
2759 int __cdecl MSVCRT__memicmp_l(const char *s1, const char *s2, MSVCRT_size_t len, MSVCRT__locale_t locale)
2761 int ret = 0;
2763 #if _MSVCR_VER == 0 || _MSVCR_VER >= 80
2764 if (!s1 || !s2)
2766 if (len)
2767 MSVCRT_INVALID_PMT(NULL, EINVAL);
2768 return len ? MSVCRT__NLSCMPERROR : 0;
2770 #endif
2772 while (len--)
2774 if ((ret = MSVCRT__tolower_l(*s1, locale) - MSVCRT__tolower_l(*s2, locale)))
2775 break;
2776 s1++;
2777 s2++;
2779 return ret;
2782 /*********************************************************************
2783 * _memicmp (MSVCRT.@)
2785 int __cdecl MSVCRT__memicmp(const char *s1, const char *s2, MSVCRT_size_t len)
2787 return MSVCRT__memicmp_l(s1, s2, len, NULL);
2790 /*********************************************************************
2791 * strcspn (MSVCRT.@)
2793 MSVCRT_size_t __cdecl MSVCRT_strcspn(const char *str, const char *reject)
2795 BOOL rejects[256];
2796 const char *p;
2798 memset(rejects, 0, sizeof(rejects));
2800 p = reject;
2801 while(*p)
2803 rejects[(unsigned char)*p] = TRUE;
2804 p++;
2807 p = str;
2808 while(*p && !rejects[(unsigned char)*p]) p++;
2809 return p - str;
2812 /*********************************************************************
2813 * strpbrk (MSVCRT.@)
2815 char* __cdecl MSVCRT_strpbrk(const char *str, const char *accept)
2817 for (; *str; str++) if (strchr( accept, *str )) return (char*)str;
2818 return NULL;
2821 /*********************************************************************
2822 * __strncnt (MSVCRT.@)
2824 MSVCRT_size_t __cdecl MSVCRT___strncnt(const char *str, MSVCRT_size_t size)
2826 MSVCRT_size_t ret = 0;
2828 #if _MSVCR_VER >= 140
2829 while (*str++ && size--)
2830 #else
2831 while (size-- && *str++)
2832 #endif
2834 ret++;
2837 return ret;
2841 #ifdef _CRTDLL
2842 /*********************************************************************
2843 * _strdec (CRTDLL.@)
2845 char * CDECL _strdec(const char *str1, const char *str2)
2847 return (char *)(str2 - 1);
2850 /*********************************************************************
2851 * _strinc (CRTDLL.@)
2853 char * CDECL _strinc(const char *str)
2855 return (char *)(str + 1);
2858 /*********************************************************************
2859 * _strnextc (CRTDLL.@)
2861 unsigned int CDECL _strnextc(const char *str)
2863 return (unsigned char)str[0];
2866 /*********************************************************************
2867 * _strninc (CRTDLL.@)
2869 char * CDECL _strninc(const char *str, size_t len)
2871 return (char *)(str + len);
2874 /*********************************************************************
2875 * _strspnp (CRTDLL.@)
2877 char * CDECL _strspnp( const char *str1, const char *str2)
2879 str1 += strspn( str1, str2 );
2880 return *str1 ? (char*)str1 : NULL;
2882 #endif