Issue #5914:  Add new C-API function PyOS_string_to_double, to complement
PyOS_double_to_string, and deprecate PyOS_ascii_strtod and PyOS_ascii_atof.
diff --git a/Python/ast.c b/Python/ast.c
index b08cf9b..1c79359 100644
--- a/Python/ast.c
+++ b/Python/ast.c
@@ -3162,18 +3162,18 @@
 #ifndef WITHOUT_COMPLEX
     if (imflag) {
         compl.real = 0.;
-        PyFPE_START_PROTECT("atof", return 0)
-            compl.imag = PyOS_ascii_atof(s);
-        PyFPE_END_PROTECT(c)
-            return PyComplex_FromCComplex(compl);
+        compl.imag = PyOS_string_to_double(s, (char **)&end, NULL);
+        if (compl.imag == -1.0 && PyErr_Occurred())
+            return NULL;
+        return PyComplex_FromCComplex(compl);
     }
     else
 #endif
     {
-        PyFPE_START_PROTECT("atof", return 0)
-            dx = PyOS_ascii_atof(s);
-        PyFPE_END_PROTECT(dx)
-            return PyFloat_FromDouble(dx);
+        dx = PyOS_string_to_double(s, NULL, NULL);
+        if (dx == -1.0 && PyErr_Occurred())
+            return NULL;
+        return PyFloat_FromDouble(dx);
     }
 }
 
diff --git a/Python/dtoa.c b/Python/dtoa.c
index 1d96304..82434bc 100644
--- a/Python/dtoa.c
+++ b/Python/dtoa.c
@@ -61,6 +61,9 @@
  *     that hasn't been MALLOC'ed, private_mem should only be used when k <=
  *     Kmax.
  *
+ *  7. _Py_dg_strtod has been modified so that it doesn't accept strings with
+ *     leading whitespace.
+ *
  ***************************************************************/
 
 /* Please send bug reports for the original dtoa.c code to David M. Gay (dmg
@@ -1355,6 +1358,7 @@
             /* no break */
         case 0:
             goto ret0;
+        /* modify original dtoa.c so that it doesn't accept leading whitespace
         case '\t':
         case '\n':
         case '\v':
@@ -1362,6 +1366,7 @@
         case '\r':
         case ' ':
             continue;
+        */
         default:
             goto break2;
         }
diff --git a/Python/marshal.c b/Python/marshal.c
index 4ad873e..4e9c129 100644
--- a/Python/marshal.c
+++ b/Python/marshal.c
@@ -670,18 +670,17 @@
 		{
 			char buf[256];
 			double dx;
+			retval = NULL;
 			n = r_byte(p);
 			if (n == EOF || r_string(buf, (int)n, p) != n) {
 				PyErr_SetString(PyExc_EOFError,
 					"EOF read where object expected");
-				retval = NULL;
 				break;
 			}
 			buf[n] = '\0';
-			retval = NULL;
-			PyFPE_START_PROTECT("atof", break)
-			dx = PyOS_ascii_atof(buf);
-			PyFPE_END_PROTECT(dx)
+			dx = PyOS_string_to_double(buf, NULL, NULL);
+			if (dx == -1.0 && PyErr_Occurred())
+				break;
 			retval = PyFloat_FromDouble(dx);
 			break;
 		}
@@ -710,29 +709,27 @@
 		{
 			char buf[256];
 			Py_complex c;
-			n = r_byte(p);
-			if (n == EOF || r_string(buf, (int)n, p) != n) {
-				PyErr_SetString(PyExc_EOFError,
-					"EOF read where object expected");
-				retval = NULL;
-				break;
-			}
-			buf[n] = '\0';
 			retval = NULL;
-			PyFPE_START_PROTECT("atof", break;)
-			c.real = PyOS_ascii_atof(buf);
-			PyFPE_END_PROTECT(c)
 			n = r_byte(p);
 			if (n == EOF || r_string(buf, (int)n, p) != n) {
 				PyErr_SetString(PyExc_EOFError,
 					"EOF read where object expected");
-				retval = NULL;
 				break;
 			}
 			buf[n] = '\0';
-			PyFPE_START_PROTECT("atof", break)
-			c.imag = PyOS_ascii_atof(buf);
-			PyFPE_END_PROTECT(c)
+			c.real = PyOS_string_to_double(buf, NULL, NULL);
+			if (c.real == -1.0 && PyErr_Occurred())
+				break;
+			n = r_byte(p);
+			if (n == EOF || r_string(buf, (int)n, p) != n) {
+				PyErr_SetString(PyExc_EOFError,
+					"EOF read where object expected");
+				break;
+			}
+			buf[n] = '\0';
+			c.imag = PyOS_string_to_double(buf, NULL, NULL);
+			if (c.imag == -1.0 && PyErr_Occurred())
+				break;
 			retval = PyComplex_FromCComplex(c);
 			break;
 		}
diff --git a/Python/pystrtod.c b/Python/pystrtod.c
index 1040610..66242d8 100644
--- a/Python/pystrtod.c
+++ b/Python/pystrtod.c
@@ -35,7 +35,7 @@
 #ifndef PY_NO_SHORT_FLOAT_REPR
 
 double
