[PATCH 2/3] msvcrt: Implement _fcvt_s.

Eryk Wieliczko ewdevel at gmail.com
Tue Dec 21 17:00:14 CST 2010


---
 dlls/msvcr100/msvcr100.spec |    2 +-
 dlls/msvcr80/msvcr80.spec   |    2 +-
 dlls/msvcr90/msvcr90.spec   |    2 +-
 dlls/msvcrt/math.c          |  133 ++++++++++++++++++++++++++++++++++++++++++-
 dlls/msvcrt/msvcrt.spec     |    2 +-
 5 files changed, 135 insertions(+), 6 deletions(-)

diff --git a/dlls/msvcr100/msvcr100.spec b/dlls/msvcr100/msvcr100.spec
index 82606e2..c15ecfd 100644
--- a/dlls/msvcr100/msvcr100.spec
+++ b/dlls/msvcr100/msvcr100.spec
@@ -606,7 +606,7 @@
 @ stub _fclose_nolock
 @ cdecl _fcloseall() msvcrt._fcloseall
 @ cdecl _fcvt(double long ptr ptr) msvcrt._fcvt
-@ stub _fcvt_s
+@ cdecl _fcvt_s(str long double long ptr ptr) msvcrt._fcvt_s
 @ cdecl _fdopen(long str) msvcrt._fdopen
 @ stub _fflush_nolock
 @ cdecl _fgetchar() msvcrt._fgetchar
diff --git a/dlls/msvcr80/msvcr80.spec b/dlls/msvcr80/msvcr80.spec
index e54eea6..49e51c1 100644
--- a/dlls/msvcr80/msvcr80.spec
+++ b/dlls/msvcr80/msvcr80.spec
@@ -447,7 +447,7 @@
 @ stub _fclose_nolock
 @ cdecl _fcloseall() msvcrt._fcloseall
 @ cdecl _fcvt(double long ptr ptr) msvcrt._fcvt
-@ stub _fcvt_s
+@ cdecl _fcvt_s(str long double long ptr ptr) msvcrt._fcvt_s
 @ cdecl _fdopen(long str) msvcrt._fdopen
 @ stub _fflush_nolock
 @ cdecl _fgetchar() msvcrt._fgetchar
diff --git a/dlls/msvcr90/msvcr90.spec b/dlls/msvcr90/msvcr90.spec
index 5baee98..480a544 100644
--- a/dlls/msvcr90/msvcr90.spec
+++ b/dlls/msvcr90/msvcr90.spec
@@ -439,7 +439,7 @@
 @ stub _fclose_nolock
 @ cdecl _fcloseall() msvcrt._fcloseall
 @ cdecl _fcvt(double long ptr ptr) msvcrt._fcvt
-@ stub _fcvt_s
+@ cdecl _fcvt_s(str long double long ptr ptr) msvcrt._fcvt_s
 @ cdecl _fdopen(long str) msvcrt._fdopen
 @ stub _fflush_nolock
 @ cdecl _fgetchar() msvcrt._fgetchar
diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c
index d2110cb..319b211 100644
--- a/dlls/msvcrt/math.c
+++ b/dlls/msvcrt/math.c
@@ -1127,9 +1127,9 @@ int CDECL _ecvt_s( char *buffer, MSVCRT_size_t length, double number, int ndigit
     /* special case - inf */
     if(number == HUGE_VAL || number == -HUGE_VAL)
     {
-        memset(buffer, '0', ndigits);
+        memset(buffer, '0', max(ndigits, 0));
         memcpy(buffer, infret, min(ndigits, sizeof(infret) - 1 ) );
-        buffer[ndigits] = '\0';
+        buffer[max(ndigits, 0)] = '\0';
         (*decpt) = 1;
         if(number == -HUGE_VAL)
             (*sign) = 1;
@@ -1253,6 +1253,135 @@ char * CDECL _fcvt( double number, int ndigits, int *decpt, int *sign )
     return first;
 }
 
+/*********************************************************************
+ *		_fcvt_s (MSVCRT.@)
+ */
+int CDECL _fcvt_s( char *buffer, MSVCRT_size_t length, double number, int ndigits, int *decpt, int *sign )
+{
+    int stop, dec1, dec2, allocsize;
+    char *ptr1, *ptr2, *first;
+    char *buf, *buf2;
+    const char infret[] = "1#INF";
+
+    if(!MSVCRT_CHECK_PMT(buffer != NULL) || !MSVCRT_CHECK_PMT(decpt != NULL) || !MSVCRT_CHECK_PMT(sign != NULL))
+    {
+        *MSVCRT__errno() = MSVCRT_EINVAL;
+        return MSVCRT_EINVAL;
+    }
+    if(!MSVCRT_CHECK_PMT(length > 2) || !MSVCRT_CHECK_PMT(ndigits < (int)length - 1))
+    {
+        *MSVCRT__errno() = MSVCRT_ERANGE;
+        return MSVCRT_ERANGE;
+    }
+
+    /* special case - inf */
+    if(number == HUGE_VAL || number == -HUGE_VAL)
+    {
+        memset(buffer, '0', max(ndigits + 1, 0));
+        memcpy(buffer, infret, min(ndigits + 1, sizeof(infret) - 1 ) );
+        buffer[max(ndigits + 1, 0)] = '\0';
+        (*decpt) = 1;
+        if(number == -HUGE_VAL)
+            (*sign) = 1;
+        else
+            (*sign) = 0;
+        return 0;
+    }
+    allocsize = max( log10( number ) + ndigits + 10, 10 );
+    buf = MSVCRT_malloc( allocsize );
+    buf2 = MSVCRT_malloc( allocsize );
+
+    if (number < 0)
+    {
+        *sign = 1;
+        number = -number;
+    }
+    else
+        *sign = 0;
+
+    snprintf(buf, allocsize, "%.*f", ndigits < 0 ? 0 : ndigits, number);
+    ptr1 = buf;
+    ptr2 = buf2;
+    first = NULL;
+    dec1 = 0;
+    dec2 = 0;
+
+    /* For numbers below the requested resolution, work out where
+       the decimal point will be rather than finding it in the string */
+    if (number < 1.0 && number > 0.0)
+    {
+        dec2 = log10(number + 1e-10);
+        if (-dec2 <= ndigits)
+            dec2 = 0;
+    }
+
+    /* If requested digits is zero or less, we will need to truncate
+     * the returned string */
+    if (ndigits < 1)
+        stop = strlen(buf) + ndigits;
+    else
+        stop = strlen(buf);
+
+    while (*ptr1 == '0')
+        ptr1++; /* Skip leading zeroes */
+    while (*ptr1 != '\0' && *ptr1 != '.')
+    {
+        if (!first)
+            first = ptr2;
+        if ((ptr1 - buf) < stop)
+            *ptr2++ = *ptr1++;
+        else
+            ptr1++;
+        dec1++;
+    }
+
+    if (ndigits > 0)
+    {
+        ptr1++;
+        if (!first)
+        {
+            while (*ptr1 == '0')
+            { /* Process leading zeroes */
+                *ptr2++ = *ptr1++;
+                 dec1--;
+            }
+        }
+        while (*ptr1 != '\0')
+        {
+            if (!first)
+                first = ptr2;
+            *ptr2++ = *ptr1++;
+        }
+    }
+
+    *ptr2 = '\0';
+
+    /* We never found a non-zero digit, then our number is either
+     * smaller than the requested precision, or 0.0 */
+    if (!first)
+    {
+        if (number > 0.0)
+            first = ptr2;
+        else
+        {
+            first = buf2;
+            dec1 = 0;
+        }
+    }
+
+    *decpt = dec2 ? dec2 : dec1;
+
+    buffer[0] = '\0';
+    if( *(decpt) + ndigits > 0 )
+    {
+        memcpy( buffer, first, *decpt + ndigits );
+        buffer[*decpt + ndigits] = '\0';
+    }
+    MSVCRT_free( buf );
+    MSVCRT_free( buf2 );
+    return 0;
+}
+
 /***********************************************************************
  *		_gcvt  (MSVCRT.@)
  */
diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec
index ba8c9ea..90c774b 100644
--- a/dlls/msvcrt/msvcrt.spec
+++ b/dlls/msvcrt/msvcrt.spec
@@ -400,7 +400,7 @@
 # stub _expand_dbg
 @ cdecl _fcloseall() MSVCRT__fcloseall
 @ cdecl _fcvt(double long ptr ptr)
-# stub _fcvt_s
+@ cdecl _fcvt_s(str long double long ptr ptr)
 @ cdecl _fdopen(long str) MSVCRT__fdopen
 @ cdecl _fgetchar()
 @ cdecl _fgetwchar()
-- 
1.7.0.4




More information about the wine-patches mailing list