X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcode%2Fdebug.lisp;h=c89794beee705ac78280b26aaf7208d46ab331bf;hb=ae469bbdd046b46348538f1b69db6e6b044be52f;hp=ecbf3e8e809c01c1bc54f9e4a2fa418962c92d17;hpb=f22ad70037030c07074327cf239bd84dc17b44b6;p=sbcl.git diff --git a/src/code/debug.lisp b/src/code/debug.lisp index ecbf3e8..c89794b 100644 --- a/src/code/debug.lisp +++ b/src/code/debug.lisp @@ -482,20 +482,24 @@ is how many frames to show." (nreverse (mapcar #'cdr *debug-print-variable-alist*)) (apply fun rest))))))) +;;; This function is not inlined so it shows up in the backtrace; that +;;; can be rather handy when one has to debug the interplay between +;;; *INVOKE-DEBUGGER-HOOK* and *DEBUGGER-HOOK*. +(declaim (notinline run-hook)) +(defun run-hook (variable condition) + (let ((old-hook (symbol-value variable))) + (when old-hook + (progv (list variable) (list nil) + (funcall old-hook condition old-hook))))) + (defun invoke-debugger (condition) #!+sb-doc "Enter the debugger." ;; call *INVOKE-DEBUGGER-HOOK* first, so that *DEBUGGER-HOOK* is not ;; called when the debugger is disabled - (let ((old-hook *invoke-debugger-hook*)) - (when old-hook - (let ((*invoke-debugger-hook* nil)) - (funcall old-hook condition old-hook)))) - (let ((old-hook *debugger-hook*)) - (when old-hook - (let ((*debugger-hook* nil)) - (funcall old-hook condition old-hook)))) + (run-hook '*invoke-debugger-hook* condition) + (run-hook '*debugger-hook* condition) ;; We definitely want *PACKAGE* to be of valid type. ;; @@ -663,6 +667,8 @@ reset to ~S." ;;; halt-on-failures and prompt-on-failures modes, suitable for ;;; noninteractive and interactive use respectively (defun disable-debugger () + "When invoked, this function will turn off both the SBCL debugger +and LDB (the low-level debugger). See also ENABLE-DEBUGGER." ;; *DEBUG-IO* used to be set here to *ERROR-OUTPUT* which is sort ;; of unexpected but mostly harmless, but then ENABLE-DEBUGGER had ;; to set it to a suitable value again and be very careful, @@ -677,6 +683,7 @@ reset to ~S." (function sb!alien:void)))) (defun enable-debugger () + "Restore the debugger if it has been turned off by DISABLE-DEBUGGER." (when (eql *invoke-debugger-hook* 'debugger-disabled-hook) (setf *invoke-debugger-hook* *old-debugger-hook* *old-debugger-hook* nil)) @@ -806,9 +813,26 @@ reset to ~S." (t (funcall cmd-fun)))))))))))) +(defvar *auto-eval-in-frame* t + #!+sb-doc + "When set (the default), evaluations in the debugger's command loop occur + relative to the current frame's environment without the need of debugger + forms that explicitly control this kind of evaluation.") + +(defun debug-eval (expr) + (cond ((not (and (fboundp 'compile) *auto-eval-in-frame*)) + (eval expr)) + ((frame-has-debug-vars-p *current-frame*) + (sb!di:eval-in-frame *current-frame* expr)) + (t + (format *debug-io* "; No debug variables for current frame: ~ + using EVAL instead of EVAL-IN-FRAME.~%") + (eval expr)))) + (defun debug-eval-print (expr) (/noshow "entering DEBUG-EVAL-PRINT" expr) - (let ((values (multiple-value-list (interactive-eval expr)))) + (let ((values (multiple-value-list + (interactive-eval expr :eval #'debug-eval)))) (/noshow "done with EVAL in DEBUG-EVAL-PRINT") (dolist (value values) (fresh-line *debug-io*) @@ -1530,6 +1554,11 @@ reset to ~S." #!-unwind-to-frame-and-call-vop (find 'sb!c:debug-catch-tag (sb!di::frame-catches frame) :key #'car)) +(defun frame-has-debug-vars-p (frame) + (sb!di:debug-var-info-available + (sb!di:code-location-debug-fun + (sb!di:frame-code-location frame)))) + ;; Hack: ensure that *U-T-F-F* has a tls index. #!+unwind-to-frame-and-call-vop (let ((sb!vm::*unwind-to-frame-function* (lambda ()))))