Changes for Lee Busby's SIGFPE patch set.
Two new modules fpectl and fpetest. Surround various and sundry f.p. operations with PyFPE_*_PROTECT macros.
This commit is contained in:
parent
0ae748d3c4
commit
52fa3a6909
|
@ -724,10 +724,14 @@ Tkapp_ExprDouble (self, args)
|
|||
{
|
||||
char *s;
|
||||
double v;
|
||||
int retval;
|
||||
|
||||
if (!PyArg_Parse(args, "s", &s))
|
||||
return NULL;
|
||||
if (Tcl_ExprDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
|
||||
PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
|
||||
retval = Tcl_ExprDouble (Tkapp_Interp (self), s, &v);
|
||||
PyFPE_END_PROTECT
|
||||
if (retval == TCL_ERROR)
|
||||
return Tkinter_Error(self);
|
||||
return Py_BuildValue("d", v);
|
||||
}
|
||||
|
|
|
@ -247,7 +247,9 @@ math_1(args, func)
|
|||
if (!PyArg_ParseTuple(args, "D", &x))
|
||||
return NULL;
|
||||
errno = 0;
|
||||
PyFPE_START_PROTECT("complex function", return 0)
|
||||
x = (*func)(x);
|
||||
PyFPE_END_PROTECT
|
||||
CHECK(x.real);
|
||||
CHECK(x.imag);
|
||||
if (errno != 0)
|
||||
|
|
|
@ -0,0 +1,244 @@
|
|||
/*
|
||||
---------------------------------------------------------------------
|
||||
/ Copyright (c) 1996. \
|
||||
| The Regents of the University of California. |
|
||||
| All rights reserved. |
|
||||
| |
|
||||
| Permission to use, copy, modify, and distribute this software for |
|
||||
| any purpose without fee is hereby granted, provided that this en- |
|
||||
| tire notice is included in all copies of any software which is or |
|
||||
| includes a copy or modification of this software and in all |
|
||||
| copies of the supporting documentation for such software. |
|
||||
| |
|
||||
| This work was produced at the University of California, Lawrence |
|
||||
| Livermore National Laboratory under contract no. W-7405-ENG-48 |
|
||||
| between the U.S. Department of Energy and The Regents of the |
|
||||
| University of California for the operation of UC LLNL. |
|
||||
| |
|
||||
| DISCLAIMER |
|
||||
| |
|
||||
| This software was prepared as an account of work sponsored by an |
|
||||
| agency of the United States Government. Neither the United States |
|
||||
| Government nor the University of California nor any of their em- |
|
||||
| ployees, makes any warranty, express or implied, or assumes any |
|
||||
| liability or responsibility for the accuracy, completeness, or |
|
||||
| usefulness of any information, apparatus, product, or process |
|
||||
| disclosed, or represents that its use would not infringe |
|
||||
| privately-owned rights. Reference herein to any specific commer- |
|
||||
| cial products, process, or service by trade name, trademark, |
|
||||
| manufacturer, or otherwise, does not necessarily constitute or |
|
||||
| imply its endorsement, recommendation, or favoring by the United |
|
||||
| States Government or the University of California. The views and |
|
||||
| opinions of authors expressed herein do not necessarily state or |
|
||||
| reflect those of the United States Government or the University |
|
||||
| of California, and shall not be used for advertising or product |
|
||||
\ endorsement purposes. /
|
||||
---------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
Floating point exception control module.
|
||||
|
||||
This Python module provides bare-bones control over floating point
|
||||
units from several hardware manufacturers. Specifically, it allows
|
||||
the user to turn on the generation of SIGFPE whenever any of the
|
||||
three serious IEEE 754 exceptions (Division by Zero, Overflow,
|
||||
Invalid Operation) occurs. We currently ignore Underflow and
|
||||
Inexact Result exceptions, although those could certainly be added
|
||||
if desired.
|
||||
|
||||
The module also establishes a signal handler for SIGFPE during
|
||||
initialization. This builds on code found in the Python
|
||||
distribution at Include/pyfpe.h and Python/pyfpe.c. If those files
|
||||
are not in your Python distribution, find them in a patch at
|
||||
ftp://icf.llnl.gov/pub/python/busby/patches.961108.tgz.
|
||||
|
||||
This module is only useful to you if it happens to include code
|
||||
specific for your hardware and software environment. If you can
|
||||
contribute OS-specific code for new platforms, or corrections for
|
||||
the code provided, it will be greatly appreciated.
|
||||
|
||||
** Version 1.0: September 20, 1996. Lee Busby, LLNL.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "Python.h"
|
||||
#include <signal.h>
|
||||
|
||||
#ifndef WANT_SIGFPE_HANDLER
|
||||
/* Define locally if they are not defined in Python. This gives only
|
||||
* the limited control to induce a core dump in case of an exception.
|
||||
*/
|
||||
static jmp_buf PyFPE_jbuf;
|
||||
static int PyFPE_counter = 0;
|
||||
#endif
|
||||
|
||||
typedef RETSIGTYPE Sigfunc(int);
|
||||
static Sigfunc sigfpe_handler;
|
||||
static void fpe_reset(Sigfunc *);
|
||||
|
||||
static PyObject *fpe_error;
|
||||
void initfpectl(void);
|
||||
static PyObject *turnon_sigfpe (PyObject *self,PyObject *args);
|
||||
static PyObject *turnoff_sigfpe (PyObject *self,PyObject *args);
|
||||
|
||||
static PyMethodDef fpectl_methods[] = {
|
||||
{"turnon_sigfpe", (PyCFunction) turnon_sigfpe, 1},
|
||||
{"turnoff_sigfpe", (PyCFunction) turnoff_sigfpe, 1},
|
||||
{0,0}
|
||||
};
|
||||
|
||||
static PyObject *turnon_sigfpe(PyObject *self,PyObject *args)
|
||||
{
|
||||
/* Do any architecture-specific one-time only initialization here. */
|
||||
|
||||
fpe_reset(sigfpe_handler);
|
||||
Py_INCREF (Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static void fpe_reset(Sigfunc *handler)
|
||||
{
|
||||
/* Reset the exception handling machinery, and reset the signal
|
||||
* handler for SIGFPE to the given handler.
|
||||
*/
|
||||
|
||||
/*-- IRIX -----------------------------------------------------------------*/
|
||||
#if defined(sgi)
|
||||
/* See man page on handle_sigfpes -- must link with -lfpe
|
||||
* My usage doesn't follow the man page exactly. Maybe somebody
|
||||
* else can explain handle_sigfpes to me....
|
||||
* cc -c -I/usr/local/python/include fpectlmodule.c
|
||||
* ld -shared -o fpectlmodule.so fpectlmodule.o -lfpe
|
||||
*/
|
||||
#include <sigfpe.h>
|
||||
typedef void user_routine (unsigned[5], int[2]);
|
||||
typedef void abort_routine (unsigned long);
|
||||
handle_sigfpes(_OFF, 0,
|
||||
(user_routine *)0,
|
||||
_TURN_OFF_HANDLER_ON_ERROR,
|
||||
(abort_routine*)0);
|
||||
handle_sigfpes(_ON, _EN_OVERFL | _EN_DIVZERO | _EN_INVALID,
|
||||
(user_routine *)0,
|
||||
_ABORT_ON_ERROR,
|
||||
(abort_routine*)0);
|
||||
signal(SIGFPE, handler);
|
||||
|
||||
/*-- SunOS and Solaris ----------------------------------------------------*/
|
||||
#elif defined(sun)
|
||||
/* References: ieee_handler, ieee_sun, ieee_functions, and ieee_flags
|
||||
man pages (SunOS or Solaris)
|
||||
cc -c -I/usr/local/python/include fpectlmodule.c
|
||||
ld -G -o fpectlmodule.so -L/opt/SUNWspro/lib fpectlmodule.o -lsunmath -lm
|
||||
*/
|
||||
#include <math.h>
|
||||
char *mode="exception", *in="all", *out;
|
||||
(void) nonstandard_arithmetic();
|
||||
(void) ieee_flags("clearall",mode,in,&out);
|
||||
(void) ieee_handler("set","common",(sigfpe_handler_type)handler);
|
||||
signal(SIGFPE, handler);
|
||||
|
||||
/*-- HPUX -----------------------------------------------------------------*/
|
||||
#elif defined(__hppa) || defined(hppa)
|
||||
/* References: fpsetmask man page */
|
||||
/* cc -Aa +z -c -I/usr/local/python/include fpectlmodule.c */
|
||||
/* ld -b -o fpectlmodule.sl fpectlmodule.o -lm */
|
||||
#include <math.h>
|
||||
fpsetdefaults();
|
||||
signal(SIGFPE, handler);
|
||||
|
||||
/*-- IBM AIX --------------------------------------------------------------*/
|
||||
#elif defined(__AIX) || defined(_AIX)
|
||||
/* References: fp_trap, fp_enable man pages */
|
||||
#include <fptrap.h>
|
||||
fp_trap(FP_TRAP_SYNC);
|
||||
fp_enable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW);
|
||||
signal(SIGFPE, handler);
|
||||
|
||||
/*-- DEC ALPHA OSF --------------------------------------------------------*/
|
||||
#elif defined(__alpha)
|
||||
/* References: exception_intro, ieee man pages */
|
||||
/* cc -c -I/usr/local/python/include fpectlmodule.c */
|
||||
/* ld -shared -o fpectlmodule.so fpectlmodule.o */
|
||||
#include <machine/fpu.h>
|
||||
unsigned long fp_control =
|
||||
IEEE_TRAP_ENABLE_INV | IEEE_TRAP_ENABLE_DZE | IEEE_TRAP_ENABLE_OVF;
|
||||
ieee_set_fp_control(fp_control);
|
||||
signal(SIGFPE, handler);
|
||||
|
||||
/*-- Cray Unicos ----------------------------------------------------------*/
|
||||
#elif defined(cray)
|
||||
/* UNICOS delivers SIGFPE by default, but no matherr */
|
||||
#ifdef HAS_LIBMSET
|
||||
libmset(-1);
|
||||
#endif
|
||||
signal(SIGFPE, handler);
|
||||
|
||||
/*-- Linux ----------------------------------------------------------------*/
|
||||
#elif defined(linux)
|
||||
/* Linux delivers SIGFPE by default,
|
||||
except for log(0), atanh(-1), 0.^0.
|
||||
*/
|
||||
signal(SIGFPE, handler);
|
||||
|
||||
/*-- NeXT -----------------------------------------------------------------*/
|
||||
#elif defined(NeXT) && defined(m68k) && defined(__GNUC__)
|
||||
/* NeXT needs explicit csr set to generate SIGFPE */
|
||||
asm("fmovel #0x1400,fpcr"); /* set OVFL and ZD bits */
|
||||
signal(SIGFPE, handler);
|
||||
|
||||
/*-- Microsoft Windows, NT ------------------------------------------------*/
|
||||
#elif defined(_MSC_VER)
|
||||
/* Reference: Visual C++ Books Online 4.2,
|
||||
Run-Time Library Reference, _control87, _controlfp */
|
||||
#include <float.h>
|
||||
unsigned int cw = _EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW;
|
||||
(void)_controlfp(0, cw);
|
||||
signal(SIGFPE, handler);
|
||||
|
||||
/*-- Give Up --------------------------------------------------------------*/
|
||||
#else
|
||||
fputs("Operation not implemented\n", stderr);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
static PyObject *turnoff_sigfpe(PyObject *self,PyObject *args)
|
||||
{
|
||||
fputs("Operation not implemented\n", stderr);
|
||||
Py_INCREF (Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static void sigfpe_handler(int signo)
|
||||
{
|
||||
fpe_reset(sigfpe_handler);
|
||||
if(PyFPE_counter) {
|
||||
longjmp(PyFPE_jbuf, 1);
|
||||
} else {
|
||||
Py_FatalError("Unprotected floating point exception");
|
||||
}
|
||||
}
|
||||
|
||||
void initfpectl(void)
|
||||
{
|
||||
PyObject *m, *d;
|
||||
static int already_initialized = 0;
|
||||
|
||||
if (already_initialized) return;
|
||||
m = Py_InitModule("fpectl", fpectl_methods);
|
||||
d = PyModule_GetDict(m);
|
||||
fpe_error = PyString_FromString("fpectl.error");
|
||||
PyDict_SetItemString(d, "error", fpe_error);
|
||||
|
||||
if (PyErr_Occurred())
|
||||
Py_FatalError("Cannot initialize module fpectl");
|
||||
already_initialized = 1;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,228 @@
|
|||
/*
|
||||
---------------------------------------------------------------------
|
||||
/ Copyright (c) 1996. \
|
||||
| The Regents of the University of California. |
|
||||
| All rights reserved. |
|
||||
| |
|
||||
| Permission to use, copy, modify, and distribute this software for |
|
||||
| any purpose without fee is hereby granted, provided that this en- |
|
||||
| tire notice is included in all copies of any software which is or |
|
||||
| includes a copy or modification of this software and in all |
|
||||
| copies of the supporting documentation for such software. |
|
||||
| |
|
||||
| This work was produced at the University of California, Lawrence |
|
||||
| Livermore National Laboratory under contract no. W-7405-ENG-48 |
|
||||
| between the U.S. Department of Energy and The Regents of the |
|
||||
| University of California for the operation of UC LLNL. |
|
||||
| |
|
||||
| DISCLAIMER |
|
||||
| |
|
||||
| This software was prepared as an account of work sponsored by an |
|
||||
| agency of the United States Government. Neither the United States |
|
||||
| Government nor the University of California nor any of their em- |
|
||||
| ployees, makes any warranty, express or implied, or assumes any |
|
||||
| liability or responsibility for the accuracy, completeness, or |
|
||||
| usefulness of any information, apparatus, product, or process |
|
||||
| disclosed, or represents that its use would not infringe |
|
||||
| privately-owned rights. Reference herein to any specific commer- |
|
||||
| cial products, process, or service by trade name, trademark, |
|
||||
| manufacturer, or otherwise, does not necessarily constitute or |
|
||||
| imply its endorsement, recommendation, or favoring by the United |
|
||||
| States Government or the University of California. The views and |
|
||||
| opinions of authors expressed herein do not necessarily state or |
|
||||
| reflect those of the United States Government or the University |
|
||||
| of California, and shall not be used for advertising or product |
|
||||
\ endorsement purposes. /
|
||||
---------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
Floating point exception test module.
|
||||
|
||||
*/
|
||||
|
||||
#include "Python.h"
|
||||
|
||||
static PyObject *fpe_error;
|
||||
void initfpetest(void);
|
||||
static PyObject *test(PyObject *self,PyObject *args);
|
||||
static int db0(void);
|
||||
static int overflow(void);
|
||||
static int nest1(double);
|
||||
static int nest2(double);
|
||||
static double nest3(double);
|
||||
|
||||
static PyMethodDef fpetest_methods[] = {
|
||||
{"test", (PyCFunction) test, 1},
|
||||
{0,0}
|
||||
};
|
||||
|
||||
static PyObject *test(PyObject *self,PyObject *args)
|
||||
{
|
||||
int i = 0, r;
|
||||
|
||||
fprintf(stderr,"Test trapping overflow\n");
|
||||
r = overflow();
|
||||
if(r){
|
||||
fprintf(stderr,"(Note: No exception was raised.)\n");
|
||||
PyErr_Clear();
|
||||
}else{
|
||||
fprintf(stderr,"Trapped:: ");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
i += r;
|
||||
|
||||
fprintf(stderr,"Test trapping division by zero\n");
|
||||
r = db0();
|
||||
if(r){
|
||||
fprintf(stderr,"(Note: No exception was raised.)\n");
|
||||
PyErr_Clear();
|
||||
}else{
|
||||
fprintf(stderr,"Trapped:: ");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
i += r;
|
||||
|
||||
fprintf(stderr,"Test nested protection zones, outer zone\n");
|
||||
r = nest1(0.0);
|
||||
if(r){
|
||||
fprintf(stderr,"(Note: No exception was raised.)\n");
|
||||
PyErr_Clear();
|
||||
}else{
|
||||
fprintf(stderr,"Trapped:: ");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
i += r;
|
||||
|
||||
fprintf(stderr,"Test nested protection zones, inner zone\n");
|
||||
fprintf(stderr,"(Note: Return will apparently come from outer zone.)\n");
|
||||
r = nest1(1.0);
|
||||
if(r){
|
||||
fprintf(stderr,"(Note: No exception was raised.)\n");
|
||||
PyErr_Clear();
|
||||
}else{
|
||||
fprintf(stderr,"Trapped:: ");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
i += r;
|
||||
|
||||
fprintf(stderr,"Test nested protection zones, trailing outer zone\n");
|
||||
r = nest1(2.0);
|
||||
if(r){
|
||||
fprintf(stderr,"(Note: No exception was raised.)\n");
|
||||
PyErr_Clear();
|
||||
}else{
|
||||
fprintf(stderr,"Trapped:: ");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
i += r;
|
||||
|
||||
fprintf(stderr,"Test nested function calls, prior error\n");
|
||||
r = nest2(0.0);
|
||||
if(r){
|
||||
fprintf(stderr,"(Note: No exception was raised.)\n");
|
||||
PyErr_Clear();
|
||||
}else{
|
||||
fprintf(stderr,"Trapped:: ");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
i += r;
|
||||
|
||||
fprintf(stderr,"Test nested function calls, interior error\n");
|
||||
r = nest2(1.0);
|
||||
if(r){
|
||||
fprintf(stderr,"(Note: No exception was raised.)\n");
|
||||
PyErr_Clear();
|
||||
}else{
|
||||
fprintf(stderr,"Trapped:: ");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
i += r;
|
||||
|
||||
fprintf(stderr,"Test nested function calls, trailing error\n");
|
||||
r = nest2(2.0);
|
||||
if(r){
|
||||
fprintf(stderr,"(Note: No exception was raised.)\n");
|
||||
PyErr_Clear();
|
||||
}else{
|
||||
fprintf(stderr,"Trapped:: ");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
i += r;
|
||||
|
||||
fprintf(stderr,"Number of tests failed: %d\n", i);
|
||||
Py_INCREF (Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static int nest1(double x)
|
||||
{
|
||||
double a = 1.0;
|
||||
PyFPE_START_PROTECT("Division by zero, outer zone", return 0)
|
||||
a = 1./x;
|
||||
PyFPE_START_PROTECT("Division by zero, inner zone", return 0)
|
||||
a = 1./(1. - x);
|
||||
PyFPE_END_PROTECT
|
||||
a = 1./(2. - x);
|
||||
PyFPE_END_PROTECT
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int nest2(double x)
|
||||
{
|
||||
double a = 1.0;
|
||||
PyFPE_START_PROTECT("Division by zero, prior error", return 0)
|
||||
a = 1./x;
|
||||
a = nest3(x);
|
||||
a = 1./(2. - x);
|
||||
PyFPE_END_PROTECT
|
||||
return(1);
|
||||
}
|
||||
|
||||
static double nest3(double x)
|
||||
{
|
||||
double result;
|
||||
PyFPE_START_PROTECT("Division by zero, nest3 error", return 0)
|
||||
result = 1./(1. - x);
|
||||
PyFPE_END_PROTECT
|
||||
return result;
|
||||
}
|
||||
|
||||
static int db0(void)
|
||||
{
|
||||
double a = 1.0;
|
||||
PyFPE_START_PROTECT("Division by zero", return 0)
|
||||
a = 1./(a - 1.);
|
||||
PyFPE_END_PROTECT
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int overflow(void)
|
||||
{
|
||||
double a, b = 1.e200;
|
||||
PyFPE_START_PROTECT("Overflow", return 0)
|
||||
a = b*b;
|
||||
PyFPE_END_PROTECT
|
||||
return(1);
|
||||
}
|
||||
|
||||
void initfpetest(void)
|
||||
{
|
||||
PyObject *m, *d;
|
||||
|
||||
m = Py_InitModule("fpetest", fpetest_methods);
|
||||
d = PyModule_GetDict(m);
|
||||
fpe_error = PyString_FromString("fpetest.error");
|
||||
PyDict_SetItemString(d, "error", fpe_error);
|
||||
|
||||
if (PyErr_Occurred())
|
||||
Py_FatalError("Cannot initialize module fpetest");
|
||||
}
|
|
@ -387,8 +387,10 @@ PyObject *args;
|
|||
iclose(image);
|
||||
return NULL;
|
||||
}
|
||||
PyFPE_START_PROTECT("readscaled", return 0)
|
||||
xfac = (float)xsize/(float)xwtd;
|
||||
yfac = (float)ysize/(float)ywtd;
|
||||
PyFPE_END_PROTECT
|
||||
cdatap = PyString_AsString(rv);
|
||||
idatap = (long *)cdatap;
|
||||
|
||||
|
|
|
@ -80,7 +80,9 @@ math_1(args, func)
|
|||
if (! PyArg_Parse(args, "d", &x))
|
||||
return NULL;
|
||||
errno = 0;
|
||||
PyFPE_START_PROTECT("in math_1", return 0)
|
||||
x = (*func)(x);
|
||||
PyFPE_END_PROTECT
|
||||
CHECK(x);
|
||||
if (errno != 0)
|
||||
return math_error();
|
||||
|
@ -97,7 +99,9 @@ math_2(args, func)
|
|||
if (! PyArg_Parse(args, "(dd)", &x, &y))
|
||||
return NULL;
|
||||
errno = 0;
|
||||
PyFPE_START_PROTECT("in math_2", return 0)
|
||||
x = (*func)(x, y);
|
||||
PyFPE_END_PROTECT
|
||||
CHECK(x);
|
||||
if (errno != 0)
|
||||
return math_error();
|
||||
|
@ -173,7 +177,9 @@ math_ldexp(self, args)
|
|||
if (! PyArg_Parse(args, "(dd)", &x, &y))
|
||||
return NULL;
|
||||
errno = 0;
|
||||
PyFPE_START_PROTECT("ldexp", return 0)
|
||||
x = ldexp(x, (int)y);
|
||||
PyFPE_END_PROTECT
|
||||
CHECK(x);
|
||||
if (errno != 0)
|
||||
return math_error();
|
||||
|
|
|
@ -1488,6 +1488,8 @@ mpz_float(self)
|
|||
/* let those bits come, let those bits go,
|
||||
e.g. dismantle mpzscratch, build PyFloatObject */
|
||||
|
||||
/* Can this overflow? Dunno, protect against that possibility. */
|
||||
PyFPE_START_PROTECT("mpz_float", return 0)
|
||||
x = 0.0;
|
||||
mulstate = 1.0;
|
||||
while (i--) {
|
||||
|
@ -1495,6 +1497,7 @@ mpz_float(self)
|
|||
mulstate *= multiplier;
|
||||
mpz_div_2exp(&mpzscratch, &mpzscratch, BITS_PER_MP_LIMB);
|
||||
}
|
||||
PyFPE_END_PROTECT
|
||||
|
||||
assert(mpz_cmp_ui(&mpzscratch, (unsigned long int)0) == 0);
|
||||
mpz_clear(&mpzscratch);
|
||||
|
|
|
@ -661,7 +661,9 @@ strop_atof(self, args)
|
|||
return NULL;
|
||||
}
|
||||
errno = 0;
|
||||
PyFPE_START_PROTECT("strop_atof", return 0)
|
||||
x = strtod(s, &end);
|
||||
PyFPE_END_PROTECT
|
||||
while (*end && isspace(Py_CHARMASK(*end)))
|
||||
end++;
|
||||
if (*end != '\0') {
|
||||
|
|
Loading…
Reference in New Issue