Piotr Caban : msvcrt: Fix Inf and NaN handling in printf function.

Alexandre Julliard julliard at winehq.org
Mon Sep 16 16:57:23 CDT 2013


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

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Mon Sep 16 15:05:16 2013 +0200

msvcrt: Fix Inf and NaN handling in printf function.

---

 dlls/msvcrt/printf.h       |   39 ++++++++++++++++++++++++++++++++++++++-
 dlls/msvcrt/tests/printf.c |   38 +++++++++++++++++++++++++++++++++++++-
 2 files changed, 75 insertions(+), 2 deletions(-)

diff --git a/dlls/msvcrt/printf.h b/dlls/msvcrt/printf.h
index 0fe27f7..dd36f59 100644
--- a/dlls/msvcrt/printf.h
+++ b/dlls/msvcrt/printf.h
@@ -537,6 +537,27 @@ int FUNC_NAME(pf_printf)(FUNC_NAME(puts_clbk) pf_puts, void *puts_ctx, const API
             int len = flags.Precision + 10;
             double val = pf_args(args_ctx, pos, VT_R8, valist).get_double;
             int r;
+            BOOL inf = FALSE, nan = FALSE;
+
+            if(isinf(val))
+                inf = TRUE;
+            else if(isnan(val))
+                nan = TRUE; /* FIXME: NaN value may be displayed as #IND or #QNAN */
+
+            if(inf || nan) {
+                if(nan || val<0)
+                    flags.Sign = '-';
+
+                if(flags.Format=='g' || flags.Format=='G')
+                    val = 1.1234; /* fraction will be overwritten with #INF or #IND string */
+                else
+                    val = 1;
+
+                if(flags.Format=='a') {
+                    if(flags.Precision==-1)
+                        flags.Precision = 6; /* strlen("#INF00") */
+                }
+            }
 
             if(flags.Format=='f') {
                 if(val>-10.0 && val<10.0)
@@ -566,9 +587,25 @@ int FUNC_NAME(pf_printf)(FUNC_NAME(puts_clbk) pf_puts, void *puts_ctx, const API
                 FUNC_NAME(pf_fixup_exponent)(tmp);
 
             decimal_point = strchr(tmp, '.');
-            if(decimal_point)
+            if(decimal_point) {
                 *decimal_point = *locinfo->lconv->decimal_point;
 
+                if(inf || nan) {
+                    static const char inf_str[] = "#INF";
+                    static const char ind_str[] = "#IND";
+
+                    for(i=1; i<=sizeof(inf ? inf_str : ind_str); i++) {
+                        if(decimal_point[i]<'0' || decimal_point[i]>'9')
+                            break;
+
+                        decimal_point[i] = inf ? inf_str[i-1] : ind_str[i-1];
+                    }
+
+                    if(i!=sizeof(inf_str) && i!=1)
+                        decimal_point[i-1]++;
+                }
+            }
+
             len = strlen(tmp);
             i = FUNC_NAME(pf_fill)(pf_puts, puts_ctx, len, &flags, TRUE);
             if(i < 0)
diff --git a/dlls/msvcrt/tests/printf.c b/dlls/msvcrt/tests/printf.c
index e61ca5f..24bc401 100644
--- a/dlls/msvcrt/tests/printf.c
+++ b/dlls/msvcrt/tests/printf.c
@@ -27,6 +27,7 @@
  
 #include <stdio.h>
 #include <errno.h>
+#include <math.h>
 
 #include "windef.h"
 #include "winbase.h"
@@ -81,7 +82,7 @@ static void test_sprintf( void )
 {
     char buffer[100];
     const char *format;
-    double pnumber=789456123;
+    double pnumber=789456123, inf, nan;
     int x, r;
     WCHAR wide[] = { 'w','i','d','e',0};
 
@@ -639,6 +640,41 @@ static void test_sprintf( void )
     ok(!strcmp(buffer,"123"), "failed: \"%s\"\n", buffer);
     r = sprintf(buffer, format, 0x12345);
     ok(!strcmp(buffer,"2345"), "failed \"%s\"\n", buffer);
+
+    nan = 0.0;
+    inf = 1.0/nan;
+    nan = sqrt(-1);
+    format = "%lf";
+    r = sprintf(buffer, format, nan);
+    ok(r==9, "r = %d\n", r);
+    ok(!strcmp(buffer, "-1.#IND00"), "failed: \"%s\"\n", buffer);
+    r = sprintf(buffer, format, inf);
+    ok(r==8, "r = %d\n", r);
+    ok(!strcmp(buffer, "1.#INF00"), "failed: \"%s\"\n", buffer);
+
+    format = "%le";
+    r = sprintf(buffer, format, nan);
+    ok(r==14, "r = %d\n", r);
+    ok(!strcmp(buffer, "-1.#IND00e+000"), "failed: \"%s\"\n", buffer);
+    r = sprintf(buffer, format, inf);
+    ok(r==13, "r = %d\n", r);
+    ok(!strcmp(buffer, "1.#INF00e+000"), "failed: \"%s\"\n", buffer);
+
+    format = "%lg";
+    r = sprintf(buffer, format, nan);
+    ok(r==7, "r = %d\n", r);
+    ok(!strcmp(buffer, "-1.#IND"), "failed: \"%s\"\n", buffer);
+    r = sprintf(buffer, format, inf);
+    ok(r==6, "r = %d\n", r);
+    ok(!strcmp(buffer, "1.#INF"), "failed: \"%s\"\n", buffer);
+
+    format = "%010.2lf";
+    r = sprintf(buffer, format, nan);
+    ok(r==10, "r = %d\n", r);
+    ok(!strcmp(buffer, "-000001.#J"), "failed: \"%s\"\n", buffer);
+    r = sprintf(buffer, format, inf);
+    ok(r==10, "r = %d\n", r);
+    ok(!strcmp(buffer, "0000001.#J"), "failed: \"%s\"\n", buffer);
 }
 
 static void test_swprintf( void )




More information about the wine-cvs mailing list