summaryrefslogtreecommitdiff
path: root/lisp/emacs-lisp/debug.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/emacs-lisp/debug.el')
-rw-r--r--lisp/emacs-lisp/debug.el62
1 files changed, 32 insertions, 30 deletions
diff --git a/lisp/emacs-lisp/debug.el b/lisp/emacs-lisp/debug.el
index 5411088189d..e0b6ca31b9e 100644
--- a/lisp/emacs-lisp/debug.el
+++ b/lisp/emacs-lisp/debug.el
@@ -237,12 +237,11 @@ the debugger will not be entered."
(unwind-protect
(save-excursion
(when (eq (car debugger-args) 'debug)
- ;; Skip the frames for backtrace-debug, byte-code,
- ;; debug--implement-debug-on-entry and the advice's `apply'.
- (backtrace-debug 4 t)
- ;; Place an extra debug-on-exit for macro's.
- (when (eq 'lambda (car-safe (cadr (backtrace-frame 4))))
- (backtrace-debug 5 t)))
+ (let ((base (debugger--backtrace-base)))
+ (backtrace-debug 1 t base) ;FIXME!
+ ;; Place an extra debug-on-exit for macro's.
+ (when (eq 'lambda (car-safe (cadr (backtrace-frame 1 base))))
+ (backtrace-debug 2 t base))))
(with-current-buffer debugger-buffer
(unless (derived-mode-p 'debugger-mode)
(debugger-mode))
@@ -343,11 +342,10 @@ Make functions into cross-reference buttons if DO-XREFS is non-nil."
(defun debugger-setup-buffer (args)
"Initialize the `*Backtrace*' buffer for entry to the debugger.
That buffer should be current already and in `debugger-mode'."
- (setq backtrace-frames (nthcdr
- ;; Remove debug--implement-debug-on-entry and the
- ;; advice's `apply' frame.
- (if (eq (car args) 'debug) 3 1)
- (backtrace-get-frames 'debug)))
+ (setq backtrace-frames
+ ;; The `base' frame is the one that gets index 0 and it is the entry to
+ ;; the debugger, so drop it with `cdr'.
+ (cdr (backtrace-get-frames (debugger--backtrace-base))))
(when (eq (car-safe args) 'exit)
(setq debugger-value (nth 1 args))
(setf (cl-getf (backtrace-frame-flags (car backtrace-frames))
@@ -477,26 +475,29 @@ removes itself from that hook."
(setq debugger-jumping-flag nil)
(remove-hook 'post-command-hook 'debugger-reenable))
-(defun debugger-frame-number (&optional skip-base)
+(defun debugger-frame-number ()
"Return number of frames in backtrace before the one point points at."
- (let ((index (backtrace-get-index))
- (count 0))
+ (let ((index (backtrace-get-index)))
(unless index
(error "This line is not a function call"))
- (unless skip-base
- (while (not (eq (cadr (backtrace-frame count)) 'debug))
- (setq count (1+ count)))
- ;; Skip debug--implement-debug-on-entry frame.
- (when (eq 'debug--implement-debug-on-entry
- (cadr (backtrace-frame (1+ count))))
- (setq count (+ 2 count))))
- (+ count index)))
+ ;; We have 3 representations of the backtrace: the real in C in `specpdl',
+ ;; the one stored in `backtrace-frames' and the textual version in
+ ;; the buffer. Check here that the one from `backtrace-frames' is in sync
+ ;; with the one from `specpdl'.
+ (cl-assert (equal (backtrace-frame-fun (nth index backtrace-frames))
+ (nth 1 (backtrace-frame (1+ index)
+ (debugger--backtrace-base)))))
+ ;; The `base' frame is the one that gets index 0 and it is the entry to
+ ;; the debugger, so the first non-debugger frame is 1.
+ ;; This `+1' skips the same frame as the `cdr' in
+ ;; `debugger-setup-buffer'.
+ (1+ index)))
(defun debugger-frame ()
"Request entry to debugger when this frame exits.
Applies to the frame whose line point is on in the backtrace."
(interactive)
- (backtrace-debug (debugger-frame-number) t)
+ (backtrace-debug (debugger-frame-number) t (debugger--backtrace-base))
(setf
(cl-getf (backtrace-frame-flags (nth (backtrace-get-index) backtrace-frames))
:debug-on-exit)
@@ -507,7 +508,7 @@ Applies to the frame whose line point is on in the backtrace."
"Do not enter debugger when this frame exits.
Applies to the frame whose line point is on in the backtrace."
(interactive)
- (backtrace-debug (debugger-frame-number) nil)
+ (backtrace-debug (debugger-frame-number) nil (debugger--backtrace-base))
(setf
(cl-getf (backtrace-frame-flags (nth (backtrace-get-index) backtrace-frames))
:debug-on-exit)
@@ -526,10 +527,8 @@ Applies to the frame whose line point is on in the backtrace."
(defun debugger--backtrace-base ()
"Return the function name that marks the top of the backtrace.
See `backtrace-frame'."
- (cond ((eq 'debug--implement-debug-on-entry
- (cadr (backtrace-frame 1 'debug)))
- 'debug--implement-debug-on-entry)
- (t 'debug)))
+ (or (cadr (memq :backtrace-base debugger-args))
+ #'debug))
(defun debugger-eval-expression (exp &optional nframe)
"Eval an expression, in an environment like that outside the debugger.
@@ -537,7 +536,7 @@ The environment used is the one when entering the activation frame at point."
(interactive
(list (read--expression "Eval in stack frame: ")))
(let ((nframe (or nframe
- (condition-case nil (1+ (debugger-frame-number 'skip-base))
+ (condition-case nil (debugger-frame-number)
(error 0)))) ;; If on first line.
(base (debugger--backtrace-base)))
(debugger-env-macro
@@ -670,7 +669,10 @@ functions to break on entry."
(if (or inhibit-debug-on-entry debugger-jumping-flag)
nil
(let ((inhibit-debug-on-entry t))
- (funcall debugger 'debug))))
+ (funcall debugger 'debug :backtrace-base
+ ;; An offset of 1 because we need to skip the advice
+ ;; OClosure that called us.
+ '(1 . debug--implement-debug-on-entry)))))
;;;###autoload
(defun debug-on-entry (function)