Add optional 4th argument to [r]find and [r]index (end of slice).
diff --git a/Doc/lib/libstring.tex b/Doc/lib/libstring.tex
index af3fd58..80222c1 100644
--- a/Doc/lib/libstring.tex
+++ b/Doc/lib/libstring.tex
@@ -103,24 +103,27 @@
 sequences.
 \end{funcdesc}
 
-\begin{funcdesc}{find}{s\, sub\optional{\, start}}
-Return the lowest index in \var{s} not smaller than \var{start} where the
-substring \var{sub} is found.  Return \code{-1} when \var{sub}
-does not occur as a substring of \var{s} with index at least \var{start}.
+\begin{funcdesc}{find}{s\, sub\optional{\, start\optional{\,end}}}
+Return the lowest index in \var{s} not smaller than \var{start} and not 
+greater than \var{end} where the substring \var{sub} is found.  Return
+\code{-1} when \var{sub} does not occur as a substring of \var{s} with
+index at least \var{start} and less than \var{end}.
 If \var{start} is omitted, it defaults to \code{0}.  If \var{start} is
 negative, \code{len(\var{s})} is added.
+If \var{end} is omitted, it defaults to \code{len(\var{s})}.  If
+\var{end} is negative, \code{len(\var{s})} is added.
 \end{funcdesc}
 
-\begin{funcdesc}{rfind}{s\, sub\optional{\, start}}
+\begin{funcdesc}{rfind}{s\, sub\optional{\, start\optional{\,end}}}
 Like \code{find} but find the highest index.
 \end{funcdesc}
 
-\begin{funcdesc}{index}{s\, sub\optional{\, start}}
+\begin{funcdesc}{index}{s\, sub\optional{\, start\optional{\,end}}}
 Like \code{find} but raise \code{ValueError} when the substring is
 not found.
 \end{funcdesc}
 
-\begin{funcdesc}{rindex}{s\, sub\optional{\, start}}
+\begin{funcdesc}{rindex}{s\, sub\optional{\, start\optional{\,end}}}
 Like \code{rfind} but raise \code{ValueError} when the substring is
 not found.
 \end{funcdesc}
diff --git a/Doc/libstring.tex b/Doc/libstring.tex
index af3fd58..80222c1 100644
--- a/Doc/libstring.tex
+++ b/Doc/libstring.tex
@@ -103,24 +103,27 @@
 sequences.
 \end{funcdesc}
 
-\begin{funcdesc}{find}{s\, sub\optional{\, start}}
-Return the lowest index in \var{s} not smaller than \var{start} where the
-substring \var{sub} is found.  Return \code{-1} when \var{sub}
-does not occur as a substring of \var{s} with index at least \var{start}.
+\begin{funcdesc}{find}{s\, sub\optional{\, start\optional{\,end}}}
+Return the lowest index in \var{s} not smaller than \var{start} and not 
+greater than \var{end} where the substring \var{sub} is found.  Return
+\code{-1} when \var{sub} does not occur as a substring of \var{s} with
+index at least \var{start} and less than \var{end}.
 If \var{start} is omitted, it defaults to \code{0}.  If \var{start} is
 negative, \code{len(\var{s})} is added.
+If \var{end} is omitted, it defaults to \code{len(\var{s})}.  If
+\var{end} is negative, \code{len(\var{s})} is added.
 \end{funcdesc}
 
-\begin{funcdesc}{rfind}{s\, sub\optional{\, start}}
+\begin{funcdesc}{rfind}{s\, sub\optional{\, start\optional{\,end}}}
 Like \code{find} but find the highest index.
 \end{funcdesc}
 
-\begin{funcdesc}{index}{s\, sub\optional{\, start}}
+\begin{funcdesc}{index}{s\, sub\optional{\, start\optional{\,end}}}
 Like \code{find} but raise \code{ValueError} when the substring is
 not found.
 \end{funcdesc}
 
-\begin{funcdesc}{rindex}{s\, sub\optional{\, start}}
+\begin{funcdesc}{rindex}{s\, sub\optional{\, start\optional{\,end}}}
 Like \code{rfind} but raise \code{ValueError} when the substring is
 not found.
 \end{funcdesc}
diff --git a/Lib/string.py b/Lib/string.py
index 687518d..d3ab88f 100644
--- a/Lib/string.py
+++ b/Lib/string.py
@@ -120,15 +120,17 @@
 	return res[len(sep):]
 
 # Find substring, raise exception if not found
-def index(s, sub, i = 0):
-	res = find(s, sub, i)
+def index(s, sub, i = 0, last=None):
+	if last == None: last = len(s)
+	res = find(s, sub, i, last)
 	if res < 0:
 		raise ValueError, 'substring not found in string.index'
 	return res
 
 # Find last substring, raise exception if not found
-def rindex(s, sub, i = 0):
-	res = rfind(s, sub, i)
+def rindex(s, sub, i = 0, last=None):
+	if last == None: last = len(s)
+	res = rfind(s, sub, i, last)
 	if res < 0:
 		raise ValueError, 'substring not found in string.index'
 	return res
@@ -149,20 +151,34 @@
 	return r
 
 # Find substring, return -1 if not found
-def find(s, sub, i = 0):
-	if i < 0: i = max(0, i + len(s))
+def find(s, sub, i = 0, last=None):
+	Slen = len(s)  # cache this value, for speed
+	if last == None:
+		last = Slen
+	elif last < 0:
+		last = max(0, last + Slen)
+	elif last > Slen:
+		last = Slen
+	if i < 0: i = max(0, i + Slen)
 	n = len(sub)
-	m = len(s) + 1 - n
+	m = last + 1 - n
 	while i < m:
 		if sub == s[i:i+n]: return i
 		i = i+1
 	return -1
 
 # Find last substring, return -1 if not found
-def rfind(s, sub, i = 0):
-	if i < 0: i = max(0, i + len(s))
+def rfind(s, sub, i = 0, last=None):
+	Slen = len(s)  # cache this value, for speed
+	if last == None:
+		last = Slen
+	elif last < 0:
+		last = max(0, last + Slen)
+	elif last > Slen:
+		last = Slen
+	if i < 0: i = max(0, i + Slen)
 	n = len(sub)
-	m = len(s) + 1 - n
+	m = last + 1 - n
 	r = -1
 	while i < m:
 		if sub == s[i:i+n]: r = i
diff --git a/Lib/stringold.py b/Lib/stringold.py
index 687518d..d3ab88f 100644
--- a/Lib/stringold.py
+++ b/Lib/stringold.py
@@ -120,15 +120,17 @@
 	return res[len(sep):]
 
 # Find substring, raise exception if not found
-def index(s, sub, i = 0):
-	res = find(s, sub, i)
+def index(s, sub, i = 0, last=None):
+	if last == None: last = len(s)
+	res = find(s, sub, i, last)
 	if res < 0:
 		raise ValueError, 'substring not found in string.index'
 	return res
 
 # Find last substring, raise exception if not found
-def rindex(s, sub, i = 0):
-	res = rfind(s, sub, i)
+def rindex(s, sub, i = 0, last=None):
+	if last == None: last = len(s)
+	res = rfind(s, sub, i, last)
 	if res < 0:
 		raise ValueError, 'substring not found in string.index'
 	return res
@@ -149,20 +151,34 @@
 	return r
 
 # Find substring, return -1 if not found
-def find(s, sub, i = 0):
-	if i < 0: i = max(0, i + len(s))
+def find(s, sub, i = 0, last=None):
+	Slen = len(s)  # cache this value, for speed
+	if last == None:
+		last = Slen
+	elif last < 0:
+		last = max(0, last + Slen)
+	elif last > Slen:
+		last = Slen
+	if i < 0: i = max(0, i + Slen)
 	n = len(sub)
-	m = len(s) + 1 - n
+	m = last + 1 - n
 	while i < m:
 		if sub == s[i:i+n]: return i
 		i = i+1
 	return -1
 
 # Find last substring, return -1 if not found
-def rfind(s, sub, i = 0):
-	if i < 0: i = max(0, i + len(s))
+def rfind(s, sub, i = 0, last=None):
+	Slen = len(s)  # cache this value, for speed
+	if last == None:
+		last = Slen
+	elif last < 0:
+		last = max(0, last + Slen)
+	elif last > Slen:
+		last = Slen
+	if i < 0: i = max(0, i + Slen)
 	n = len(sub)
-	m = len(s) + 1 - n
+	m = last + 1 - n
 	r = -1
 	while i < m:
 		if sub == s[i:i+n]: r = i
diff --git a/Modules/stropmodule.c b/Modules/stropmodule.c
index 8ddf37d..9594837 100644
--- a/Modules/stropmodule.c
+++ b/Modules/stropmodule.c
@@ -33,6 +33,12 @@
 
 #include "Python.h"
 
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#else
+#define INT_MAX 2147483647
+#endif
+
 #include <ctype.h>
 /* XXX This file assumes that the <ctype.h> is*() functions
    XXX are defined for all 8-bit characters! */
@@ -286,11 +292,17 @@
 	PyObject *args;
 {
 	char *s, *sub;
-	int len, n, i = 0;
+	int len, n, i = 0, last = INT_MAX;
 
-	if (!PyArg_ParseTuple(args, "s#s#|i", &s, &len, &sub, &n, &i))
+	if (!PyArg_ParseTuple(args, "s#s#|ii", &s, &len, &sub, &n, &i, &last))
 		return NULL;
 
+	if (last > len)
+		last = len;
+	if (last < 0)
+		last += len;
+	if (last < 0)
+		last = 0;
 	if (i < 0)
 		i += len;
 	if (i < 0)
@@ -299,8 +311,8 @@
 	if (n == 0)
 		return PyInt_FromLong((long)i);
 
-	len -= n;
-	for (; i <= len; ++i)
+	last -= n;
+	for (; i <= last; ++i)
 		if (s[i] == sub[0] &&
 		    (n == 1 || memcmp(&s[i+1], &sub[1], n-1) == 0))
 			return PyInt_FromLong((long)i);
@@ -316,20 +328,26 @@
 {
 	char *s, *sub;
 	int len, n, j;
-	int i = 0;
+	int i = 0, last = INT_MAX;
 
-	if (!PyArg_ParseTuple(args, "s#s#|i", &s, &len, &sub, &n, &i))
+	if (!PyArg_ParseTuple(args, "s#s#|ii", &s, &len, &sub, &n, &i, &last))
 		return NULL;
 
+	if (last > len)
+		last = len;
+	if (last < 0)
+		last += len;
+	if (last < 0)
+		last = 0;
 	if (i < 0)
 		i += len;
 	if (i < 0)
 		i = 0;
 
 	if (n == 0)
-		return PyInt_FromLong((long)len);
+		return PyInt_FromLong((long)last);
 
-	for (j = len-n; j >= i; --j)
+	for (j = last-n; j >= i; --j)
 		if (s[j] == sub[0] &&
 		    (n == 1 || memcmp(&s[j+1], &sub[1], n-1) == 0))
 			return PyInt_FromLong((long)j);
@@ -663,7 +681,7 @@
 	errno = 0;
 	PyFPE_START_PROTECT("strop_atof", return 0)
 	x = strtod(s, &end);
-	PyFPE_END_PROTECT
+	PyFPE_END_PROTECT(x)
 	while (*end && isspace(Py_CHARMASK(*end)))
 		end++;
 	if (*end != '\0') {