Module: wine Branch: master Commit: 3a25d7d9aad35a28373cad6740741cdd777f51ef URL: http://source.winehq.org/git/wine.git/?a=commit;h=3a25d7d9aad35a28373cad6740...
Author: Piotr Caban piotr@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(); }