Daniel Lehman : msvcr120: Add fesetexceptflag.

Alexandre Julliard julliard at winehq.org
Fri Mar 12 14:36:15 CST 2021


Module: wine
Branch: master
Commit: 5fd512504ce4e2518aba34ad264e03703cecefb3
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=5fd512504ce4e2518aba34ad264e03703cecefb3

Author: Daniel Lehman <dlehman25 at gmail.com>
Date:   Thu Mar 11 23:12:08 2021 -0800

msvcr120: Add fesetexceptflag.

Signed-off-by: Daniel Lehman <dlehman25 at gmail.com>
Signed-off-by: Piotr Caban <piotr at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 .../api-ms-win-crt-runtime-l1-1-0.spec             |  2 +-
 dlls/msvcr120/msvcr120.spec                        |  2 +-
 dlls/msvcr120/tests/msvcr120.c                     | 82 ++++++++++++++++++++--
 dlls/msvcr120_app/msvcr120_app.spec                |  2 +-
 dlls/msvcrt/math.c                                 | 17 +++++
 dlls/ucrtbase/ucrtbase.spec                        |  2 +-
 include/msvcrt/fenv.h                              |  3 +
 7 files changed, 101 insertions(+), 9 deletions(-)

diff --git a/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec b/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec
index 66c2d8cc264..1440e96db17 100644
--- a/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec
+++ b/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec
@@ -93,7 +93,7 @@
 @ cdecl fegetround() ucrtbase.fegetround
 @ stub feholdexcept
 @ cdecl fesetenv(ptr) ucrtbase.fesetenv
-@ stub fesetexceptflag
+@ cdecl fesetexceptflag(ptr long) ucrtbase.fesetexceptflag
 @ cdecl fesetround(long) ucrtbase.fesetround
 @ cdecl fetestexcept(long) ucrtbase.fetestexcept
 @ cdecl perror(str) ucrtbase.perror
diff --git a/dlls/msvcr120/msvcr120.spec b/dlls/msvcr120/msvcr120.spec
index 27ae5a930f6..7719bc662e0 100644
--- a/dlls/msvcr120/msvcr120.spec
+++ b/dlls/msvcr120/msvcr120.spec
@@ -2152,7 +2152,7 @@
 @ stub feraiseexcept
 @ cdecl ferror(ptr)
 @ cdecl fesetenv(ptr)
-@ stub fesetexceptflag
+@ cdecl fesetexceptflag(ptr long)
 @ cdecl fesetround(long)
 @ cdecl fetestexcept(long)
 @ stub feupdateenv
diff --git a/dlls/msvcr120/tests/msvcr120.c b/dlls/msvcr120/tests/msvcr120.c
index 537e9077402..9104cfcd447 100644
--- a/dlls/msvcr120/tests/msvcr120.c
+++ b/dlls/msvcr120/tests/msvcr120.c
@@ -182,6 +182,7 @@ static int (CDECL *p_fegetenv)(fenv_t*);
 static int (CDECL *p_fesetenv)(const fenv_t*);
 static int (CDECL *p_fegetround)(void);
 static int (CDECL *p_fesetround)(int);
+static int (CDECL *p_fesetexceptflag)(const fexcept_t*,int);
 static int (CDECL *p_fetestexcept)(int);
 static int (CDECL *p__clearfp)(void);
 static _locale_t (__cdecl *p_wcreate_locale)(int, const wchar_t *);
@@ -258,6 +259,7 @@ static BOOL init(void)
     SET(p_fesetenv, "fesetenv");
     SET(p_fegetround, "fegetround");
     SET(p_fesetround, "fesetround");
+    SET(p_fesetexceptflag, "fesetexceptflag");
     SET(p_fetestexcept, "fetestexcept");
 
     SET(p__clearfp, "_clearfp");
@@ -799,7 +801,31 @@ static void test_feenv(void)
         FE_INVALID,
         FE_ALL_EXCEPT,
     };
