Author: gschneider Date: Tue Aug 4 17:17:00 2009 New Revision: 42383
URL: http://svn.reactos.org/svn/reactos?rev=42383&view=rev Log: _ecvt: - Rewrite the function, getting rid of alloca and unneeded code parts - Relies on working sprintf, especially allows to detect the decimal point position independent of wanted precision - Fixes all msvcrt printf winetests
Removed: trunk/reactos/lib/sdk/crt/stdlib/ecvtbuf.c Modified: trunk/reactos/lib/sdk/crt/crt.rbuild trunk/reactos/lib/sdk/crt/stdlib/ecvt.c
Modified: trunk/reactos/lib/sdk/crt/crt.rbuild URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/sdk/crt/crt.rbuild?rev=... ============================================================================== --- trunk/reactos/lib/sdk/crt/crt.rbuild [iso-8859-1] (original) +++ trunk/reactos/lib/sdk/crt/crt.rbuild [iso-8859-1] Tue Aug 4 17:17:00 2009 @@ -317,7 +317,6 @@ <file>abort.c</file> <file>atexit.c</file> <file>ecvt.c</file> - <file>ecvtbuf.c</file> <file>errno.c</file> <file>fcvt.c</file> <file>fcvtbuf.c</file>
Modified: trunk/reactos/lib/sdk/crt/stdlib/ecvt.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/sdk/crt/stdlib/ecvt.c?r... ============================================================================== --- trunk/reactos/lib/sdk/crt/stdlib/ecvt.c [iso-8859-1] (original) +++ trunk/reactos/lib/sdk/crt/stdlib/ecvt.c [iso-8859-1] Tue Aug 4 17:17:00 2009 @@ -1,7 +1,12 @@ -/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ +/* + * PROJECT: ReactOS CRT + * LICENSE: See COPYING in the top level directory + * PURPOSE: CRT's ecvt + * FILE: lib/sdk/crt/stdlib/ecvt.c + * PROGRAMERS: Gregor Schneider (parts based on ecvtbuf.c by DJ Delorie) + */ + #include <precomp.h> - -char *ecvtbuf (double, int, int *, int *, char *);
/* * @implemented @@ -9,6 +14,98 @@ char * _ecvt (double value, int ndigits, int *decpt, int *sign) { - static char ecvt_buf[DBL_MAX_10_EXP + 10]; - return ecvtbuf (value, ndigits, decpt, sign, ecvt_buf); + char *ecvtbuf, *cvtbuf; + char *s, *d; + + s = cvtbuf = (char*)malloc(ndigits + 18); /* sign, dot, null, 15 for alignment */ + d = ecvtbuf = (char*)malloc(DBL_MAX_10_EXP + 10); + + *sign = 0; + *decpt = 0; + + if (cvtbuf == NULL || ecvtbuf == NULL) + { + return NULL; + } + + sprintf(cvtbuf, "%-+.*E", ndigits, value); + /* Treat special values */ + if (strncmp(s, "NaN", 3) == 0) + { + memcpy(ecvtbuf, s, 4); + } + else if (strncmp(s + 1, "Inf", 3) == 0) + { + memcpy(ecvtbuf, s, 5); + } + else + { + /* Set the sign */ + if (*s && *s == '-') + { + *sign = 1; + } + s++; + /* Copy the first digit */ + if (*s && *s != '.') + { + if (d - ecvtbuf < ndigits) + { + *d++ = *s++; + } + else + { + s++; + } + } + /* Skip the decimal point */ + if (*s && *s == '.') + { + s++; + } + /* Copy fractional digits */ + while (*s && *s != 'E') + { + if (d - ecvtbuf < ndigits) + { + *d++ = *s++; + } + else + { + s++; + } + } + /* Skip the exponent */ + if (*s && *s == 'E') + { + s++; + } + /* Set the decimal point to the exponent value plus the one digit we copied */ + *decpt = atoi(s) + 1; + /* Handle special decimal point cases */ + if (cvtbuf[1] == '0') + { + *decpt = 0; + } + if (ndigits < 1) + { + /* Need enhanced precision*/ + char* tbuf = (char*)malloc(ndigits + 18); + sprintf(tbuf, "%-+.*E", ndigits + 2, value); + if (tbuf[1] >= '5') + { + (*decpt)++; + } + free(tbuf); + } + /* Pad with zeroes */ + while (d - ecvtbuf < ndigits) + { + *d++ = '0'; + } + /* Terminate */ + *d = '\0'; + } + free(cvtbuf); + return ecvtbuf; }
Removed: trunk/reactos/lib/sdk/crt/stdlib/ecvtbuf.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/sdk/crt/stdlib/ecvtbuf.... ============================================================================== --- trunk/reactos/lib/sdk/crt/stdlib/ecvtbuf.c [iso-8859-1] (original) +++ trunk/reactos/lib/sdk/crt/stdlib/ecvtbuf.c (removed) @@ -1,108 +1,0 @@ -/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <float.h> -#include <malloc.h> -// #include <msvcrt/locale.h> - -void __ecvround (char *, char *, const char *, int *); - -void -__ecvround (char *numbuf, char *last_digit, const char *after_last, int *decpt) -{ - char *p; - int carry = 0; - - /* Do we have at all to round the last digit? */ - if (*after_last > '4') - { - p = last_digit; - carry = 1; - - /* Propagate the rounding through trailing '9' digits. */ - do { - int sum = *p + carry; - carry = sum > '9'; - *p-- = sum - carry * 10; - } while (carry && p >= numbuf); - - /* We have 9999999... which needs to be rounded to 100000.. */ - if (carry && p == numbuf) - { - *p = '1'; - *decpt += 1; - } - } -} - -char * -ecvtbuf (double value, int ndigits, int *decpt, int *sign, char *buf) -{ - static char INFINITY[] = "Infinity"; - char decimal = '.' /* localeconv()->decimal_point[0] */; - char *cvtbuf = (char *)_alloca (ndigits + 20); /* +3 for sign, dot, null; */ - /* two extra for rounding */ - /* 15 extra for alignment */ - char *s = cvtbuf, *d = buf; - - /* Produce two extra digits, so we could round properly. */ - sprintf (cvtbuf, "%-+.*E", ndigits + 2, value); - *decpt = 0; - - /* The sign. */ - if (*s++ == '-') - *sign = 1; - else - *sign = 0; - - /* Special values get special treatment. */ - if (strncmp (s, "Inf", 3) == 0) - { - /* SunOS docs says we have return "Infinity" for NDIGITS >= 8. */ - memcpy (buf, INFINITY, ndigits >= 8 ? 9 : 3); - if (ndigits < 8) - buf[3] = '\0'; - } - else if (strcmp (s, "NaN") == 0) - memcpy (buf, s, 4); - else - { - char *last_digit, *digit_after_last; - - /* Copy (the single) digit before the decimal. */ - while (*s && *s != decimal && d - buf < ndigits) - *d++ = *s++; - - /* If we don't see any exponent, here's our decimal point. */ - *decpt = d - buf; - if (*s) - s++; - - /* Copy the fraction digits. */ - while (*s && *s != 'E' && d - buf < ndigits) - *d++ = *s++; - - /* Remember the last digit copied and the one after it. */ - last_digit = d > buf ? d - 1 : d; - digit_after_last = s; - - /* Get past the E in exponent field. */ - while (*s && *s++ != 'E') - ; - - /* Adjust the decimal point by the exponent value. */ - *decpt += atoi (s); - - /* Pad with zeroes if needed. */ - while (d - buf < ndigits) - *d++ = '0'; - - /* Zero-terminate. */ - *d = '\0'; - - /* Round if necessary. */ - __ecvround (buf, last_digit, digit_after_last, decpt); - } - return buf; -}