1
1
; ;; debug.el --- debuggers and related commands for Emacs -*- lexical-binding : t -*-
2
2
3
- ; ; Copyright (C) 1985-1986, 1994, 2001-2024 Free Software Foundation,
3
+ ; ; Copyright (C) 1985-1986, 1994, 2001-2023 Free Software Foundation,
4
4
; ; Inc.
5
5
6
6
; ; Maintainer: emacs-devel@gnu.org
@@ -153,24 +153,11 @@ where CAUSE can be:
153
153
(insert (debugger--buffer-state-content state)))
154
154
(goto-char (debugger--buffer-state-pos state)))
155
155
156
- (defvar debugger--last-error nil )
157
-
158
- (defun debugger--duplicate-p (args )
159
- (pcase args
160
- (`(error , err . , _ ) (and (consp err) (eq err debugger--last-error)))))
161
-
162
156
;;;### autoload
163
157
(setq debugger 'debug )
164
158
;;;### autoload
165
159
(defun debug (&rest args )
166
160
" Enter debugger. \\ <debugger-mode-map>`\\[debugger-continue]' returns from the debugger.
167
-
168
- In interactive sessions, this switches to a backtrace buffer and shows
169
- the Lisp backtrace of function calls there. In batch mode (more accurately,
170
- when `noninteractive' is non-nil), it shows the Lisp backtrace on the
171
- standard error stream (unless `backtrace-on-error-noninteractive' is nil),
172
- and then kills Emacs, causing it to exit with a negative exit code.
173
-
174
161
Arguments are mainly for use when this is called from the internals
175
162
of the evaluator.
176
163
@@ -181,14 +168,9 @@ first will be printed into the backtrace buffer.
181
168
If `inhibit-redisplay' is non-nil when this function is called,
182
169
the debugger will not be entered."
183
170
(interactive )
184
- (if (or inhibit-redisplay
185
- (debugger--duplicate-p args))
186
- ; ; Don't really try to enter debugger within an eval from redisplay
187
- ; ; or if we already popper into the debugger for this error,
188
- ; ; which can happen when we have several nested `handler-bind' s that
189
- ; ; want to invoke the debugger.
171
+ (if inhibit-redisplay
172
+ ; ; Don't really try to enter debugger within an eval from redisplay.
190
173
debugger-value
191
- (setq debugger--last-error nil )
192
174
(let ((non-interactive-frame
193
175
(or noninteractive ; FIXME: Presumably redundant.
194
176
; ; If we're in the initial-frame (where `message' just
@@ -211,7 +193,7 @@ the debugger will not be entered."
211
193
(let (debugger-value
212
194
(debugger-previous-state
213
195
(if (get-buffer " *Backtrace*" )
214
- (with-current-buffer " *Backtrace*"
196
+ (with-current-buffer ( get-buffer " *Backtrace*" )
215
197
(debugger--save-buffer-state))))
216
198
(debugger-args args)
217
199
(debugger-buffer (get-buffer-create " *Backtrace*" ))
@@ -248,11 +230,12 @@ the debugger will not be entered."
248
230
(unwind-protect
249
231
(save-excursion
250
232
(when (eq (car debugger-args) 'debug )
251
- (let ((base (debugger--backtrace-base )))
252
- (backtrace-debug 1 t base) ; FIXME!
253
- ; ; Place an extra debug-on-exit for macro's.
254
- (when (eq 'lambda (car-safe (cadr (backtrace-frame 1 base))))
255
- (backtrace-debug 2 t base))))
233
+ ; ; Skip the frames for backtrace-debug, byte-code,
234
+ ; ; debug--implement-debug-on-entry and the advice's `apply' .
235
+ (backtrace-debug 4 t )
236
+ ; ; Place an extra debug-on-exit for macro's.
237
+ (when (eq 'lambda (car-safe (cadr (backtrace-frame 4 ))))
238
+ (backtrace-debug 5 t )))
256
239
(with-current-buffer debugger-buffer
257
240
(unless (derived-mode-p 'debugger-mode )
258
241
(debugger-mode ))
@@ -329,12 +312,6 @@ the debugger will not be entered."
329
312
(backtrace-mode))))
330
313
(with-timeout-unsuspend debugger-with-timeout-suspend)
331
314
(set-match-data debugger-outer-match-data)))
332
- (when (eq 'error (car-safe debugger-args))
333
- ; ; Remember the error we just debugged, to avoid re-entering
334
- ; ; the debugger if some higher-up `handler-bind' invokes us
335
- ; ; again, oblivious that the error was already debugged from
336
- ; ; a more deeply nested `handler-bind' .
337
- (setq debugger--last-error (nth 1 debugger-args)))
338
315
(setq debug-on-next-call debugger-step-after-exit)
339
316
debugger-value))))
340
317
@@ -359,10 +336,11 @@ Make functions into cross-reference buttons if DO-XREFS is non-nil."
359
336
(defun debugger-setup-buffer (args )
360
337
" Initialize the `*Backtrace*' buffer for entry to the debugger.
361
338
That buffer should be current already and in `debugger-mode' ."
362
- (setq backtrace-frames
363
- ; ; The `base' frame is the one that gets index 0 and it is the entry to
364
- ; ; the debugger, so drop it with `cdr' .
365
- (cdr (backtrace-get-frames (debugger--backtrace-base ))))
339
+ (setq backtrace-frames (nthcdr
340
+ ; ; Remove debug--implement-debug-on-entry and the
341
+ ; ; advice's `apply' frame.
342
+ (if (eq (car args) 'debug ) 3 1 )
343
+ (backtrace-get-frames 'debug )))
366
344
(when (eq (car-safe args) 'exit )
367
345
(setq debugger-value (nth 1 args))
368
346
(setf (cl-getf (backtrace-frame-flags (car backtrace-frames))
@@ -492,29 +470,26 @@ removes itself from that hook."
492
470
(setq debugger-jumping-flag nil )
493
471
(remove-hook 'post-command-hook 'debugger-reenable ))
494
472
495
- (defun debugger-frame-number ()
473
+ (defun debugger-frame-number (&optional skip-base )
496
474
" Return number of frames in backtrace before the one point points at."
497
- (let ((index (backtrace-get-index)))
475
+ (let ((index (backtrace-get-index))
476
+ (count 0 ))
498
477
(unless index
499
478
(error " This line is not a function call " ))
500
- ; ; We have 3 representations of the backtrace: the real in C in `specpdl' ,
501
- ; ; the one stored in `backtrace-frames' and the textual version in
502
- ; ; the buffer. Check here that the one from `backtrace-frames' is in sync
503
- ; ; with the one from `specpdl' .
504
- (cl-assert (equal (backtrace-frame-fun (nth index backtrace-frames))
505
- (nth 1 (backtrace-frame (1+ index)
506
- (debugger--backtrace-base )))))
507
- ; ; The `base' frame is the one that gets index 0 and it is the entry to
508
- ; ; the debugger, so the first non-debugger frame is 1.
509
- ; ; This `+1' skips the same frame as the `cdr' in
510
- ; ; `debugger-setup-buffer' .
511
- (1+ index)))
479
+ (unless skip-base
480
+ (while (not (eq (cadr (backtrace-frame count)) 'debug ))
481
+ (setq count (1+ count)))
482
+ ; ; Skip debug--implement-debug-on-entry frame.
483
+ (when (eq 'debug--implement-debug-on-entry
484
+ (cadr (backtrace-frame (1+ count))))
485
+ (setq count (+ 2 count))))
486
+ (+ count index)))
512
487
513
488
(defun debugger-frame ()
514
489
" Request entry to debugger when this frame exits.
515
490
Applies to the frame whose line point is on in the backtrace."
516
491
(interactive )
517
- (backtrace-debug (debugger-frame-number ) t ( debugger--backtrace-base ) )
492
+ (backtrace-debug (debugger-frame-number ) t )
518
493
(setf
519
494
(cl-getf (backtrace-frame-flags (nth (backtrace-get-index) backtrace-frames))
520
495
:debug-on-exit )
@@ -525,7 +500,7 @@ Applies to the frame whose line point is on in the backtrace."
525
500
" Do not enter debugger when this frame exits.
526
501
Applies to the frame whose line point is on in the backtrace."
527
502
(interactive )
528
- (backtrace-debug (debugger-frame-number ) nil ( debugger--backtrace-base ) )
503
+ (backtrace-debug (debugger-frame-number ) nil )
529
504
(setf
530
505
(cl-getf (backtrace-frame-flags (nth (backtrace-get-index) backtrace-frames))
531
506
:debug-on-exit )
@@ -544,16 +519,18 @@ Applies to the frame whose line point is on in the backtrace."
544
519
(defun debugger--backtrace-base ()
545
520
" Return the function name that marks the top of the backtrace.
546
521
See `backtrace-frame' ."
547
- (or (cadr (memq :backtrace-base debugger-args))
548
- #'debug ))
522
+ (cond ((eq 'debug--implement-debug-on-entry
523
+ (cadr (backtrace-frame 1 'debug )))
524
+ 'debug--implement-debug-on-entry )
525
+ (t 'debug )))
549
526
550
527
(defun debugger-eval-expression (exp &optional nframe )
551
528
" Eval an expression, in an environment like that outside the debugger.
552
529
The environment used is the one when entering the activation frame at point."
553
530
(interactive
554
531
(list (read--expression " Eval in stack frame: " )))
555
532
(let ((nframe (or nframe
556
- (condition-case nil (debugger-frame-number )
533
+ (condition-case nil (1+ ( debugger-frame-number 'skip-base ) )
557
534
(error 0 )))) ; ; If on first line.
558
535
(base (debugger--backtrace-base )))
559
536
(debugger-env-macro
@@ -668,7 +645,7 @@ Complete list of commands:
668
645
(princ (debugger-eval-expression exp))
669
646
(terpri ))
670
647
671
- (with-current-buffer debugger-record-buffer
648
+ (with-current-buffer ( get-buffer debugger-record-buffer)
672
649
(message " %s "
673
650
(buffer-substring (line-beginning-position 0 )
674
651
(line-end-position 0 )))))
@@ -686,10 +663,7 @@ functions to break on entry."
686
663
(if (or inhibit-debug-on-entry debugger-jumping-flag)
687
664
nil
688
665
(let ((inhibit-debug-on-entry t ))
689
- (funcall debugger 'debug :backtrace-base
690
- ; ; An offset of 1 because we need to skip the advice
691
- ; ; OClosure that called us.
692
- '(1 . debug--implement-debug-on-entry)))))
666
+ (funcall debugger 'debug ))))
693
667
694
668
;;;### autoload
695
669
(defun debug-on-entry (function )
0 commit comments