Piotr Caban : msvcrt: Added _gcvt_s implementation.

Alexandre Julliard julliard at winehq.org
Fri Aug 27 11:11:19 CDT 2010


Module: wine
Branch: master
Commit: 3a25d7d9aad35a28373cad6740741cdd777f51ef
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=3a25d7d9aad35a28373cad6740741cdd777f51ef

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Fri Aug 27 01:46:35 2010 +0200

msvcrt: Added _gcvt_s implementation.

---

 dlls/msvcr100/msvcr100.spec |    2 +-
 dlls/msvcr80/msvcr80.spec   |    2 +-
 dlls/msvcr90/msvcr90.spec   |    2 +-
 dlls/msvcrt/math.c          |   45 +++++++++++++++++++++++++++++++++++++++--
 dlls/msvcrt/msvcrt.h        |    2 +
 dlls/msvcrt/msvcrt.spec     |    2 +-
 dlls/msvcrt/tests/string.c  |   46 +++++++++++++++++++++++++++++++++++++++---
 7 files changed, 90 insertions(+), 11 deletions(-)

diff --git a/dlls/msvcr100/msvcr100.spec b/dlls/msvcr100/msvcr100.spec
index a1c5a37..a8cbbab 100644
--- a/dlls/msvcr100/msvcr100.spec
+++ b/dlls/msvcr100/msvcr100.spec
@@ -674,7 +674,7 @@
 @ varargs _fwscanf_l(ptr wstr ptr) msvcrt._fwscanf_l
 @ varargs _fwscanf_s_l(ptr wstr ptr) msvcrt._fwscanf_s_l
 @ cdecl _gcvt(double long str) msvcrt._gcvt
-@ stub _gcvt_s
+@ cdecl _gcvt_s(ptr long  double long) msvcrt._gcvt_s
 @ stub _get_current_locale
 @ stub _get_daylight
 @ stub _get_doserrno
diff --git a/dlls/msvcr80/msvcr80.spec b/dlls/msvcr80/msvcr80.spec
index a161b64..0a54876 100644
--- a/dlls/msvcr80/msvcr80.spec
+++ b/dlls/msvcr80/msvcr80.spec
@@ -515,7 +515,7 @@
 @ varargs _fwscanf_l(ptr wstr ptr) msvcrt._fwscanf_l
 @ varargs _fwscanf_s_l(ptr wstr ptr) msvcrt._fwscanf_s_l
 @ cdecl _gcvt(double long str) msvcrt._gcvt
-@ stub _gcvt_s
+@ cdecl _gcvt_s(ptr long  double long) msvcrt._gcvt_s
 @ stub _get_amblksiz
 @ stub _get_current_locale
 @ stub _get_daylight
diff --git a/dlls/msvcr90/msvcr90.spec b/dlls/msvcr90/msvcr90.spec
index d369331..ffdd84e 100644
--- a/dlls/msvcr90/msvcr90.spec
+++ b/dlls/msvcr90/msvcr90.spec
@@ -507,7 +507,7 @@
 @ varargs _fwscanf_l(ptr wstr ptr) msvcrt._fwscanf_l
 @ varargs _fwscanf_s_l(ptr wstr ptr) msvcrt._fwscanf_s_l
 @ cdecl _gcvt(double long str) msvcrt._gcvt
-@ stub _gcvt_s
+@ cdecl _gcvt_s(ptr long  double long) msvcrt._gcvt_s
 @ stub _get_amblksiz
 @ stub _get_current_locale
 @ stub _get_daylight
diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c
index 5a31ae1..4a3f65e 100644
--- a/dlls/msvcrt/math.c
+++ b/dlls/msvcrt/math.c
@@ -1196,15 +1196,54 @@ char * CDECL _fcvt( double number, int ndigits, int *decpt, int *sign )
 
 /***********************************************************************
  *		_gcvt  (MSVCRT.@)
- *
- * FIXME: uses both E and F.
  */
 char * CDECL _gcvt( double number, int ndigit, char *buff )
 {
-    sprintf(buff, "%.*E", ndigit, number);
+    if(!buff) {
+        *MSVCRT__errno() = MSVCRT_EINVAL;
+        return NULL;
+    }
+
+    if(ndigit < 0) {
+        *MSVCRT__errno() = MSVCRT_ERANGE;
+        return NULL;
+    }
+
+    MSVCRT_sprintf(buff, "%.*g", ndigit, number);
     return buff;
 }
 