+    static const struct {
+        fexcept_t except;
+        unsigned int flag;
+        unsigned int get;
+        fexcept_t expect;
+    } tests2[] = {
+        /* except                   flag                     get             expect */
+        { 0,                        0,                       0,              0 },
+        { FE_ALL_EXCEPT,            FE_INEXACT,              0,              0 },
+        { FE_ALL_EXCEPT,            FE_INEXACT,              FE_ALL_EXCEPT,  FE_INEXACT },
+        { FE_ALL_EXCEPT,            FE_INEXACT,              FE_INEXACT,     FE_INEXACT },
+        { FE_ALL_EXCEPT,            FE_INEXACT,              FE_OVERFLOW,    0 },
+        { FE_ALL_EXCEPT,            FE_ALL_EXCEPT,           FE_ALL_EXCEPT,  FE_ALL_EXCEPT },
+        { FE_ALL_EXCEPT,            FE_ALL_EXCEPT,           FE_INEXACT,     FE_INEXACT },
+        { FE_ALL_EXCEPT,            FE_ALL_EXCEPT,           0,              0 },
+        { FE_ALL_EXCEPT,            FE_ALL_EXCEPT,           ~0,             FE_ALL_EXCEPT },
+        { FE_ALL_EXCEPT,            FE_ALL_EXCEPT,           ~FE_ALL_EXCEPT, 0 },
+        { FE_INEXACT,               FE_ALL_EXCEPT,           FE_ALL_EXCEPT,  FE_INEXACT },
+        { FE_INEXACT,               FE_UNDERFLOW,            FE_ALL_EXCEPT,  0 },
+        { FE_UNDERFLOW,             FE_INEXACT,              FE_ALL_EXCEPT,  0 },
+        { FE_INEXACT|FE_UNDERFLOW,  FE_UNDERFLOW,            FE_ALL_EXCEPT,  FE_UNDERFLOW },
+        { FE_UNDERFLOW,             FE_INEXACT|FE_UNDERFLOW, FE_ALL_EXCEPT,  FE_UNDERFLOW },
+    };
     fenv_t env, env2;
+    fexcept_t except;
     int i, ret, flags;
 
     p__clearfp();
@@ -819,16 +845,37 @@ static void test_feenv(void)
     ret = p_fegetround();
     ok(ret == FE_TONEAREST, "Got unexpected round mode %#x.\n", ret);
 
+    if(0) { /* crash on windows */
+        p_fesetexceptflag(NULL, FE_ALL_EXCEPT);
+    }
+    except = FE_ALL_EXCEPT;
+    ret = p_fesetexceptflag(&except, FE_INEXACT|FE_UNDERFLOW);
+    ok(!ret, "fesetexceptflag returned %x\n", ret);
+    except = p_fetestexcept(FE_ALL_EXCEPT);
+    ok(except == (FE_INEXACT|FE_UNDERFLOW), "expected %x, got %lx\n", FE_INEXACT|FE_UNDERFLOW, except);
+
+    /* no crash, but no-op */
+    ret = p_fesetexceptflag(NULL, 0);
+    ok(!ret, "fesetexceptflag returned %x\n", ret);
+    except = p_fetestexcept(FE_ALL_EXCEPT);
+    ok(except == (FE_INEXACT|FE_UNDERFLOW), "expected %x, got %lx\n", FE_INEXACT|FE_UNDERFLOW, except);
+
+    /* zero clears all */
+    except = 0;
+    ret = p_fesetexceptflag(&except, FE_ALL_EXCEPT);
+    ok(!ret, "fesetexceptflag returned %x\n", ret);
+    except = p_fetestexcept(FE_ALL_EXCEPT);
+    ok(!except, "expected 0, got %lx\n", except);
+
     ret = p_fetestexcept(FE_ALL_EXCEPT);
     ok(!ret, "fetestexcept returned %x\n", ret);
 
     flags = 0;
+    /* adding bits with flags */
     for(i=0; i<ARRAY_SIZE(tests); i++) {
-        ret = p_fegetenv(&env);
-        ok(!ret, "Test %d: fegetenv returned %x\n", i, ret);
-        env._Fe_stat |= tests[i];
-        ret = p_fesetenv(&env);
-        ok(!ret, "Test %d: fesetenv returned %x\n", i, ret);
+        except = FE_ALL_EXCEPT;
+        ret = p_fesetexceptflag(&except, tests[i]);
+        ok(!ret, "Test %d: fesetexceptflag returned %x\n", i, ret);
 
         ret = p_fetestexcept(tests[i]);
         ok(ret == tests[i], "Test %d: expected %x, got %x\n", i, tests[i], ret);
@@ -837,6 +884,31 @@ static void test_feenv(void)
         ret = p_fetestexcept(FE_ALL_EXCEPT);
         ok(ret == flags, "Test %d: expected %x, got %x\n", i, flags, ret);
     }