-PyOS_ascii_strtod(const char *nptr, char **endptr)
+_PyOS_ascii_strtod(const char *nptr, char **endptr)
 {
 	double result;
 	_Py_SET_53BIT_PRECISION_HEADER;
@@ -64,7 +64,7 @@
 */
 
 double
-PyOS_ascii_strtod(const char *nptr, char **endptr)
+_PyOS_ascii_strtod(const char *nptr, char **endptr)
 {
 	char *fail_pos;
 	double val = -1.0;
@@ -92,15 +92,10 @@
 	   and underflows */
 	errno = 0;
 
-	/* We process any leading whitespace and the optional sign manually,
-	   then pass the remainder to the system strtod.  This ensures that
-	   the result of an underflow has the correct sign. (bug #1725)  */
-
+	/* We process the optional sign manually, then pass the remainder to
+	   the system strtod.  This ensures that the result of an underflow
+	   has the correct sign. (bug #1725)  */
 	p = nptr;
-	/* Skip leading space */
-	while (Py_ISSPACE(*p))
-		p++;
-
 	/* Process leading sign, if present */
 	if (*p == '-') {
 		negate = 1;
@@ -185,8 +180,7 @@
 		copy = (char *)PyMem_MALLOC(end - digits_pos +
 					    1 + decimal_point_len);
 		if (copy == NULL) {
-			if (endptr)
-				*endptr = (char *)nptr;
+			*endptr = (char *)nptr;
 			errno = ENOMEM;
 			return val;
 		}
@@ -227,27 +221,116 @@
   got_val:
 	if (negate && fail_pos != nptr)
 		val = -val;
-
-	if (endptr)
-		*endptr = fail_pos;
+	*endptr = fail_pos;
 
 	return val;
 
   invalid_string:
-	if (endptr)
-		*endptr = (char*)nptr;
+	*endptr = (char*)nptr;
 	errno = EINVAL;
 	return -1.0;
 }
 
 #endif
 
+/* PyOS_ascii_strtod is DEPRECATED in Python 3.1 */
+
+double
+PyOS_ascii_strtod(const char *nptr, char **endptr)
+{
+	char *fail_pos;
+	const char *p;
+	double x;
+
+	if (PyErr_WarnEx(PyExc_DeprecationWarning,
+			 "PyOS_ascii_strtod and PyOS_ascii_atof are "
+			 "deprecated.  Use PyOS_string_to_double "
+			 "instead.", 1) < 0)
+		return -1.0;
+
+	/* _PyOS_ascii_strtod already does everything that we want,
+	   except that it doesn't parse leading whitespace */
+	p = nptr;
+	while (Py_ISSPACE(*p))
+		p++;
+	x = _PyOS_ascii_strtod(p, &fail_pos);
+	if (fail_pos == p)
+		fail_pos = (char *)nptr;
+	if (endptr)
+		*endptr = (char *)fail_pos;
+	return x;
+}
+
+/* PyOS_ascii_strtod is DEPRECATED in Python 3.1 */
+
 double
 PyOS_ascii_atof(const char *nptr)
 {
 	return PyOS_ascii_strtod(nptr, NULL);
 }
 
+/* PyOS_string_to_double is the recommended replacement for the deprecated
+   PyOS_ascii_strtod and PyOS_ascii_atof functions.  It converts a
+   null-terminated byte string s (interpreted as a string of ASCII characters)
+   to a float.  The string should not have leading or trailing whitespace (in
+   contrast, PyOS_ascii_strtod allows leading whitespace but not trailing
+   whitespace).  The conversion is independent of the current locale.
+
+   If endptr is NULL, try to convert the whole string.  Raise ValueError and
+   return -1.0 if the string is not a valid representation of a floating-point
+   number.
+
+   If endptr is non-NULL, try to convert as much of the string as possible.
+   If no initial segment of the string is the valid representation of a
+   floating-point number then *endptr is set to point to the beginning of the
+   string, -1.0 is returned and again ValueError is raised.
+
+   On overflow (e.g., when trying to convert '1e500' on an IEEE 754 machine),
+   if overflow_exception is NULL then +-Py_HUGE_VAL is returned, and no Python
+   exception is raised.  Otherwise, overflow_exception should point to a
+   a Python exception, this exception will be raised, -1.0 will be returned,
+   and *endptr will point just past the end of the converted value.
+
+   If any other failure occurs (for example lack of memory), -1.0 is returned
+   and the appropriate Python exception will have been set.
+*/
+
+double
+PyOS_string_to_double(const char *s,
+		      char **endptr,
+		      PyObject *overflow_exception)
+{
+	double x, result=-1.0;
+	char *fail_pos;
+
+	errno = 0;
+	PyFPE_START_PROTECT("PyOS_string_to_double", return -1.0)
+	x = _PyOS_ascii_strtod(s, &fail_pos);
+	PyFPE_END_PROTECT(x)
+
+	if (errno == ENOMEM) {
+		PyErr_NoMemory();
+		fail_pos = (char *)s;
+	}
+	else if (!endptr && (fail_pos == s || *fail_pos != '\0'))
+		PyErr_Format(PyExc_ValueError,
+			      "could not convert string to float: "
+			      "%.200s", s);
+	else if (fail_pos == s)
+		PyErr_Format(PyExc_ValueError,
+			      "could not convert string to float: "
+			      "%.200s", s);
+	else if (errno == ERANGE && fabs(x) >= 1.0 && overflow_exception)
+		PyErr_Format(overflow_exception,
+			      "value too large to convert to float: "
+			      "%.200s", s);
+	else
+		result = x;
+
+	if (endptr != NULL)
+		*endptr = fail_pos;
+	return result;
+}
 
 /* Given a string that may have a decimal point in the current
    locale, change it back to a dot.  Since the string cannot get