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?…
==============================================================================
--- 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;
-}