- New function sys.call_tracing() allows pdb to debug code
  recursively.
- pdb has a new command, "debug", which lets you step through
  arbitrary code from the debugger's (pdb) prompt.
diff --git a/Include/eval.h b/Include/eval.h
index 66638e7..b78dfe0 100644
--- a/Include/eval.h
+++ b/Include/eval.h
@@ -17,6 +17,8 @@
 					PyObject **defs, int defc,
 					PyObject *closure);
 
+PyAPI_FUNC(PyObject *) _PyEval_CallTracing(PyObject *func, PyObject *args);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/Lib/pdb.py b/Lib/pdb.py
index d7215cf..46dff55 100755
--- a/Lib/pdb.py
+++ b/Lib/pdb.py
@@ -523,6 +523,33 @@
                 print '*** Jump failed:', e
     do_j = do_jump
 
+    def do_debug(self, arg):
+        sys.settrace(None)
+        globals = self.curframe.f_globals
+        locals = self.curframe.f_locals
+	p = Pdb()
+	p.prompt = "(%s) " % self.prompt.strip()
+	print "ENTERING RECURSIVE DEBUGGER"
+	sys.call_tracing(p.run, (arg, globals, locals))
+	print "LEAVING RECURSIVE DEBUGGER"
+        sys.settrace(self.trace_dispatch)
+        self.lastcmd = p.lastcmd
+
+    def dont_debug(self, arg):
+        locals = self.curframe.f_locals
+        globals = self.curframe.f_globals
+        try:
+            r = sys.call_tracing(eval, (arg, globals, locals))
+	    print "--- DEBUG RETURNED ---"
+	    if r is not None:
+	        print repr(r)
+        except:
+            t, v = sys.exc_info()[:2]
+            if type(t) == type(''):
+                exc_type_name = t
+            else: exc_type_name = t.__name__
+            print '***', exc_type_name + ':', v
+
     def do_quit(self, arg):
         self.set_quit()
         return 1
@@ -834,6 +861,12 @@
         print """j(ump) lineno
 Set the next line that will be executed."""
 
+    def help_debug(self):
+        print """debug code
+Enter a recursive debugger that steps through the code argument
+(which is an arbitrary expression or statement to be executed
+in the current environment)."""
+
     def help_list(self):
         self.help_l()
 
diff --git a/Misc/NEWS b/Misc/NEWS
index 3ded09e..661c2ca 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -49,6 +49,9 @@
 Extension modules
 -----------------
 
+- New function sys.call_tracing() allows pdb to debug code
+  recursively.
+
 - New function gc.get_referents(obj) returns a list of objects
   directly referenced by obj.  In effect, it exposes what the object's
   tp_traverse slot does, and can be helpful when debugging memory
@@ -86,6 +89,9 @@
 Library
 -------
 
+- pdb has a new command, "debug", which lets you step through
+  arbitrary code from the debugger's (pdb) prompt.
+
 - unittest.failUnlessEqual and its equivalent unittest.assertEqual now
   return 'not a == b' rather than 'a != b'.  This gives the desired
   result for classes that define __eq__ without defining __ne__.
diff --git a/Python/ceval.c b/Python/ceval.c
index f965d38..080b3c1 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -3024,6 +3024,24 @@
 	return result;
 }
 
+PyObject *
+_PyEval_CallTracing(PyObject *func, PyObject *args)
+{
+	PyFrameObject *frame = PyEval_GetFrame();
+	PyThreadState *tstate = frame->f_tstate;
+	int save_tracing = tstate->tracing;
+	int save_use_tracing = tstate->use_tracing;
+	PyObject *result;
+
+	tstate->tracing = 0;
+	tstate->use_tracing = ((tstate->c_tracefunc != NULL)
+			       || (tstate->c_profilefunc != NULL));
+	result = PyObject_Call(func, args, NULL);
+	tstate->tracing = save_tracing;
+	tstate->use_tracing = save_use_tracing;
+	return result;
+}
+
 static int
 maybe_call_line_trace(Py_tracefunc func, PyObject *obj, 
 		      PyFrameObject *frame, int *instr_lb, int *instr_ub)
diff --git a/Python/sysmodule.c b/Python/sysmodule.c
index fa7f3c4..50b9912 100644
--- a/Python/sysmodule.c
+++ b/Python/sysmodule.c
@@ -17,6 +17,7 @@
 #include "Python.h"
 #include "compile.h"
 #include "frameobject.h"
+#include "eval.h"
 
 #include "osdefs.h"
 
@@ -609,6 +610,23 @@
 	return (PyObject*)f;
 }
 
+PyDoc_STRVAR(call_tracing_doc,
+"call_tracing(func, args) -> object\n\
+\n\
+Call func(*args), while tracing is enabled.  The tracing state is\n\
+saved, and restored afterwards.  This is intended to be called from\n\
+a debugger from a checkpoint, to recursively debug some other code."
+);
+
+static PyObject *
+sys_call_tracing(PyObject *self, PyObject *args)
+{
+	PyObject *func, *funcargs;
+	if (!PyArg_ParseTuple(args, "OO:call_tracing", &func, &funcargs))
+		return NULL;
+	return _PyEval_CallTracing(func, funcargs);
+}
+
 PyDoc_STRVAR(callstats_doc,
 "callstats() -> tuple of integers\n\
 \n\
@@ -700,6 +718,7 @@
 	{"setrecursionlimit", sys_setrecursionlimit, METH_VARARGS,
 	 setrecursionlimit_doc},
 	{"settrace",	sys_settrace, METH_O, settrace_doc},
+	{"call_tracing", sys_call_tracing, METH_VARARGS, call_tracing_doc},
 	{NULL,		NULL}		/* sentinel */
 };