+/***********************************************************************
+ *              _gcvt_s  (MSVCRT.@)
+ */
+int CDECL _gcvt_s(char *buff, MSVCRT_size_t size, double number, int digits)
+{
+    int len;
+
+    if(!buff) {
+        *MSVCRT__errno() = MSVCRT_EINVAL;
+        return MSVCRT_EINVAL;
+    }
+
+    if( digits<0 || digits>=size) {
+        if(size)
+            buff[0] = '\0';
+
+        *MSVCRT__errno() = MSVCRT_ERANGE;
+        return MSVCRT_ERANGE;
+    }
+
+    len = MSVCRT__scprintf("%.*g", digits, number);
+    if(len > size) {
+        buff[0] = '\0';
+        *MSVCRT__errno() = MSVCRT_ERANGE;
+        return MSVCRT_ERANGE;
+    }
+
+    MSVCRT_sprintf(buff, "%.*g", digits, number);
+    return 0;
+}
+
 #include <stdlib.h> /* div_t, ldiv_t */
 
 /*********************************************************************
diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h
index 363223d..86df133 100644
--- a/dlls/msvcrt/msvcrt.h
+++ b/dlls/msvcrt/msvcrt.h
@@ -743,6 +743,8 @@ MSVCRT_FILE*   __cdecl MSVCRT__wfdopen(int, const MSVCRT_wchar_t *);
 int            __cdecl MSVCRT_vsnprintf(char *str, MSVCRT_size_t len, const char *format, __ms_va_list valist);
 int            __cdecl MSVCRT_vsnwprintf(MSVCRT_wchar_t *str, MSVCRT_size_t len,
                                        const MSVCRT_wchar_t *format, __ms_va_list valist );
+int            __cdecl MSVCRT_sprintf(char*,const char*,...);
+int            __cdecl MSVCRT__scprintf(const char*,...);
 int            __cdecl MSVCRT_raise(int sig);
 
 typedef struct MSVCRT_tagLC_ID {
diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec
index 6d3e1dd..a7371a8 100644
--- a/dlls/msvcrt/msvcrt.spec
+++ b/dlls/msvcrt/msvcrt.spec
@@ -461,7 +461,7 @@
 @ varargs _fwscanf_l(ptr wstr ptr) MSVCRT__fwscanf_l
 @ varargs _fwscanf_s_l(ptr wstr ptr) MSVCRT__fwscanf_s_l
 @ cdecl _gcvt(double long str)
-# stub _gcvt_s
+@ cdecl _gcvt_s(ptr long  double long)
 # stub _get_doserrno
 # stub _get_environ
 # stub _get_errno
diff --git a/dlls/msvcrt/tests/string.c b/dlls/msvcrt/tests/string.c
index e2324b0..94c2fa3 100644
--- a/dlls/msvcrt/tests/string.c
+++ b/dlls/msvcrt/tests/string.c
@@ -58,6 +58,7 @@ static __int64 (__cdecl *p_strtoi64)(const char *, char **, int);
 static unsigned __int64 (__cdecl *p_strtoui64)(const char *, char **, int);
 static int (__cdecl *pwcstombs_s)(size_t*,char*,size_t,const wchar_t*,size_t);
 static int (__cdecl *pmbstowcs_s)(size_t*,wchar_t*,size_t,const char*,size_t);
+static errno_t (__cdecl *p_gcvt_s)(char*,size_t,double,int);
 static int *p__mb_cur_max;
 static unsigned char *p_mbctype;
 
@@ -1241,6 +1242,41 @@ static void test_mbstowcs(void)
     ok(!memcmp(mOut, mHiragana, sizeof(mHiragana)), "mOut = %s\n", mOut);
 }
 
+static void test_gcvt(void)
+{
+    char buf[1024], *res;
+    errno_t err;
+
+    if(!p_gcvt_s) {
+        win_skip("Skipping _gcvt tests\n");
+        return;
+    }
+
+    errno = 0;
+    res = _gcvt(1.2, -1, buf);
+    ok(res == NULL, "res != NULL\n");
+    ok(errno == ERANGE, "errno = %d\n", errno);
+
+    errno = 0;
+    res = _gcvt(1.2, 5, NULL);
+    ok(res == NULL, "res != NULL\n");
+    ok(errno == EINVAL, "errno = %d\n", errno);
+
+    res = gcvt(1.2, 5, buf);
+    ok(res == buf, "res != buf\n");
+    ok(!strcmp(buf, "1.2"), "buf = %s\n", buf);
+
+    buf[0] = 'x';
+    err = p_gcvt_s(buf, 5, 1.2, 10);
+    ok(err == ERANGE, "err = %d\n", err);
+    ok(buf[0] == '\0', "buf[0] = %c\n", buf[0]);
+
+    buf[0] = 'x';
+    err = p_gcvt_s(buf, 4, 123456, 2);
+    ok(err == ERANGE, "err = %d\n", err);
+    ok(buf[0] == '\0', "buf[0] = %c\n", buf[0]);
+}
+
 START_TEST(string)
 {
     char mem[100];
@@ -1261,10 +1297,11 @@ START_TEST(string)
     p_wcscpy_s = (void *)GetProcAddress( hMsvcrt,"wcscpy_s" );
     p_wcsupr_s = (void *)GetProcAddress( hMsvcrt,"_wcsupr_s" );
     p_strnlen = (void *)GetProcAddress( hMsvcrt,"strnlen" );
-    p_strtoi64 = (void *) GetProcAddress(hMsvcrt, "_strtoi64");
-    p_strtoui64 = (void *) GetProcAddress(hMsvcrt, "_strtoui64");
-    pmbstowcs_s = (void *) GetProcAddress(hMsvcrt, "mbstowcs_s");
-    pwcstombs_s = (void *) GetProcAddress(hMsvcrt, "wcstombs_s");
+    p_strtoi64 = (void *)GetProcAddress(hMsvcrt, "_strtoi64");
+    p_strtoui64 = (void *)GetProcAddress(hMsvcrt, "_strtoui64");
+    pmbstowcs_s = (void *)GetProcAddress(hMsvcrt, "mbstowcs_s");
+    pwcstombs_s = (void *)GetProcAddress(hMsvcrt, "wcstombs_s");
+    p_gcvt_s = (void *)GetProcAddress(hMsvcrt, "_gcvt_s");
 
     /* MSVCRT memcpy behaves like memmove for overlapping moves,
        MFC42 CString::Insert seems to rely on that behaviour */
@@ -1298,4 +1335,5 @@ START_TEST(string)
     test__strtoi64();
     test__strtod();
     test_mbstowcs();
+    test_gcvt();
 }




More information about the wine-cvs mailing list