diff options
| author | Stefan Monnier | 2013-07-26 03:38:18 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2013-07-26 03:38:18 -0400 |
| commit | 56ea72917a7a700e29cf6c115fd1cd75ad782e9e (patch) | |
| tree | 1a9220717c6333b376d45ebc044ad8ed71cfda37 /lisp | |
| parent | f6b1502430653fac080f76a08edd2eb690f92146 (diff) | |
| download | emacs-56ea72917a7a700e29cf6c115fd1cd75ad782e9e.tar.gz emacs-56ea72917a7a700e29cf6c115fd1cd75ad782e9e.zip | |
Add support for lexical variables to the debugger's `e' command.
* lisp/emacs-lisp/debug.el (debug): Don't let-bind the debugger-outer-*
vars, except for debugger-outer-match-data.
(debugger-frame-number): Move check for "on a function call" from
callers into it. Add `skip-base' argument.
(debugger-frame, debugger-frame-clear): Simplify accordingly.
(debugger-env-macro): Only reset the state stored in non-variables,
i.e. current-buffer and match-data.
(debugger-eval-expression): Rewrite using backtrace-eval.
* lisp/subr.el (internal--called-interactively-p--get-frame): Remove.
(called-interactively-p):
* lisp/emacs-lisp/edebug.el (edebug--called-interactively-skip): Use the new
`base' arg of backtrace-frame instead.
* src/eval.c (set_specpdl_old_value): New function.
(unbind_to): Minor simplification.
(get_backtrace_frame): New function.
(Fbacktrace_frame): Use it. Add `base' argument.
(backtrace_eval_unrewind, Fbacktrace_eval): New functions.
(syms_of_eval): Export backtrace-eval.
* src/xterm.c (x_focus_changed): Simplify.
Diffstat (limited to 'lisp')
| -rw-r--r-- | lisp/ChangeLog | 16 | ||||
| -rw-r--r-- | lisp/emacs-lisp/debug.el | 145 | ||||
| -rw-r--r-- | lisp/emacs-lisp/edebug.el | 2 | ||||
| -rw-r--r-- | lisp/subr.el | 18 |
4 files changed, 48 insertions, 133 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 79582ea560a..84919e634be 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,19 @@ | |||
| 1 | 2013-07-26 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 2 | |||
| 3 | Add support for lexical variables to the debugger's `e' command. | ||
| 4 | * emacs-lisp/debug.el (debug): Don't let-bind the debugger-outer-* | ||
| 5 | vars, except for debugger-outer-match-data. | ||
| 6 | (debugger-frame-number): Move check for "on a function call" from | ||
| 7 | callers into it. Add `skip-base' argument. | ||
| 8 | (debugger-frame, debugger-frame-clear): Simplify accordingly. | ||
| 9 | (debugger-env-macro): Only reset the state stored in non-variables, | ||
| 10 | i.e. current-buffer and match-data. | ||
| 11 | (debugger-eval-expression): Rewrite using backtrace-eval. | ||
| 12 | * subr.el (internal--called-interactively-p--get-frame): Remove. | ||
| 13 | (called-interactively-p): | ||
| 14 | * emacs-lisp/edebug.el (edebug--called-interactively-skip): Use the new | ||
| 15 | `base' arg of backtrace-frame instead. | ||
| 16 | |||
| 1 | 2013-07-26 Glenn Morris <rgm@gnu.org> | 17 | 2013-07-26 Glenn Morris <rgm@gnu.org> |
| 2 | 18 | ||
| 3 | * align.el (align-regexp): Doc fix. (Bug#14857) | 19 | * align.el (align-regexp): Doc fix. (Bug#14857) |
diff --git a/lisp/emacs-lisp/debug.el b/lisp/emacs-lisp/debug.el index 0728e86d072..aee48eef668 100644 --- a/lisp/emacs-lisp/debug.el +++ b/lisp/emacs-lisp/debug.el | |||
| @@ -102,22 +102,6 @@ The value used here is passed to `quit-restore-window'." | |||
| 102 | This is to optimize `debugger-make-xrefs'.") | 102 | This is to optimize `debugger-make-xrefs'.") |
| 103 | 103 | ||
| 104 | (defvar debugger-outer-match-data) | 104 | (defvar debugger-outer-match-data) |
| 105 | (defvar debugger-outer-load-read-function) | ||
| 106 | (defvar debugger-outer-overriding-local-map) | ||
| 107 | (defvar debugger-outer-overriding-terminal-local-map) | ||
| 108 | (defvar debugger-outer-track-mouse) | ||
| 109 | (defvar debugger-outer-last-command) | ||
| 110 | (defvar debugger-outer-this-command) | ||
| 111 | (defvar debugger-outer-unread-command-events) | ||
| 112 | (defvar debugger-outer-unread-post-input-method-events) | ||
| 113 | (defvar debugger-outer-last-input-event) | ||
| 114 | (defvar debugger-outer-last-command-event) | ||
| 115 | (defvar debugger-outer-last-nonmenu-event) | ||
| 116 | (defvar debugger-outer-last-event-frame) | ||
| 117 | (defvar debugger-outer-standard-input) | ||
| 118 | (defvar debugger-outer-standard-output) | ||
| 119 | (defvar debugger-outer-inhibit-redisplay) | ||
| 120 | (defvar debugger-outer-cursor-in-echo-area) | ||
| 121 | (defvar debugger-will-be-back nil | 105 | (defvar debugger-will-be-back nil |
| 122 | "Non-nil if we expect to get back in the debugger soon.") | 106 | "Non-nil if we expect to get back in the debugger soon.") |
| 123 | 107 | ||
| @@ -174,24 +158,6 @@ first will be printed into the backtrace buffer." | |||
| 174 | ;; Save the outer values of these vars for the `e' command | 158 | ;; Save the outer values of these vars for the `e' command |
| 175 | ;; before we replace the values. | 159 | ;; before we replace the values. |
| 176 | (debugger-outer-match-data (match-data)) | 160 | (debugger-outer-match-data (match-data)) |
| 177 | (debugger-outer-load-read-function load-read-function) | ||
| 178 | (debugger-outer-overriding-local-map overriding-local-map) | ||
| 179 | (debugger-outer-overriding-terminal-local-map | ||
| 180 | overriding-terminal-local-map) | ||
| 181 | (debugger-outer-track-mouse track-mouse) | ||
| 182 | (debugger-outer-last-command last-command) | ||
| 183 | (debugger-outer-this-command this-command) | ||
| 184 | (debugger-outer-unread-command-events unread-command-events) | ||
| 185 | (debugger-outer-unread-post-input-method-events | ||
| 186 | unread-post-input-method-events) | ||
| 187 | (debugger-outer-last-input-event last-input-event) | ||
| 188 | (debugger-outer-last-command-event last-command-event) | ||
| 189 | (debugger-outer-last-nonmenu-event last-nonmenu-event) | ||
| 190 | (debugger-outer-last-event-frame last-event-frame) | ||
| 191 | (debugger-outer-standard-input standard-input) | ||
| 192 | (debugger-outer-standard-output standard-output) | ||
| 193 | (debugger-outer-inhibit-redisplay inhibit-redisplay) | ||
| 194 | (debugger-outer-cursor-in-echo-area cursor-in-echo-area) | ||
| 195 | (debugger-with-timeout-suspend (with-timeout-suspend))) | 161 | (debugger-with-timeout-suspend (with-timeout-suspend))) |
| 196 | ;; Set this instead of binding it, so that `q' | 162 | ;; Set this instead of binding it, so that `q' |
| 197 | ;; will not restore it. | 163 | ;; will not restore it. |
| @@ -294,26 +260,6 @@ first will be printed into the backtrace buffer." | |||
| 294 | (funcall (nth 0 debugger-previous-state)))))) | 260 | (funcall (nth 0 debugger-previous-state)))))) |
| 295 | (with-timeout-unsuspend debugger-with-timeout-suspend) | 261 | (with-timeout-unsuspend debugger-with-timeout-suspend) |
| 296 | (set-match-data debugger-outer-match-data))) | 262 | (set-match-data debugger-outer-match-data))) |
| 297 | ;; Put into effect the modified values of these variables | ||
| 298 | ;; in case the user set them with the `e' command. | ||
| 299 | (setq load-read-function debugger-outer-load-read-function) | ||
| 300 | (setq overriding-local-map debugger-outer-overriding-local-map) | ||
| 301 | (setq overriding-terminal-local-map | ||
| 302 | debugger-outer-overriding-terminal-local-map) | ||
| 303 | (setq track-mouse debugger-outer-track-mouse) | ||
| 304 | (setq last-command debugger-outer-last-command) | ||
| 305 | (setq this-command debugger-outer-this-command) | ||
| 306 | (setq unread-command-events debugger-outer-unread-command-events) | ||
| 307 | (setq unread-post-input-method-events | ||
| 308 | debugger-outer-unread-post-input-method-events) | ||
| 309 | (setq last-input-event debugger-outer-last-input-event) | ||
| 310 | (setq last-command-event debugger-outer-last-command-event) | ||
| 311 | (setq last-nonmenu-event debugger-outer-last-nonmenu-event) | ||
| 312 | (setq last-event-frame debugger-outer-last-event-frame) | ||
| 313 | (setq standard-input debugger-outer-standard-input) | ||
| 314 | (setq standard-output debugger-outer-standard-output) | ||
| 315 | (setq inhibit-redisplay debugger-outer-inhibit-redisplay) | ||
| 316 | (setq cursor-in-echo-area debugger-outer-cursor-in-echo-area) | ||
| 317 | (setq debug-on-next-call debugger-step-after-exit) | 263 | (setq debug-on-next-call debugger-step-after-exit) |
| 318 | debugger-value))) | 264 | debugger-value))) |
| 319 | 265 | ||
| @@ -518,18 +464,21 @@ removes itself from that hook." | |||
| 518 | (setq debugger-jumping-flag nil) | 464 | (setq debugger-jumping-flag nil) |
| 519 | (remove-hook 'post-command-hook 'debugger-reenable)) | 465 | (remove-hook 'post-command-hook 'debugger-reenable)) |
| 520 | 466 | ||
| 521 | (defun debugger-frame-number () | 467 | (defun debugger-frame-number (&optional skip-base) |
| 522 | "Return number of frames in backtrace before the one point points at." | 468 | "Return number of frames in backtrace before the one point points at." |
| 523 | (save-excursion | 469 | (save-excursion |
| 524 | (beginning-of-line) | 470 | (beginning-of-line) |
| 471 | (if (looking-at " *;;;\\|[a-z]") | ||
| 472 | (error "This line is not a function call")) | ||
| 525 | (let ((opoint (point)) | 473 | (let ((opoint (point)) |
| 526 | (count 0)) | 474 | (count 0)) |
| 527 | (while (not (eq (cadr (backtrace-frame count)) 'debug)) | 475 | (unless skip-base |
| 528 | (setq count (1+ count))) | 476 | (while (not (eq (cadr (backtrace-frame count)) 'debug)) |
| 529 | ;; Skip debug--implement-debug-on-entry frame. | 477 | (setq count (1+ count))) |
| 530 | (when (eq 'debug--implement-debug-on-entry | 478 | ;; Skip debug--implement-debug-on-entry frame. |
| 531 | (cadr (backtrace-frame (1+ count)))) | 479 | (when (eq 'debug--implement-debug-on-entry |
| 532 | (setq count (+ 2 count))) | 480 | (cadr (backtrace-frame (1+ count)))) |
| 481 | (setq count (+ 2 count)))) | ||
| 533 | (goto-char (point-min)) | 482 | (goto-char (point-min)) |
| 534 | (when (looking-at "Debugger entered--\\(Lisp error\\|returning value\\):") | 483 | (when (looking-at "Debugger entered--\\(Lisp error\\|returning value\\):") |
| 535 | (goto-char (match-end 0)) | 484 | (goto-char (match-end 0)) |
| @@ -551,12 +500,8 @@ removes itself from that hook." | |||
| 551 | "Request entry to debugger when this frame exits. | 500 | "Request entry to debugger when this frame exits. |
| 552 | Applies to the frame whose line point is on in the backtrace." | 501 | Applies to the frame whose line point is on in the backtrace." |
| 553 | (interactive) | 502 | (interactive) |
| 554 | (save-excursion | ||
| 555 | (beginning-of-line) | ||
| 556 | (if (looking-at " *;;;\\|[a-z]") | ||
| 557 | (error "This line is not a function call"))) | ||
| 558 | (beginning-of-line) | ||
| 559 | (backtrace-debug (debugger-frame-number) t) | 503 | (backtrace-debug (debugger-frame-number) t) |
| 504 | (beginning-of-line) | ||
| 560 | (if (= (following-char) ? ) | 505 | (if (= (following-char) ? ) |
| 561 | (let ((inhibit-read-only t)) | 506 | (let ((inhibit-read-only t)) |
| 562 | (delete-char 1) | 507 | (delete-char 1) |
| @@ -567,12 +512,8 @@ Applies to the frame whose line point is on in the backtrace." | |||
| 567 | "Do not enter debugger when this frame exits. | 512 | "Do not enter debugger when this frame exits. |
| 568 | Applies to the frame whose line point is on in the backtrace." | 513 | Applies to the frame whose line point is on in the backtrace." |
| 569 | (interactive) | 514 | (interactive) |
| 570 | (save-excursion | ||
| 571 | (beginning-of-line) | ||
| 572 | (if (looking-at " *;;;\\|[a-z]") | ||
| 573 | (error "This line is not a function call"))) | ||
| 574 | (beginning-of-line) | ||
| 575 | (backtrace-debug (debugger-frame-number) nil) | 515 | (backtrace-debug (debugger-frame-number) nil) |
| 516 | (beginning-of-line) | ||
| 576 | (if (= (following-char) ?*) | 517 | (if (= (following-char) ?*) |
| 577 | (let ((inhibit-read-only t)) | 518 | (let ((inhibit-read-only t)) |
| 578 | (delete-char 1) | 519 | (delete-char 1) |
| @@ -583,59 +524,33 @@ Applies to the frame whose line point is on in the backtrace." | |||
| 583 | "Run BODY in original environment." | 524 | "Run BODY in original environment." |
| 584 | (declare (indent 0)) | 525 | (declare (indent 0)) |
| 585 | `(save-excursion | 526 | `(save-excursion |
| 586 | (if (null (buffer-name debugger-old-buffer)) | 527 | (if (null (buffer-live-p debugger-old-buffer)) |
| 587 | ;; old buffer deleted | 528 | ;; old buffer deleted |
| 588 | (setq debugger-old-buffer (current-buffer))) | 529 | (setq debugger-old-buffer (current-buffer))) |
| 589 | (set-buffer debugger-old-buffer) | 530 | (set-buffer debugger-old-buffer) |
| 590 | (let ((load-read-function debugger-outer-load-read-function) | 531 | (set-match-data debugger-outer-match-data) |
| 591 | (overriding-terminal-local-map | 532 | (prog1 |
| 592 | debugger-outer-overriding-terminal-local-map) | 533 | (progn ,@body) |
| 593 | (overriding-local-map debugger-outer-overriding-local-map) | 534 | (setq debugger-outer-match-data (match-data))))) |
| 594 | (track-mouse debugger-outer-track-mouse) | ||
| 595 | (last-command debugger-outer-last-command) | ||
| 596 | (this-command debugger-outer-this-command) | ||
| 597 | (unread-command-events debugger-outer-unread-command-events) | ||
| 598 | (unread-post-input-method-events | ||
| 599 | debugger-outer-unread-post-input-method-events) | ||
| 600 | (last-input-event debugger-outer-last-input-event) | ||
| 601 | (last-command-event debugger-outer-last-command-event) | ||
| 602 | (last-nonmenu-event debugger-outer-last-nonmenu-event) | ||
| 603 | (last-event-frame debugger-outer-last-event-frame) | ||
| 604 | (standard-input debugger-outer-standard-input) | ||
| 605 | (standard-output debugger-outer-standard-output) | ||
| 606 | (inhibit-redisplay debugger-outer-inhibit-redisplay) | ||
| 607 | (cursor-in-echo-area debugger-outer-cursor-in-echo-area)) | ||
| 608 | (set-match-data debugger-outer-match-data) | ||
| 609 | (prog1 | ||
| 610 | (progn ,@body) | ||
| 611 | (setq debugger-outer-match-data (match-data)) | ||
| 612 | (setq debugger-outer-load-read-function load-read-function) | ||
| 613 | (setq debugger-outer-overriding-terminal-local-map | ||
| 614 | overriding-terminal-local-map) | ||
| 615 | (setq debugger-outer-overriding-local-map overriding-local-map) | ||
| 616 | (setq debugger-outer-track-mouse track-mouse) | ||
| 617 | (setq debugger-outer-last-command last-command) | ||
| 618 | (setq debugger-outer-this-command this-command) | ||
| 619 | (setq debugger-outer-unread-command-events unread-command-events) | ||
| 620 | (setq debugger-outer-unread-post-input-method-events | ||
| 621 | unread-post-input-method-events) | ||
| 622 | (setq debugger-outer-last-input-event last-input-event) | ||
| 623 | (setq debugger-outer-last-command-event last-command-event) | ||
| 624 | (setq debugger-outer-last-nonmenu-event last-nonmenu-event) | ||
| 625 | (setq debugger-outer-last-event-frame last-event-frame) | ||
| 626 | (setq debugger-outer-standard-input standard-input) | ||
| 627 | (setq debugger-outer-standard-output standard-output) | ||
| 628 | (setq debugger-outer-inhibit-redisplay inhibit-redisplay) | ||
| 629 | (setq debugger-outer-cursor-in-echo-area cursor-in-echo-area) | ||
| 630 | )))) | ||
| 631 | 535 | ||
| 632 | (defun debugger-eval-expression (exp) | 536 | (defun debugger-eval-expression (exp) |
| 633 | "Eval an expression, in an environment like that outside the debugger." | 537 | "Eval an expression, in an environment like that outside the debugger. |
| 538 | The environment used is the one when entering the activation frame at point." | ||
| 634 | (interactive | 539 | (interactive |
| 635 | (list (read-from-minibuffer "Eval: " | 540 | (list (read-from-minibuffer "Eval: " |
| 636 | nil read-expression-map t | 541 | nil read-expression-map t |
| 637 | 'read-expression-history))) | 542 | 'read-expression-history))) |
| 638 | (debugger-env-macro (eval-expression exp))) | 543 | (let ((nframe (condition-case nil (1+ (debugger-frame-number 'skip-base)) |
| 544 | (error 0))) ;; If on first line. | ||
| 545 | (base (if (eq 'debug--implement-debug-on-entry | ||
| 546 | (cadr (backtrace-frame 1 'debug))) | ||
| 547 | 'debug--implement-debug-on-entry 'debug))) | ||
| 548 | (debugger-env-macro | ||
| 549 | (let ((val (backtrace-eval exp nframe base))) | ||
| 550 | (prog1 | ||
| 551 | (prin1 val t) | ||
| 552 | (let ((str (eval-expression-print-format val))) | ||
| 553 | (if str (princ str t)))))))) | ||
| 639 | 554 | ||
| 640 | (defvar debugger-mode-map | 555 | (defvar debugger-mode-map |
| 641 | (let ((map (make-keymap)) | 556 | (let ((map (make-keymap)) |
diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el index 36c72f3a3bd..7771c3adaa4 100644 --- a/lisp/emacs-lisp/edebug.el +++ b/lisp/emacs-lisp/edebug.el | |||
| @@ -4268,7 +4268,7 @@ With prefix argument, make it a temporary breakpoint." | |||
| 4268 | (eq (nth 1 (nth 1 frame1)) '()) | 4268 | (eq (nth 1 (nth 1 frame1)) '()) |
| 4269 | (eq (nth 1 frame2) 'edebug-enter)) | 4269 | (eq (nth 1 frame2) 'edebug-enter)) |
| 4270 | ;; `edebug-enter' calls itself on its first invocation. | 4270 | ;; `edebug-enter' calls itself on its first invocation. |
| 4271 | (if (eq (nth 1 (internal--called-interactively-p--get-frame i)) | 4271 | (if (eq (nth 1 (backtrace-frame i 'called-interactively-p)) |
| 4272 | 'edebug-enter) | 4272 | 'edebug-enter) |
| 4273 | 2 1))) | 4273 | 2 1))) |
| 4274 | 4274 | ||
diff --git a/lisp/subr.el b/lisp/subr.el index 7130639dbe5..3b85a9bedb0 100644 --- a/lisp/subr.el +++ b/lisp/subr.el | |||
| @@ -4191,22 +4191,6 @@ I is the index of the frame after FRAME2. It should return nil | |||
| 4191 | if those frames don't seem special and otherwise, it should return | 4191 | if those frames don't seem special and otherwise, it should return |
| 4192 | the number of frames to skip (minus 1).") | 4192 | the number of frames to skip (minus 1).") |
| 4193 | 4193 | ||
| 4194 | (defmacro internal--called-interactively-p--get-frame (n) | ||
| 4195 | ;; `sym' will hold a global variable, which will be used kind of like C's | ||
| 4196 | ;; "static" variables. | ||
| 4197 | (let ((sym (make-symbol "base-index"))) | ||
| 4198 | `(progn | ||
| 4199 | (defvar ,sym) | ||
| 4200 | (unless (boundp ',sym) | ||
| 4201 | (let ((i 1)) | ||
| 4202 | (while (not (eq (indirect-function (nth 1 (backtrace-frame i)) t) | ||
| 4203 | (indirect-function 'called-interactively-p))) | ||
| 4204 | (setq i (1+ i))) | ||
| 4205 | (setq ,sym i))) | ||
| 4206 | ;; (unless (eq (nth 1 (backtrace-frame ,sym)) 'called-interactively-p) | ||
| 4207 | ;; (error "called-interactively-p: %s is out-of-sync!" ,sym)) | ||
| 4208 | (backtrace-frame (+ ,sym ,n))))) | ||
| 4209 | |||
| 4210 | (defun called-interactively-p (&optional kind) | 4194 | (defun called-interactively-p (&optional kind) |
| 4211 | "Return t if the containing function was called by `call-interactively'. | 4195 | "Return t if the containing function was called by `call-interactively'. |
| 4212 | If KIND is `interactive', then only return t if the call was made | 4196 | If KIND is `interactive', then only return t if the call was made |
| @@ -4241,7 +4225,7 @@ command is called from a keyboard macro?" | |||
| 4241 | (get-next-frame | 4225 | (get-next-frame |
| 4242 | (lambda () | 4226 | (lambda () |
| 4243 | (setq frame nextframe) | 4227 | (setq frame nextframe) |
| 4244 | (setq nextframe (internal--called-interactively-p--get-frame i)) | 4228 | (setq nextframe (backtrace-frame i 'called-interactively-p)) |
| 4245 | ;; (message "Frame %d = %S" i nextframe) | 4229 | ;; (message "Frame %d = %S" i nextframe) |
| 4246 | (setq i (1+ i))))) | 4230 | (setq i (1+ i))))) |
| 4247 | (funcall get-next-frame) ;; Get the first frame. | 4231 | (funcall get-next-frame) ;; Get the first frame. |