Signed-off-by: Daniel Lehman dlehman25@gmail.com
--- v2: - use _statusfp() - improved tests --- .../api-ms-win-crt-runtime-l1-1-0.spec | 2 +- dlls/msvcr120/msvcr120.spec | 2 +- dlls/msvcr120/tests/msvcr120.c | 33 ++++++++++++++++++- dlls/msvcr120_app/msvcr120_app.spec | 2 +- dlls/msvcrt/math.c | 8 +++++ dlls/ucrtbase/ucrtbase.spec | 2 +- include/msvcrt/fenv.h | 1 + 7 files changed, 45 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 74d682b33bf..66c2d8cc264 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 @@ -95,7 +95,7 @@ @ cdecl fesetenv(ptr) ucrtbase.fesetenv @ stub fesetexceptflag @ cdecl fesetround(long) ucrtbase.fesetround -@ stub fetestexcept +@ cdecl fetestexcept(long) ucrtbase.fetestexcept @ cdecl perror(str) ucrtbase.perror @ cdecl quick_exit(long) ucrtbase.quick_exit @ cdecl raise(long) ucrtbase.raise diff --git a/dlls/msvcr120/msvcr120.spec b/dlls/msvcr120/msvcr120.spec index 0e1c7705166..27ae5a930f6 100644 --- a/dlls/msvcr120/msvcr120.spec +++ b/dlls/msvcr120/msvcr120.spec @@ -2154,7 +2154,7 @@ @ cdecl fesetenv(ptr) @ stub fesetexceptflag @ cdecl fesetround(long) -@ stub fetestexcept +@ cdecl fetestexcept(long) @ stub feupdateenv @ cdecl fflush(ptr) @ cdecl fgetc(ptr) diff --git a/dlls/msvcr120/tests/msvcr120.c b/dlls/msvcr120/tests/msvcr120.c index e8ef2be3520..537e9077402 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_fetestexcept)(int); static int (CDECL *p__clearfp)(void); static _locale_t (__cdecl *p_wcreate_locale)(int, const wchar_t *); static void (__cdecl *p_free_locale)(_locale_t); @@ -257,6 +258,7 @@ static BOOL init(void) SET(p_fesetenv, "fesetenv"); SET(p_fegetround, "fegetround"); SET(p_fesetround, "fesetround"); + SET(p_fetestexcept, "fetestexcept");
SET(p__clearfp, "_clearfp"); SET(p_vsscanf, "vsscanf"); @@ -788,8 +790,17 @@ static void test_critical_section(void)
static void test_feenv(void) { + static const int tests[] = { + 0, + FE_INEXACT, + FE_UNDERFLOW, + FE_OVERFLOW, + FE_DIVBYZERO, + FE_INVALID, + FE_ALL_EXCEPT, + }; fenv_t env, env2; - int ret; + int i, ret, flags;
p__clearfp();
@@ -807,6 +818,26 @@ static void test_feenv(void) ok(!ret, "fesetenv returned %x\n", ret); ret = p_fegetround(); ok(ret == FE_TONEAREST, "Got unexpected round mode %#x.\n", ret); + + ret = p_fetestexcept(FE_ALL_EXCEPT); + ok(!ret, "fetestexcept returned %x\n", ret); + + flags = 0; + 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); + + ret = p_fetestexcept(tests[i]); + ok(ret == tests[i], "Test %d: expected %x, got %x\n", i, tests[i], ret); + + flags |= tests[i]; + ret = p_fetestexcept(FE_ALL_EXCEPT); + ok(ret == flags, "Test %d: expected %x, got %x\n", i, flags, ret); + } + p__clearfp(); }
static void test__wcreate_locale(void) diff --git a/dlls/msvcr120_app/msvcr120_app.spec b/dlls/msvcr120_app/msvcr120_app.spec index 05b8a97a084..daee644d965 100644 --- a/dlls/msvcr120_app/msvcr120_app.spec +++ b/dlls/msvcr120_app/msvcr120_app.spec @@ -1820,7 +1820,7 @@ @ cdecl fesetenv(ptr) msvcr120.fesetenv @ stub fesetexceptflag @ cdecl fesetround(long) msvcr120.fesetround -@ stub fetestexcept +@ cdecl fetestexcept(long) msvcr120.fetestexcept @ stub feupdateenv @ cdecl fflush(ptr) msvcr120.fflush @ cdecl fgetc(ptr) msvcr120.fgetc diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c index d6b0d9422e7..6c1d665c843 100644 --- a/dlls/msvcrt/math.c +++ b/dlls/msvcrt/math.c @@ -2214,6 +2214,14 @@ int CDECL fegetenv(fenv_t *env) env->_Fe_stat = _statusfp(); return 0; } + +/********************************************************************* + * fetestexcept (MSVCR120.@) + */ +int CDECL fetestexcept(int flags) +{ + return _statusfp() & flags; +} #endif
#if _MSVCR_VER>=140 diff --git a/dlls/ucrtbase/ucrtbase.spec b/dlls/ucrtbase/ucrtbase.spec index 0a8d74521f5..d40df5e0efc 100644 --- a/dlls/ucrtbase/ucrtbase.spec +++ b/dlls/ucrtbase/ucrtbase.spec @@ -2296,7 +2296,7 @@ @ cdecl fesetenv(ptr) @ stub fesetexceptflag @ cdecl fesetround(long) -@ stub fetestexcept +@ cdecl fetestexcept(long) @ cdecl fflush(ptr) @ cdecl fgetc(ptr) @ cdecl fgetpos(ptr ptr) diff --git a/include/msvcrt/fenv.h b/include/msvcrt/fenv.h index 92b341bd46b..3dcbcf0b8fe 100644 --- a/include/msvcrt/fenv.h +++ b/include/msvcrt/fenv.h @@ -34,6 +34,7 @@ _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 fetestexcept(int);
#ifdef __cplusplus }
Signed-off-by: Daniel Lehman dlehman25@gmail.com
--- v2: - crash on NULL except* only happens with non-zero flags - fix implementation (thanks Piotr) - more tests
--- .../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
Signed-off-by: Piotr Caban piotr@codeweavers.com
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 | 26 +++++++++++++++++-- dlls/msvcr120_app/msvcr120_app.spec | 2 +- dlls/msvcrt/math.c | 12 +++++++++ dlls/ucrtbase/ucrtbase.spec | 2 +- include/msvcrt/fenv.h | 1 + 7 files changed, 41 insertions(+), 6 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 1440e96db17..017155c65d5 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 @@ -87,7 +87,7 @@ @ cdecl _wsystem(wstr) ucrtbase._wsystem @ cdecl abort() ucrtbase.abort @ cdecl exit(long) ucrtbase.exit -@ stub feclearexcept +@ cdecl feclearexcept(long) ucrtbase.feclearexcept @ cdecl fegetenv(ptr) ucrtbase.fegetenv @ stub fegetexceptflag @ cdecl fegetround() ucrtbase.fegetround diff --git a/dlls/msvcr120/msvcr120.spec b/dlls/msvcr120/msvcr120.spec index 7719bc662e0..105c349355e 100644 --- a/dlls/msvcr120/msvcr120.spec +++ b/dlls/msvcr120/msvcr120.spec @@ -2143,7 +2143,7 @@ @ cdecl fdim(double double) @ cdecl fdimf(float float) @ cdecl fdiml(double double) fdim -@ stub feclearexcept +@ cdecl feclearexcept(long) @ cdecl fegetenv(ptr) @ stub fegetexceptflag @ cdecl fegetround() diff --git a/dlls/msvcr120/tests/msvcr120.c b/dlls/msvcr120/tests/msvcr120.c index 9104cfcd447..cff6128bbe9 100644 --- a/dlls/msvcr120/tests/msvcr120.c +++ b/dlls/msvcr120/tests/msvcr120.c @@ -184,6 +184,7 @@ 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_feclearexcept)(int); static int (CDECL *p__clearfp)(void); static _locale_t (__cdecl *p_wcreate_locale)(int, const wchar_t *); static void (__cdecl *p_free_locale)(_locale_t); @@ -261,6 +262,7 @@ static BOOL init(void) SET(p_fesetround, "fesetround"); SET(p_fesetexceptflag, "fesetexceptflag"); SET(p_fetestexcept, "fetestexcept"); + SET(p_feclearexcept, "feclearexcept");
SET(p__clearfp, "_clearfp"); SET(p_vsscanf, "vsscanf"); @@ -854,6 +856,11 @@ static void test_feenv(void) except = p_fetestexcept(FE_ALL_EXCEPT); ok(except == (FE_INEXACT|FE_UNDERFLOW), "expected %x, got %lx\n", FE_INEXACT|FE_UNDERFLOW, except);
+ ret = p_feclearexcept(~FE_ALL_EXCEPT); + ok(!ret, "feclearexceptflag 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); @@ -885,7 +892,18 @@ static void test_feenv(void) ok(ret == flags, "Test %d: expected %x, got %x\n", i, flags, ret); }
- p__clearfp(); + for(i=0; i<ARRAY_SIZE(tests); i++) { + ret = p_feclearexcept(tests[i]); + ok(!ret, "Test %d: feclearexceptflag returned %x\n", i, ret); + + flags &= ~tests[i]; + except = p_fetestexcept(tests[i]); + ok(!except, "Test %d: expected %x, got %lx\n", i, flags, except); + } + + except = p_fetestexcept(FE_ALL_EXCEPT); + ok(!except, "expected 0, got %lx\n", except); + /* setting bits with except */ for(i=0; i<ARRAY_SIZE(tests); i++) { except = tests[i]; @@ -909,7 +927,11 @@ static void test_feenv(void) 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(); + + ret = p_feclearexcept(FE_ALL_EXCEPT); + ok(!ret, "feclearexceptflag returned %x\n", ret); + except = p_fetestexcept(FE_ALL_EXCEPT); + ok(!except, "expected 0, got %lx\n", except); }
static void test__wcreate_locale(void) diff --git a/dlls/msvcr120_app/msvcr120_app.spec b/dlls/msvcr120_app/msvcr120_app.spec index 24d98427acf..e3cda9a0022 100644 --- a/dlls/msvcr120_app/msvcr120_app.spec +++ b/dlls/msvcr120_app/msvcr120_app.spec @@ -1809,7 +1809,7 @@ @ cdecl fdim(double double) msvcr120.fdim @ cdecl fdimf(float float) msvcr120.fdimf @ cdecl fdiml(double double) msvcr120.fdiml -@ stub feclearexcept +@ cdecl feclearexcept(long) msvcr120.feclearexcept @ cdecl fegetenv(ptr) msvcr120.fegetenv @ stub fegetexceptflag @ cdecl fegetround() msvcr120.fegetround diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c index 16ff50f0334..16e940c21ce 100644 --- a/dlls/msvcrt/math.c +++ b/dlls/msvcrt/math.c @@ -2239,6 +2239,18 @@ int CDECL fesetexceptflag(const fexcept_t *status, int excepts) env._Fe_stat |= (*status & excepts); return fesetenv(&env); } + +/********************************************************************* + * feclearexcept (MSVCR120.@) + */ +int CDECL feclearexcept(int flags) +{ + fenv_t env; + + fegetenv(&env); + env._Fe_stat &= ~(flags & FE_ALL_EXCEPT); + return fesetenv(&env); +} #endif
#if _MSVCR_VER>=140 diff --git a/dlls/ucrtbase/ucrtbase.spec b/dlls/ucrtbase/ucrtbase.spec index cd012aa0ab9..1df40c81b76 100644 --- a/dlls/ucrtbase/ucrtbase.spec +++ b/dlls/ucrtbase/ucrtbase.spec @@ -2286,7 +2286,7 @@ @ cdecl fdim(double double) @ cdecl fdimf(float float) @ cdecl fdiml(double double) fdim -@ stub feclearexcept +@ cdecl feclearexcept(long) @ cdecl fegetenv(ptr) @ stub fegetexceptflag @ cdecl fegetround() diff --git a/include/msvcrt/fenv.h b/include/msvcrt/fenv.h index 6396bd688f3..b37fbc100bf 100644 --- a/include/msvcrt/fenv.h +++ b/include/msvcrt/fenv.h @@ -37,6 +37,7 @@ _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 feclearexcept(int); _ACRTIMP int __cdecl fetestexcept(int);
#ifdef __cplusplus
Signed-off-by: Piotr Caban piotr@codeweavers.com
Signed-off-by: Daniel Lehman dlehman25@gmail.com
--- v2: use _statusfp() --- .../api-ms-win-crt-runtime-l1-1-0.spec | 2 +- dlls/msvcr120/msvcr120.spec | 2 +- dlls/msvcr120/tests/msvcr120.c | 13 +++++++++++++ dlls/msvcr120_app/msvcr120_app.spec | 2 +- dlls/msvcrt/math.c | 9 +++++++++ dlls/ucrtbase/ucrtbase.spec | 2 +- include/msvcrt/fenv.h | 1 + 7 files changed, 27 insertions(+), 4 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 017155c65d5..3733a524382 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 @@ -89,7 +89,7 @@ @ cdecl exit(long) ucrtbase.exit @ cdecl feclearexcept(long) ucrtbase.feclearexcept @ cdecl fegetenv(ptr) ucrtbase.fegetenv -@ stub fegetexceptflag +@ cdecl fegetexceptflag(ptr long) ucrtbase.fegetexceptflag @ cdecl fegetround() ucrtbase.fegetround @ stub feholdexcept @ cdecl fesetenv(ptr) ucrtbase.fesetenv diff --git a/dlls/msvcr120/msvcr120.spec b/dlls/msvcr120/msvcr120.spec index 105c349355e..306bee5f50c 100644 --- a/dlls/msvcr120/msvcr120.spec +++ b/dlls/msvcr120/msvcr120.spec @@ -2145,7 +2145,7 @@ @ cdecl fdiml(double double) fdim @ cdecl feclearexcept(long) @ cdecl fegetenv(ptr) -@ stub fegetexceptflag +@ cdecl fegetexceptflag(ptr long) @ cdecl fegetround() @ stub feholdexcept @ cdecl feof(ptr) diff --git a/dlls/msvcr120/tests/msvcr120.c b/dlls/msvcr120/tests/msvcr120.c index cff6128bbe9..151989f8f74 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_fegetexceptflag)(fexcept_t*,int); static int (CDECL *p_fesetexceptflag)(const fexcept_t*,int); static int (CDECL *p_fetestexcept)(int); static int (CDECL *p_feclearexcept)(int); @@ -260,6 +261,7 @@ static BOOL init(void) SET(p_fesetenv, "fesetenv"); SET(p_fegetround, "fegetround"); SET(p_fesetround, "fesetround"); + SET(p_fegetexceptflag, "fegetexceptflag"); SET(p_fesetexceptflag, "fesetexceptflag"); SET(p_fetestexcept, "fetestexcept"); SET(p_feclearexcept, "feclearexcept"); @@ -849,6 +851,7 @@ static void test_feenv(void)
if(0) { /* crash on windows */ p_fesetexceptflag(NULL, FE_ALL_EXCEPT); + p_fegetexceptflag(NULL, 0); } except = FE_ALL_EXCEPT; ret = p_fesetexceptflag(&except, FE_INEXACT|FE_UNDERFLOW); @@ -890,6 +893,16 @@ static void test_feenv(void) flags |= tests[i]; ret = p_fetestexcept(FE_ALL_EXCEPT); ok(ret == flags, "Test %d: expected %x, got %x\n", i, flags, ret); + + except = ~0; + ret = p_fegetexceptflag(&except, ~0); + ok(!ret, "Test %d: fegetexceptflag returned %x.\n", i, ret); + ok(except == flags, "Test %d: expected %x, got %lx\n", i, flags, except); + + except = ~0; + ret = p_fegetexceptflag(&except, tests[i]); + ok(!ret, "Test %d: fegetexceptflag returned %x.\n", i, ret); + ok(except == tests[i], "Test %d: expected %x, got %lx\n", i, tests[i], except); }
for(i=0; i<ARRAY_SIZE(tests); i++) { diff --git a/dlls/msvcr120_app/msvcr120_app.spec b/dlls/msvcr120_app/msvcr120_app.spec index e3cda9a0022..b16d1a5b3f0 100644 --- a/dlls/msvcr120_app/msvcr120_app.spec +++ b/dlls/msvcr120_app/msvcr120_app.spec @@ -1811,7 +1811,7 @@ @ cdecl fdiml(double double) msvcr120.fdiml @ cdecl feclearexcept(long) msvcr120.feclearexcept @ cdecl fegetenv(ptr) msvcr120.fegetenv -@ stub fegetexceptflag +@ cdecl fegetexceptflag(ptr long) msvcr120.fegetexceptflag @ cdecl fegetround() msvcr120.fegetround @ stub feholdexcept @ cdecl feof(ptr) msvcr120.feof diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c index 16e940c21ce..6b2d08a8294 100644 --- a/dlls/msvcrt/math.c +++ b/dlls/msvcrt/math.c @@ -2251,6 +2251,15 @@ int CDECL feclearexcept(int flags) env._Fe_stat &= ~(flags & FE_ALL_EXCEPT); return fesetenv(&env); } + +/********************************************************************* + * fegetexceptflag (MSVCR120.@) + */ +int CDECL fegetexceptflag(fexcept_t *status, int excepts) +{ + *status = _statusfp() & excepts; + return 0; +} #endif
#if _MSVCR_VER>=140 diff --git a/dlls/ucrtbase/ucrtbase.spec b/dlls/ucrtbase/ucrtbase.spec index 1df40c81b76..8f331825fc4 100644 --- a/dlls/ucrtbase/ucrtbase.spec +++ b/dlls/ucrtbase/ucrtbase.spec @@ -2288,7 +2288,7 @@ @ cdecl fdiml(double double) fdim @ cdecl feclearexcept(long) @ cdecl fegetenv(ptr) -@ stub fegetexceptflag +@ cdecl fegetexceptflag(ptr long) @ cdecl fegetround() @ stub feholdexcept @ cdecl feof(ptr) diff --git a/include/msvcrt/fenv.h b/include/msvcrt/fenv.h index b37fbc100bf..a6b53eca567 100644 --- a/include/msvcrt/fenv.h +++ b/include/msvcrt/fenv.h @@ -34,6 +34,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 fegetround(void); _ACRTIMP int __cdecl fesetround(int); _ACRTIMP int __cdecl fesetexceptflag(const fexcept_t*, int);
Signed-off-by: Piotr Caban piotr@codeweavers.com