+
+    p__clearfp();
+    /* setting bits with except */
+    for(i=0; i<ARRAY_SIZE(tests); i++) {
+        except = tests[i];
+        ret = p_fesetexceptflag(&except, FE_ALL_EXCEPT);
+        ok(!ret, "Test %d: fesetexceptflag returned %x\n", i, ret);
+
+        ret = p_fetestexcept(tests[i]);
+        ok(ret == tests[i], "Test %d: expected %x, got %x\n", i, tests[i], ret);
+
+        ret = p_fetestexcept(FE_ALL_EXCEPT);
+        ok(ret == tests[i], "Test %d: expected %x, got %x\n", i, tests[i], ret);
+    }
+
+    for(i=0; i<ARRAY_SIZE(tests2); i++) {
+        p__clearfp();
+
+        except = tests2[i].except;
+        ret = p_fesetexceptflag(&except, tests2[i].flag);
+        ok(!ret, "Test %d: fesetexceptflag returned %x\n", i, ret);
+
+        ret = p_fetestexcept(tests2[i].get);
+        ok(ret == tests2[i].expect, "Test %d: expected %lx, got %x\n", i, tests2[i].expect, ret);
+    }
     p__clearfp();
 }
 
diff --git a/dlls/msvcr120_app/msvcr120_app.spec b/dlls/msvcr120_app/msvcr120_app.spec
index daee644d965..24d98427acf 100644
--- a/dlls/msvcr120_app/msvcr120_app.spec
+++ b/dlls/msvcr120_app/msvcr120_app.spec
@@ -1818,7 +1818,7 @@
 @ stub feraiseexcept
 @ cdecl ferror(ptr) msvcr120.ferror
 @ cdecl fesetenv(ptr) msvcr120.fesetenv
-@ stub fesetexceptflag
+@ cdecl fesetexceptflag(ptr long) msvcr120.fesetexceptflag
 @ cdecl fesetround(long) msvcr120.fesetround
 @ cdecl fetestexcept(long) msvcr120.fetestexcept
 @ stub feupdateenv
diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c
index 6c1d665c843..16ff50f0334 100644
--- a/dlls/msvcrt/math.c
+++ b/dlls/msvcrt/math.c
@@ -2222,6 +2222,23 @@ int CDECL fetestexcept(int flags)
 {
     return _statusfp() & flags;
 }
+
+/*********************************************************************
+ *      fesetexceptflag (MSVCR120.@)
+ */
+int CDECL fesetexceptflag(const fexcept_t *status, int excepts)
+{
+    fenv_t env;
+
+    if(!excepts)
+        return 0;
+
+    fegetenv(&env);
+    excepts &= FE_ALL_EXCEPT;
+    env._Fe_stat &= ~excepts;
+    env._Fe_stat |= (*status & excepts);
+    return fesetenv(&env);
+}
 #endif
 
 #if _MSVCR_VER>=140
diff --git a/dlls/ucrtbase/ucrtbase.spec b/dlls/ucrtbase/ucrtbase.spec
index d40df5e0efc..cd012aa0ab9 100644
--- a/dlls/ucrtbase/ucrtbase.spec
+++ b/dlls/ucrtbase/ucrtbase.spec
@@ -2294,7 +2294,7 @@
 @ cdecl feof(ptr)
 @ cdecl ferror(ptr)
 @ cdecl fesetenv(ptr)
-@ stub fesetexceptflag
+@ cdecl fesetexceptflag(ptr long)
 @ cdecl fesetround(long)
 @ cdecl fetestexcept(long)
 @ cdecl fflush(ptr)
diff --git a/include/msvcrt/fenv.h b/include/msvcrt/fenv.h
index 3dcbcf0b8fe..6396bd688f3 100644
--- a/include/msvcrt/fenv.h
+++ b/include/msvcrt/fenv.h
@@ -30,10 +30,13 @@ typedef struct
     __msvcrt_ulong _Fe_stat;
 } fenv_t;
 
+typedef __msvcrt_ulong fexcept_t;
+
 _ACRTIMP int __cdecl fegetenv(fenv_t*);
 _ACRTIMP int __cdecl fesetenv(const fenv_t*);
 _ACRTIMP int __cdecl fegetround(void);
 _ACRTIMP int __cdecl fesetround(int);
+_ACRTIMP int __cdecl fesetexceptflag(const fexcept_t*, int);
 _ACRTIMP int __cdecl fetestexcept(int);
 
 #ifdef __cplusplus




More information about the wine-cvs mailing list