Support FPE handling under MSVC/mingw32.

This commit is contained in:
goffioul 2005-10-25 13:05:39 +00:00
parent 8314aaa872
commit 0deebf6f4f
3 changed files with 51 additions and 3 deletions

View file

@ -483,6 +483,10 @@ edit_double(int n, double d, int *sp, char *s, int *ep)
{
char *exponent, *p, buff[DBL_SIZE + 1];
int length;
#if defined(HAVE_FENV_H) || defined(_MSC_VER) || defined(mingw32)
fenv_t env;
feholdexcept(&env);
#endif
if (isnan(d) || !finite(d))
FEerror("Can't print a non-number.", 0);
@ -530,6 +534,9 @@ edit_double(int n, double d, int *sp, char *s, int *ep)
s[i] = '0';
}
s[n] = '\0';
#if defined(HAVE_FENV_H) || defined(_MSC_VER) || defined(mingw32)
fesetenv(&env);
#endif
return length;
}

View file

@ -15,7 +15,7 @@
*/
#include <config.h>
#ifdef HAVE_FENV_H
#if defined(HAVE_FENV_H)
# define _GNU_SOURCE
# include <fenv.h>
# ifndef FE_UNDERFLOW
@ -39,6 +39,7 @@
#include <signal.h>
#if defined(mingw32) || defined(_MSC_VER)
# include <windows.h>
void handle_fpe_signal(int,int);
#endif
#if !defined(_MSC_VER)
# include <unistd.h>
@ -129,7 +130,7 @@ signal_catcher(int sig)
{
if (!ecl_interrupt_enable ||
symbol_value(@'si::*interrupt-enable*') == Cnil) {
signal(sig, signal_catcher);
mysignal(sig, signal_catcher);
cl_env.interrupt_pending = sig;
return;
}
@ -148,6 +149,11 @@ signal_catcher(int sig)
#endif
} CL_UNWIND_PROTECT_END;
#else
#if defined (_MSC_VER)
if (sig == SIGFPE) {
handle_fpe_signal(sig, _fpecode);
}
#endif
handle_signal(sig);
#endif
}
@ -242,6 +248,26 @@ LONG WINAPI W32_exception_filter(struct _EXCEPTION_POINTERS* ep)
return excpt_result;
}
void handle_fpe_signal(int sig, int num)
{
cl_object condition = @'arithmetic-error';
switch (num) {
case _FPE_OVERFLOW:
condition = @'floating-point-overflow';
break;
case _FPE_UNDERFLOW:
condition = @'floating-point-underflow';
break;
case _FPE_ZERODIVIDE:
condition = @'division-by-zero';
break;
}
si_trap_fpe(@'last', Ct);
cl_error(1, condition);
}
BOOL WINAPI W32_console_ctrl_handler(DWORD type)
{
switch (type)
@ -258,7 +284,7 @@ BOOL WINAPI W32_console_ctrl_handler(DWORD type)
cl_object
si_trap_fpe(cl_object condition, cl_object flag)
{
#if defined(HAVE_FENV_H) && defined(HAVE_FEENABLEEXCEPT)
#if (defined(HAVE_FENV_H) && defined(HAVE_FEENABLEEXCEPT)) || defined(_MSC_VER) || defined(mingw32)
static int last_bits = 0;
int bits = 0;
if (condition == @'division-by-zero')
@ -271,6 +297,9 @@ si_trap_fpe(cl_object condition, cl_object flag)
bits = FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW;
else if (condition == @'last')
bits = last_bits;
#if defined(_MSC_VER) || defined (mingw32)
_fpreset();
#endif
if (bits) {
if (flag == Cnil) {
fedisableexcept(bits);

View file

@ -217,6 +217,18 @@ extern cl_fixnum ecl_runtime(void);
extern bool ecl_interrupt_enable;
#if defined(_MSC_VER) || defined(mingw32)
# include <float.h>
# define FE_DIVBYZERO EM_ZERODIVIDE
# define FE_OVERFLOW EM_OVERFLOW
# define FE_UNDERFLOW EM_UNDERFLOW
# define feenableexcept(bits) { int cw = _controlfp(0,0); cw &= ~(bits); _controlfp(cw,MCW_EM); }
# define fedisableexcept(bits) { int cw = _controlfp(0,0); cw |= (bits); _controlfp(cw,MCW_EM); }
# define feholdexcept(bits) { *(bits) = _controlfp(0,0); _controlfp(0xffffffff, MCW_EM); }
# define fesetenv(bits) _controlfp(*(bits), MCW_EM)
typedef int fenv_t;
#endif
/* unixfsys.d */
#if defined(_MSC_VER) || defined(mingw32)