Commit 1150c045 authored by Piotr Caban's avatar Piotr Caban Committed by Alexandre Julliard

msvcr120: Add fegetenv implementation.

parent 6526ac19
...@@ -88,7 +88,7 @@ ...@@ -88,7 +88,7 @@
@ cdecl abort() ucrtbase.abort @ cdecl abort() ucrtbase.abort
@ cdecl exit(long) ucrtbase.exit @ cdecl exit(long) ucrtbase.exit
@ stub feclearexcept @ stub feclearexcept
@ stub fegetenv @ cdecl fegetenv(ptr) ucrtbase.fegetenv
@ stub fegetexceptflag @ stub fegetexceptflag
@ stub fegetround @ stub fegetround
@ stub feholdexcept @ stub feholdexcept
......
...@@ -2144,7 +2144,7 @@ ...@@ -2144,7 +2144,7 @@
@ stub fdimf @ stub fdimf
@ stub fdiml @ stub fdiml
@ stub feclearexcept @ stub feclearexcept
@ stub fegetenv @ cdecl fegetenv(ptr) MSVCRT_fegetenv
@ stub fegetexceptflag @ stub fegetexceptflag
@ stub fegetround @ stub fegetround
@ stub feholdexcept @ stub feholdexcept
......
...@@ -147,6 +147,12 @@ struct MSVCRT_lconv ...@@ -147,6 +147,12 @@ struct MSVCRT_lconv
wchar_t* _W_negative_sign; wchar_t* _W_negative_sign;
}; };
typedef struct
{
unsigned int control;
unsigned int status;
} fenv_t;
static char* (CDECL *p_setlocale)(int category, const char* locale); static char* (CDECL *p_setlocale)(int category, const char* locale);
static struct MSVCRT_lconv* (CDECL *p_localeconv)(void); static struct MSVCRT_lconv* (CDECL *p_localeconv)(void);
static size_t (CDECL *p_wcstombs_s)(size_t *ret, char* dest, size_t sz, const wchar_t* src, size_t max); static size_t (CDECL *p_wcstombs_s)(size_t *ret, char* dest, size_t sz, const wchar_t* src, size_t max);
...@@ -162,6 +168,8 @@ static int (CDECL *p__finite)(double); ...@@ -162,6 +168,8 @@ static int (CDECL *p__finite)(double);
static float (CDECL *p_wcstof)(const wchar_t*, wchar_t**); static float (CDECL *p_wcstof)(const wchar_t*, wchar_t**);
static double (CDECL *p_remainder)(double, double); static double (CDECL *p_remainder)(double, double);
static int* (CDECL *p_errno)(void); static int* (CDECL *p_errno)(void);
static int (CDECL *p_fegetenv)(fenv_t*);
static int (CDECL *p__clearfp)(void);
/* make sure we use the correct errno */ /* make sure we use the correct errno */
#undef errno #undef errno
...@@ -207,6 +215,8 @@ static BOOL init(void) ...@@ -207,6 +215,8 @@ static BOOL init(void)
p_wcstof = (void*)GetProcAddress(module, "wcstof"); p_wcstof = (void*)GetProcAddress(module, "wcstof");
p_remainder = (void*)GetProcAddress(module, "remainder"); p_remainder = (void*)GetProcAddress(module, "remainder");
p_errno = (void*)GetProcAddress(module, "_errno"); p_errno = (void*)GetProcAddress(module, "_errno");
SET(p_fegetenv, "fegetenv");
SET(p__clearfp, "_clearfp");
if(sizeof(void*) == 8) { /* 64-bit initialization */ if(sizeof(void*) == 8) { /* 64-bit initialization */
SET(p_critical_section_ctor, SET(p_critical_section_ctor,
"??0critical_section@Concurrency@@QEAA@XZ"); "??0critical_section@Concurrency@@QEAA@XZ");
...@@ -686,6 +696,20 @@ static void test_critical_section(void) ...@@ -686,6 +696,20 @@ static void test_critical_section(void)
call_func1(p_critical_section_dtor, &cs); call_func1(p_critical_section_dtor, &cs);
} }
static void test_fegetenv(void)
{
int ret;
fenv_t env;
p__clearfp();
ret = p_fegetenv(&env);
ok(!ret, "fegetenv returned %x\n", ret);
ok(env.control == (_EM_INEXACT|_EM_UNDERFLOW|_EM_OVERFLOW|_EM_ZERODIVIDE|_EM_INVALID),
"env.control = %x\n", env.control);
ok(!env.status, "env.status = %x\n", env.status);
}
START_TEST(msvcr120) START_TEST(msvcr120)
{ {
if (!init()) return; if (!init()) return;
...@@ -699,4 +723,5 @@ START_TEST(msvcr120) ...@@ -699,4 +723,5 @@ START_TEST(msvcr120)
test__strtof(); test__strtof();
test_remainder(); test_remainder();
test_critical_section(); test_critical_section();
test_fegetenv();
} }
...@@ -1810,7 +1810,7 @@ ...@@ -1810,7 +1810,7 @@
@ stub fdimf @ stub fdimf
@ stub fdiml @ stub fdiml
@ stub feclearexcept @ stub feclearexcept
@ stub fegetenv @ cdecl fegetenv(ptr) msvcr120.fegetenv
@ stub fegetexceptflag @ stub fegetexceptflag
@ stub fegetround @ stub fegetround
@ stub feholdexcept @ stub feholdexcept
......
...@@ -1199,6 +1199,17 @@ int CDECL _controlfp_s(unsigned int *cur, unsigned int newval, unsigned int mask ...@@ -1199,6 +1199,17 @@ int CDECL _controlfp_s(unsigned int *cur, unsigned int newval, unsigned int mask
} }
/********************************************************************* /*********************************************************************
* fegetenv (MSVCR120.@)
*/
int CDECL MSVCRT_fegetenv(fenv_t *env)
{
env->control = _controlfp(0, 0) & (MSVCRT__EM_INEXACT | MSVCRT__EM_UNDERFLOW |
MSVCRT__EM_OVERFLOW | MSVCRT__EM_ZERODIVIDE | MSVCRT__EM_INVALID);
env->status = _statusfp();
return 0;
}
/*********************************************************************
* __fpe_flt_rounds (UCRTBASE.@) * __fpe_flt_rounds (UCRTBASE.@)
*/ */
int CDECL __fpe_flt_rounds(void) int CDECL __fpe_flt_rounds(void)
......
...@@ -910,6 +910,12 @@ struct MSVCRT__stat64 { ...@@ -910,6 +910,12 @@ struct MSVCRT__stat64 {
#define MSVCRT__DN_SAVE_OPERANDS_FLUSH_RESULTS 0x03000000 #define MSVCRT__DN_SAVE_OPERANDS_FLUSH_RESULTS 0x03000000
#define MSVCRT__EM_AMBIGUOUS 0x80000000 #define MSVCRT__EM_AMBIGUOUS 0x80000000
typedef struct
{
unsigned int control;
unsigned int status;
} fenv_t;
#define MSVCRT_CLOCKS_PER_SEC 1000 #define MSVCRT_CLOCKS_PER_SEC 1000
/* signals */ /* signals */
......
...@@ -2286,7 +2286,7 @@ ...@@ -2286,7 +2286,7 @@
@ stub fdimf @ stub fdimf
@ stub fdiml @ stub fdiml
@ stub feclearexcept @ stub feclearexcept
@ stub fegetenv @ cdecl fegetenv(ptr) MSVCRT_fegetenv
@ stub fegetexceptflag @ stub fegetexceptflag
@ stub fegetround @ stub fegetround
@ stub feholdexcept @ stub feholdexcept
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment