* string.py: added rindex(), rfind(); changed index() to interpret
  negative start indices starting from the right.
* ftplib.py: debug() -> set_debuglevel(); change demo to use __init__().
* os.py: added execl, execlp, and execvp.
* lambda.py: removed (now that we have built-in map, reduce, bagof, lambda)
* test_b{1,2}.py, testall.out: added tests for bagof, lambda, map, reduce
* commands.py: use os, not posix
* test_grammar.py: make it easy to disable non-portable int overflow tests
* dis.py: don't abuse range()
diff --git a/Lib/string.py b/Lib/string.py
index 764c396..afe5bec 100644
--- a/Lib/string.py
+++ b/Lib/string.py
@@ -100,6 +100,7 @@
 		if len(args) > 1:
 			raise TypeError, 'string.index(): too many args'
 		i = args[0]
+		if i < 0: i = i + len(s)
 	else:
 		i = 0
 	n = len(sub)
@@ -109,6 +110,25 @@
 		i = i+1
 	raise index_error, (s, sub) + args
 
+# Find last substring, raise exception if not found
+def rindex(s, sub, *args):
+	if args:
+		if len(args) > 1:
+			raise TypeError, 'string.rindex(): too many args'
+		i = args[0]
+		if i < 0: i = i + len(s)
+	else:
+		i = 0
+	n = len(sub)
+	m = len(s) + 1 - n
+	r = None
+	while i < m:
+		if sub == s[i:i+n]: r = i
+		i = i+1
+	if r is None:
+		raise index_error, (s, sub) + args
+	return r
+
 # Find substring, return -1 if not found
 def find(*args):
 	try:
@@ -116,6 +136,13 @@
 	except index_error:
 		return -1
 
+# Find last substring, return -1 if not found
+def rfind(*args):
+	try:
+		return apply(rindex, args)
+	except index_error:
+		return -1
+
 # Convert string to float
 atof_error = 'non-float argument to string.atof'
 def atof(str):