[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