Signed-off-by: Daniel Lehman dlehman25@gmail.com --- .../api-ms-win-crt-runtime-l1-1-0.spec | 2 +- dlls/msvcr120/msvcr120.spec | 2 +- dlls/msvcr120/tests/msvcr120.c | 50 ++++++++++++++++++- dlls/msvcr120_app/msvcr120_app.spec | 2 +- dlls/msvcrt/math.c | 20 ++++++++ dlls/ucrtbase/ucrtbase.spec | 2 +- include/msvcrt/fenv.h | 1 + 7 files changed, 74 insertions(+), 5 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 1d0b6e06b7c..610af8e436b 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 d9628883f34..430124740bb 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 a34c336d94d..5266e73a3a0 100644 --- a/dlls/msvcr120/tests/msvcr120.c +++ b/dlls/msvcr120/tests/msvcr120.c @@ -183,6 +183,7 @@ static int (CDECL *p_fesetenv)(const fenv_t*); static int (CDECL *p_fegetround)(void); static int (CDECL *p_fesetround)(int); static int (CDECL *p_fegetexceptflag)(fexcept_t*,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 *); @@ -260,6 +261,7 @@ static BOOL init(void) SET(p_fegetround, "fegetround"); SET(p_fesetround, "fesetround"); SET(p_fegetexceptflag, "fegetexceptflag"); + SET(p_fesetexceptflag, "fesetexceptflag"); SET(p_fetestexcept, "fetestexcept");
SET(p__clearfp, "_clearfp"); @@ -808,6 +810,15 @@ static void test_feenv(void) { FE_ALL_EXCEPT, ~0, FE_ALL_EXCEPT }, { FE_ALL_EXCEPT, ~FE_ALL_EXCEPT, 0 }, }; + static const unsigned long tests2[] = { + 0, + FE_INEXACT, + FE_UNDERFLOW, + FE_OVERFLOW, + FE_DIVBYZERO, + FE_INVALID, + FE_ALL_EXCEPT, + }; fenv_t env, env2; fexcept_t except; int i, ret; @@ -829,8 +840,10 @@ static void test_feenv(void) ret = p_fegetround(); ok(ret == FE_TONEAREST, "Got unexpected round mode %#x.\n", ret);
- if(0) /* crashes on windows */ + if(0) { /* crashes on windows */ p_fegetexceptflag(NULL, 0); + p_fesetexceptflag(NULL, FE_ALL_EXCEPT); + }
for(i=0; i<ARRAY_SIZE(tests); i++) { env._Fe_stat = tests[i].set; @@ -846,6 +859,41 @@ static void test_feenv(void) ok(except == tests[i].expect, "expected %lx, got %lx\n", tests[i].expect, except); }
+ ret = p_fesetexceptflag(NULL, 0); + ok(!ret, "fesetexceptflag returned %x\n", ret); + + for(i=0; i<ARRAY_SIZE(tests2); i++) { + p__clearfp(); + + except = FE_ALL_EXCEPT; + ret = p_fesetexceptflag(&except, tests2[i]); + ok(!ret, "fesetexceptflag returned %x\n", ret); + + except = p_fetestexcept(tests2[i]); + ok(except == tests2[i], "expected %lx, got %lx\n", tests2[i], except); + + p__clearfp(); + + except = tests2[i]; + ret = p_fesetexceptflag(&except, FE_ALL_EXCEPT); + ok(!ret, "fesetexceptflag returned %x\n", ret); + + except = p_fetestexcept(tests2[i]); + ok(except == tests2[i], "expected %lx, got %lx\n", tests2[i], except); + } + + except = FE_ALL_EXCEPT; + ret = p_fesetexceptflag(&except, 0); + ok(!ret, "fesetexceptflag returned %x\n", ret); + except = p_fetestexcept(FE_ALL_EXCEPT); + ok(except == FE_ALL_EXCEPT, "expected %x, got %lx\n", FE_ALL_EXCEPT, except); + + 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); + p__clearfp(); }
diff --git a/dlls/msvcr120_app/msvcr120_app.spec b/dlls/msvcr120_app/msvcr120_app.spec index 152eda3be81..2905f4d7b08 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 5ae5f2e5d6c..8157e02f94a 100644 --- a/dlls/msvcrt/math.c +++ b/dlls/msvcrt/math.c @@ -2237,6 +2237,26 @@ int CDECL fetestexcept(int flags) fegetexceptflag(&except, flags); return except; } + +/********************************************************************* + * fesetexceptflag (MSVCR120.@) + */ +int CDECL fesetexceptflag(const fexcept_t *status, int excepts) +{ + fenv_t env; + + if(!status) + return 0; + + if(!*status) { + _clearfp(); + return 0; + } + + fegetenv(&env); + env._Fe_stat |= (*status & excepts & FE_ALL_EXCEPT); + return fesetenv(&env); +} #endif
#if _MSVCR_VER>=140 diff --git a/dlls/ucrtbase/ucrtbase.spec b/dlls/ucrtbase/ucrtbase.spec index 4f842c58d27..e5fbc6b14b9 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 0ddb6852368..45cd0b9e534 100644 --- a/include/msvcrt/fenv.h +++ b/include/msvcrt/fenv.h @@ -35,6 +35,7 @@ typedef __msvcrt_ulong fexcept_t; _ACRTIMP int __cdecl fegetenv(fenv_t*); _ACRTIMP int __cdecl fesetenv(const fenv_t*); _ACRTIMP int __cdecl fegetexceptflag(fexcept_t*, int); +_ACRTIMP int __cdecl fesetexceptflag(const fexcept_t*, int); _ACRTIMP int __cdecl fegetround(void); _ACRTIMP int __cdecl fesetround(int); _ACRTIMP int __cdecl fetestexcept(int);