diff options
| author | Noam Postavsky | 2017-06-29 19:42:32 -0400 |
|---|---|---|
| committer | Noam Postavsky | 2017-06-29 19:42:32 -0400 |
| commit | 169532b0ebc3acb0b1c943d0b3d8b569cd57ca4b (patch) | |
| tree | 60d7ae515b92944d1e90772df3ae5dac05b5c715 /lisp | |
| parent | 138447c3abd749d1c27d99d7089b1b0903352ade (diff) | |
| parent | c87c87fcc361494815bbd1d92f450b0b80a3ecbb (diff) | |
| download | emacs-169532b0ebc3acb0b1c943d0b3d8b569cd57ca4b.tar.gz emacs-169532b0ebc3acb0b1c943d0b3d8b569cd57ca4b.zip | |
; Merge: Backtrace printing improvements (Bug#6991)
Diffstat (limited to 'lisp')
| -rw-r--r-- | lisp/emacs-lisp/cl-print.el | 9 | ||||
| -rw-r--r-- | lisp/emacs-lisp/debug.el | 181 | ||||
| -rw-r--r-- | lisp/emacs-lisp/ert.el | 85 | ||||
| -rw-r--r-- | lisp/select.el | 3 | ||||
| -rw-r--r-- | lisp/subr.el | 3 | ||||
| -rw-r--r-- | lisp/term/w32-win.el | 2 |
6 files changed, 113 insertions, 170 deletions
diff --git a/lisp/emacs-lisp/cl-print.el b/lisp/emacs-lisp/cl-print.el index 89a71d1b6c5..824d0b7b4f5 100644 --- a/lisp/emacs-lisp/cl-print.el +++ b/lisp/emacs-lisp/cl-print.el | |||
| @@ -105,10 +105,11 @@ into a button whose action shows the function's disassembly.") | |||
| 105 | (if args | 105 | (if args |
| 106 | (prin1 args stream) | 106 | (prin1 args stream) |
| 107 | (princ "()" stream))) | 107 | (princ "()" stream))) |
| 108 | (let ((doc (documentation object 'raw))) | 108 | (pcase (help-split-fundoc (documentation object 'raw) object) |
| 109 | (when doc | 109 | ;; Drop args which `help-function-arglist' already printed. |
| 110 | (princ " " stream) | 110 | (`(,_usage . ,(and doc (guard (stringp doc)))) |
| 111 | (prin1 doc stream))) | 111 | (princ " " stream) |
| 112 | (prin1 doc stream))) | ||
| 112 | (let ((inter (interactive-form object))) | 113 | (let ((inter (interactive-form object))) |
| 113 | (when inter | 114 | (when inter |
| 114 | (princ " " stream) | 115 | (princ " " stream) |
diff --git a/lisp/emacs-lisp/debug.el b/lisp/emacs-lisp/debug.el index 83456fc31a2..726005af9b1 100644 --- a/lisp/emacs-lisp/debug.el +++ b/lisp/emacs-lisp/debug.el | |||
| @@ -49,6 +49,12 @@ the middle is discarded, and just the beginning and end are displayed." | |||
| 49 | :group 'debugger | 49 | :group 'debugger |
| 50 | :version "21.1") | 50 | :version "21.1") |
| 51 | 51 | ||
| 52 | (defcustom debugger-print-function #'cl-prin1 | ||
| 53 | "Function used to print values in the debugger backtraces." | ||
| 54 | :type 'function | ||
| 55 | :options '(cl-prin1 prin1) | ||
| 56 | :version "26.1") | ||
| 57 | |||
| 52 | (defcustom debugger-bury-or-kill 'bury | 58 | (defcustom debugger-bury-or-kill 'bury |
| 53 | "What to do with the debugger buffer when exiting `debug'. | 59 | "What to do with the debugger buffer when exiting `debug'. |
| 54 | The value affects the behavior of operations on any window | 60 | The value affects the behavior of operations on any window |
| @@ -264,6 +270,43 @@ first will be printed into the backtrace buffer." | |||
| 264 | (setq debug-on-next-call debugger-step-after-exit) | 270 | (setq debug-on-next-call debugger-step-after-exit) |
| 265 | debugger-value))) | 271 | debugger-value))) |
| 266 | 272 | ||
| 273 | |||
| 274 | (defvar cl-print-compiled-button) | ||
| 275 | |||
| 276 | (defun debugger-insert-backtrace (frames do-xrefs) | ||
| 277 | "Format and insert the backtrace FRAMES at point. | ||
| 278 | Make functions into cross-reference buttons if DO-XREFS is non-nil." | ||
| 279 | (let ((standard-output (current-buffer)) | ||
| 280 | (cl-print-compiled-button t) | ||
| 281 | (eval-buffers eval-buffer-list)) | ||
| 282 | (require 'help-mode) ; Define `help-function-def' button type. | ||
| 283 | (pcase-dolist (`(,evald ,fun ,args ,flags) frames) | ||
| 284 | (insert (if (plist-get flags :debug-on-exit) | ||
| 285 | "* " " ")) | ||
| 286 | (let ((fun-file (and do-xrefs (symbol-file fun 'defun))) | ||
| 287 | (fun-pt (point))) | ||
| 288 | (cond | ||
| 289 | ((and evald (not debugger-stack-frame-as-list)) | ||
| 290 | (funcall debugger-print-function fun) | ||
| 291 | (if args (funcall debugger-print-function args) (princ "()"))) | ||
| 292 | (t | ||
| 293 | (funcall debugger-print-function (cons fun args)) | ||
| 294 | (cl-incf fun-pt))) | ||
| 295 | (when fun-file | ||
| 296 | (make-text-button fun-pt (+ fun-pt (length (symbol-name fun))) | ||
| 297 | :type 'help-function-def | ||
| 298 | 'help-args (list fun fun-file)))) | ||
| 299 | ;; After any frame that uses eval-buffer, insert a line that | ||
| 300 | ;; states the buffer position it's reading at. | ||
| 301 | (when (and eval-buffers (memq fun '(eval-buffer eval-region))) | ||
| 302 | (insert (format " ; Reading at buffer position %d" | ||
| 303 | ;; This will get the wrong result if there are | ||
| 304 | ;; two nested eval-region calls for the same | ||
| 305 | ;; buffer. That's not a very useful case. | ||
| 306 | (with-current-buffer (pop eval-buffers) | ||
| 307 | (point))))) | ||
| 308 | (insert "\n")))) | ||
| 309 | |||
| 267 | (defun debugger-setup-buffer (args) | 310 | (defun debugger-setup-buffer (args) |
| 268 | "Initialize the `*Backtrace*' buffer for entry to the debugger. | 311 | "Initialize the `*Backtrace*' buffer for entry to the debugger. |
| 269 | That buffer should be current already." | 312 | That buffer should be current already." |
| @@ -271,27 +314,20 @@ That buffer should be current already." | |||
| 271 | (erase-buffer) | 314 | (erase-buffer) |
| 272 | (set-buffer-multibyte t) ;Why was it nil ? -stef | 315 | (set-buffer-multibyte t) ;Why was it nil ? -stef |
| 273 | (setq buffer-undo-list t) | 316 | (setq buffer-undo-list t) |
| 274 | (let ((standard-output (current-buffer)) | ||
| 275 | (print-escape-newlines t) | ||
| 276 | (print-level 8) | ||
| 277 | (print-length 50)) | ||
| 278 | ;; FIXME the debugger could pass a custom callback to mapbacktrace | ||
| 279 | ;; instead of manipulating printed results. | ||
| 280 | (mapbacktrace #'backtrace--print-frame 'debug)) | ||
| 281 | (goto-char (point-min)) | ||
| 282 | (delete-region (point) | ||
| 283 | (progn | ||
| 284 | (forward-line (if (eq (car args) 'debug) | ||
| 285 | ;; Remove debug--implement-debug-on-entry | ||
| 286 | ;; and the advice's `apply' frame. | ||
| 287 | 3 | ||
| 288 | 1)) | ||
| 289 | (point))) | ||
| 290 | (insert "Debugger entered") | 317 | (insert "Debugger entered") |
| 291 | ;; lambda is for debug-on-call when a function call is next. | 318 | (let ((frames (nthcdr |
| 292 | ;; debug is for debug-on-entry function called. | 319 | ;; Remove debug--implement-debug-on-entry and the |
| 293 | (let ((pos (point))) | 320 | ;; advice's `apply' frame. |
| 321 | (if (eq (car args) 'debug) 3 1) | ||
| 322 | (backtrace-frames 'debug))) | ||
| 323 | (print-escape-newlines t) | ||
| 324 | (print-escape-control-characters t) | ||
| 325 | (print-level 8) | ||
| 326 | (print-length 50) | ||
| 327 | (pos (point))) | ||
| 294 | (pcase (car args) | 328 | (pcase (car args) |
| 329 | ;; lambda is for debug-on-call when a function call is next. | ||
| 330 | ;; debug is for debug-on-entry function called. | ||
| 295 | ((or `lambda `debug) | 331 | ((or `lambda `debug) |
| 296 | (insert "--entering a function:\n") | 332 | (insert "--entering a function:\n") |
| 297 | (setq pos (1- (point)))) | 333 | (setq pos (1- (point)))) |
| @@ -300,11 +336,9 @@ That buffer should be current already." | |||
| 300 | (insert "--returning value: ") | 336 | (insert "--returning value: ") |
| 301 | (setq pos (point)) | 337 | (setq pos (point)) |
| 302 | (setq debugger-value (nth 1 args)) | 338 | (setq debugger-value (nth 1 args)) |
| 303 | (prin1 debugger-value (current-buffer)) | 339 | (funcall debugger-print-function debugger-value (current-buffer)) |
| 304 | (insert ?\n) | 340 | (setf (cl-getf (nth 3 (car frames)) :debug-on-exit) nil) |
| 305 | (delete-char 1) | 341 | (insert ?\n)) |
| 306 | (insert ? ) | ||
| 307 | (beginning-of-line)) | ||
| 308 | ;; Watchpoint triggered. | 342 | ;; Watchpoint triggered. |
| 309 | ((and `watchpoint (let `(,symbol ,newval . ,details) (cdr args))) | 343 | ((and `watchpoint (let `(,symbol ,newval . ,details) (cdr args))) |
| 310 | (insert | 344 | (insert |
| @@ -327,7 +361,7 @@ That buffer should be current already." | |||
| 327 | (`error | 361 | (`error |
| 328 | (insert "--Lisp error: ") | 362 | (insert "--Lisp error: ") |
| 329 | (setq pos (point)) | 363 | (setq pos (point)) |
| 330 | (prin1 (nth 1 args) (current-buffer)) | 364 | (funcall debugger-print-function (nth 1 args) (current-buffer)) |
| 331 | (insert ?\n)) | 365 | (insert ?\n)) |
| 332 | ;; debug-on-call, when the next thing is an eval. | 366 | ;; debug-on-call, when the next thing is an eval. |
| 333 | (`t | 367 | (`t |
| @@ -337,98 +371,15 @@ That buffer should be current already." | |||
| 337 | (_ | 371 | (_ |
| 338 | (insert ": ") | 372 | (insert ": ") |
| 339 | (setq pos (point)) | 373 | (setq pos (point)) |
| 340 | (prin1 (if (eq (car args) 'nil) | 374 | (funcall debugger-print-function |
| 341 | (cdr args) args) | 375 | (if (eq (car args) 'nil) |
| 342 | (current-buffer)) | 376 | (cdr args) args) |
| 377 | (current-buffer)) | ||
| 343 | (insert ?\n))) | 378 | (insert ?\n))) |
| 379 | (debugger-insert-backtrace frames t) | ||
| 344 | ;; Place point on "stack frame 0" (bug#15101). | 380 | ;; Place point on "stack frame 0" (bug#15101). |
| 345 | (goto-char pos)) | 381 | (goto-char pos))) |
| 346 | ;; After any frame that uses eval-buffer, | 382 | |
| 347 | ;; insert a line that states the buffer position it's reading at. | ||
| 348 | (save-excursion | ||
| 349 | (let ((tem eval-buffer-list)) | ||
| 350 | (while (and tem | ||
| 351 | (re-search-forward "^ eval-\\(buffer\\|region\\)(" nil t)) | ||
| 352 | (end-of-line) | ||
| 353 | (insert (format " ; Reading at buffer position %d" | ||
| 354 | ;; This will get the wrong result | ||
| 355 | ;; if there are two nested eval-region calls | ||
| 356 | ;; for the same buffer. That's not a very useful case. | ||
| 357 | (with-current-buffer (car tem) | ||
| 358 | (point)))) | ||
| 359 | (pop tem)))) | ||
| 360 | (debugger-make-xrefs)) | ||
| 361 | |||
| 362 | (defun debugger-make-xrefs (&optional buffer) | ||
| 363 | "Attach cross-references to function names in the `*Backtrace*' buffer." | ||
| 364 | (interactive "b") | ||
| 365 | (with-current-buffer (or buffer (current-buffer)) | ||
| 366 | (save-excursion | ||
| 367 | (setq buffer (current-buffer)) | ||
| 368 | (let ((inhibit-read-only t) | ||
| 369 | (old-end (point-min)) (new-end (point-min))) | ||
| 370 | ;; If we saved an old backtrace, find the common part | ||
| 371 | ;; between the new and the old. | ||
| 372 | ;; Compare line by line, starting from the end, | ||
| 373 | ;; because that's the part that is likely to be unchanged. | ||
| 374 | (if debugger-previous-backtrace | ||
| 375 | (let (old-start new-start (all-match t)) | ||
| 376 | (goto-char (point-max)) | ||
| 377 | (with-temp-buffer | ||
| 378 | (insert debugger-previous-backtrace) | ||
| 379 | (while (and all-match (not (bobp))) | ||
| 380 | (setq old-end (point)) | ||
| 381 | (forward-line -1) | ||
| 382 | (setq old-start (point)) | ||
| 383 | (with-current-buffer buffer | ||
| 384 | (setq new-end (point)) | ||
| 385 | (forward-line -1) | ||
| 386 | (setq new-start (point))) | ||
| 387 | (if (not (zerop | ||
| 388 | (let ((case-fold-search nil)) | ||
| 389 | (compare-buffer-substrings | ||
| 390 | (current-buffer) old-start old-end | ||
| 391 | buffer new-start new-end)))) | ||
| 392 | (setq all-match nil)))) | ||
| 393 | ;; Now new-end is the position of the start of the | ||
| 394 | ;; unchanged part in the current buffer, and old-end is | ||
| 395 | ;; the position of that same text in the saved old | ||
| 396 | ;; backtrace. But we must subtract (point-min) since strings are | ||
| 397 | ;; indexed in origin 0. | ||
| 398 | |||
| 399 | ;; Replace the unchanged part of the backtrace | ||
| 400 | ;; with the text from debugger-previous-backtrace, | ||
| 401 | ;; since that already has the proper xrefs. | ||
| 402 | ;; With this optimization, we only need to scan | ||
| 403 | ;; the changed part of the backtrace. | ||
| 404 | (delete-region new-end (point-max)) | ||
| 405 | (goto-char (point-max)) | ||
| 406 | (insert (substring debugger-previous-backtrace | ||
| 407 | (- old-end (point-min)))) | ||
| 408 | ;; Make the unchanged part of the backtrace inaccessible | ||
| 409 | ;; so it won't be scanned. | ||
| 410 | (narrow-to-region (point-min) new-end))) | ||
| 411 | |||
| 412 | ;; Scan the new part of the backtrace, inserting xrefs. | ||
| 413 | (goto-char (point-min)) | ||
| 414 | (while (progn | ||
| 415 | (goto-char (+ (point) 2)) | ||
| 416 | (skip-syntax-forward "^w_") | ||
| 417 | (not (eobp))) | ||
| 418 | (let* ((beg (point)) | ||
| 419 | (end (progn (skip-syntax-forward "w_") (point))) | ||
| 420 | (sym (intern-soft (buffer-substring-no-properties | ||
| 421 | beg end))) | ||
| 422 | (file (and sym (symbol-file sym 'defun)))) | ||
| 423 | (when file | ||
| 424 | (goto-char beg) | ||
| 425 | ;; help-xref-button needs to operate on something matched | ||
| 426 | ;; by a regexp, so set that up for it. | ||
| 427 | (re-search-forward "\\(\\sw\\|\\s_\\)+") | ||
| 428 | (help-xref-button 0 'help-function-def sym file))) | ||
| 429 | (forward-line 1)) | ||
| 430 | (widen)) | ||
| 431 | (setq debugger-previous-backtrace (buffer-string))))) | ||
| 432 | 383 | ||
| 433 | (defun debugger-step-through () | 384 | (defun debugger-step-through () |
| 434 | "Proceed, stepping through subexpressions of this expression. | 385 | "Proceed, stepping through subexpressions of this expression. |
diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el index 2c49a634e35..7edc40188e1 100644 --- a/lisp/emacs-lisp/ert.el +++ b/lisp/emacs-lisp/ert.el | |||
| @@ -670,48 +670,12 @@ and is displayed in front of the value of MESSAGE-FORM." | |||
| 670 | (cl-defstruct (ert-test-aborted-with-non-local-exit | 670 | (cl-defstruct (ert-test-aborted-with-non-local-exit |
| 671 | (:include ert-test-result))) | 671 | (:include ert-test-result))) |
| 672 | 672 | ||
| 673 | 673 | (defun ert--print-backtrace (backtrace do-xrefs) | |
| 674 | (defun ert--record-backtrace () | ||
| 675 | "Record the current backtrace (as a list) and return it." | ||
| 676 | ;; Since the backtrace is stored in the result object, result | ||
| 677 | ;; objects must only be printed with appropriate limits | ||
| 678 | ;; (`print-level' and `print-length') in place. For interactive | ||
| 679 | ;; use, the cost of ensuring this possibly outweighs the advantage | ||
| 680 | ;; of storing the backtrace for | ||
| 681 | ;; `ert-results-pop-to-backtrace-for-test-at-point' given that we | ||
| 682 | ;; already have `ert-results-rerun-test-debugging-errors-at-point'. | ||
| 683 | ;; For batch use, however, printing the backtrace may be useful. | ||
| 684 | (cl-loop | ||
| 685 | ;; 6 is the number of frames our own debugger adds (when | ||
| 686 | ;; compiled; more when interpreted). FIXME: Need to describe a | ||
| 687 | ;; procedure for determining this constant. | ||
| 688 | for i from 6 | ||
| 689 | for frame = (backtrace-frame i) | ||
| 690 | while frame | ||
| 691 | collect frame)) | ||
| 692 | |||
| 693 | (defun ert--print-backtrace (backtrace) | ||
| 694 | "Format the backtrace BACKTRACE to the current buffer." | 674 | "Format the backtrace BACKTRACE to the current buffer." |
| 695 | ;; This is essentially a reimplementation of Fbacktrace | ||
| 696 | ;; (src/eval.c), but for a saved backtrace, not the current one. | ||
| 697 | (let ((print-escape-newlines t) | 675 | (let ((print-escape-newlines t) |
| 698 | (print-level 8) | 676 | (print-level 8) |
| 699 | (print-length 50)) | 677 | (print-length 50)) |
| 700 | (dolist (frame backtrace) | 678 | (debugger-insert-backtrace backtrace do-xrefs))) |
| 701 | (pcase-exhaustive frame | ||
| 702 | (`(nil ,special-operator . ,arg-forms) | ||
| 703 | ;; Special operator. | ||
| 704 | (insert | ||
| 705 | (format " %S\n" (cons special-operator arg-forms)))) | ||
| 706 | (`(t ,fn . ,args) | ||
| 707 | ;; Function call. | ||
| 708 | (insert (format " %S(" fn)) | ||
| 709 | (cl-loop for firstp = t then nil | ||
| 710 | for arg in args do | ||
| 711 | (unless firstp | ||
| 712 | (insert " ")) | ||
| 713 | (insert (format "%S" arg))) | ||
| 714 | (insert ")\n")))))) | ||
| 715 | 679 | ||
| 716 | ;; A container for the state of the execution of a single test and | 680 | ;; A container for the state of the execution of a single test and |
| 717 | ;; environment data needed during its execution. | 681 | ;; environment data needed during its execution. |
| @@ -750,7 +714,19 @@ run. ARGS are the arguments to `debugger'." | |||
| 750 | ((quit) 'quit) | 714 | ((quit) 'quit) |
| 751 | ((ert-test-skipped) 'skipped) | 715 | ((ert-test-skipped) 'skipped) |
| 752 | (otherwise 'failed))) | 716 | (otherwise 'failed))) |
| 753 | (backtrace (ert--record-backtrace)) | 717 | ;; We store the backtrace in the result object for |
| 718 | ;; `ert-results-pop-to-backtrace-for-test-at-point'. | ||
| 719 | ;; This means we have to limit `print-level' and | ||
| 720 | ;; `print-length' when printing result objects. That | ||
| 721 | ;; might not be worth while when we can also use | ||
| 722 | ;; `ert-results-rerun-test-debugging-errors-at-point', | ||
| 723 | ;; (i.e., when running interactively) but having the | ||
| 724 | ;; backtrace ready for printing is important for batch | ||
| 725 | ;; use. | ||
| 726 | ;; | ||
| 727 | ;; Grab the frames starting from `signal', frames below | ||
| 728 | ;; that are all from the debugger. | ||
| 729 | (backtrace (backtrace-frames 'signal)) | ||
| 754 | (infos (reverse ert--infos))) | 730 | (infos (reverse ert--infos))) |
| 755 | (setf (ert--test-execution-info-result info) | 731 | (setf (ert--test-execution-info-result info) |
| 756 | (cl-ecase type | 732 | (cl-ecase type |
| @@ -1409,8 +1385,9 @@ Returns the stats object." | |||
| 1409 | (ert-test-result-with-condition | 1385 | (ert-test-result-with-condition |
| 1410 | (message "Test %S backtrace:" (ert-test-name test)) | 1386 | (message "Test %S backtrace:" (ert-test-name test)) |
| 1411 | (with-temp-buffer | 1387 | (with-temp-buffer |
| 1412 | (ert--print-backtrace (ert-test-result-with-condition-backtrace | 1388 | (ert--print-backtrace |
| 1413 | result)) | 1389 | (ert-test-result-with-condition-backtrace result) |
| 1390 | nil) | ||
| 1414 | (goto-char (point-min)) | 1391 | (goto-char (point-min)) |
| 1415 | (while (not (eobp)) | 1392 | (while (not (eobp)) |
| 1416 | (let ((start (point)) | 1393 | (let ((start (point)) |
| @@ -1828,12 +1805,23 @@ EWOC and STATS are arguments for `ert--results-update-stats-display'." | |||
| 1828 | 1805 | ||
| 1829 | BEGIN and END specify a region in the current buffer." | 1806 | BEGIN and END specify a region in the current buffer." |
| 1830 | (save-excursion | 1807 | (save-excursion |
| 1831 | (save-restriction | 1808 | (goto-char begin) |
| 1832 | (narrow-to-region begin end) | 1809 | (while (progn |
| 1833 | ;; Inhibit optimization in `debugger-make-xrefs' that would | 1810 | (goto-char (+ (point) 2)) |
| 1834 | ;; sometimes insert unrelated backtrace info into our buffer. | 1811 | (skip-syntax-forward "^w_") |
| 1835 | (let ((debugger-previous-backtrace nil)) | 1812 | (< (point) end)) |
| 1836 | (debugger-make-xrefs))))) | 1813 | (let* ((beg (point)) |
| 1814 | (end (progn (skip-syntax-forward "w_") (point))) | ||
| 1815 | (sym (intern-soft (buffer-substring-no-properties | ||
| 1816 | beg end))) | ||
| 1817 | (file (and sym (symbol-file sym 'defun)))) | ||
| 1818 | (when file | ||
| 1819 | (goto-char beg) | ||
| 1820 | ;; help-xref-button needs to operate on something matched | ||
| 1821 | ;; by a regexp, so set that up for it. | ||
| 1822 | (re-search-forward "\\(\\sw\\|\\s_\\)+") | ||
| 1823 | (help-xref-button 0 'help-function-def sym file))) | ||
| 1824 | (forward-line 1)))) | ||
| 1837 | 1825 | ||
| 1838 | (defun ert--string-first-line (s) | 1826 | (defun ert--string-first-line (s) |
| 1839 | "Return the first line of S, or S if it contains no newlines. | 1827 | "Return the first line of S, or S if it contains no newlines. |
| @@ -2420,8 +2408,7 @@ To be used in the ERT results buffer." | |||
| 2420 | ;; Use unibyte because `debugger-setup-buffer' also does so. | 2408 | ;; Use unibyte because `debugger-setup-buffer' also does so. |
| 2421 | (set-buffer-multibyte nil) | 2409 | (set-buffer-multibyte nil) |
| 2422 | (setq truncate-lines t) | 2410 | (setq truncate-lines t) |
| 2423 | (ert--print-backtrace backtrace) | 2411 | (ert--print-backtrace backtrace t) |
| 2424 | (debugger-make-xrefs) | ||
| 2425 | (goto-char (point-min)) | 2412 | (goto-char (point-min)) |
| 2426 | (insert (substitute-command-keys "Backtrace for test `")) | 2413 | (insert (substitute-command-keys "Backtrace for test `")) |
| 2427 | (ert-insert-test-name-button (ert-test-name test)) | 2414 | (ert-insert-test-name-button (ert-test-name test)) |
diff --git a/lisp/select.el b/lisp/select.el index 4849d7d515e..579c5c7e2ee 100644 --- a/lisp/select.el +++ b/lisp/select.el | |||
| @@ -475,6 +475,9 @@ two markers or an overlay. Otherwise, it is nil." | |||
| 475 | (t | 475 | (t |
| 476 | (error "Unknown selection type: %S" type))))) | 476 | (error "Unknown selection type: %S" type))))) |
| 477 | 477 | ||
| 478 | ;; Most programs are unable to handle NUL bytes in strings. | ||
| 479 | (setq str (replace-regexp-in-string "\0" "\\0" str t t)) | ||
| 480 | |||
| 478 | (setq next-selection-coding-system nil) | 481 | (setq next-selection-coding-system nil) |
| 479 | (cons type str)))) | 482 | (cons type str)))) |
| 480 | 483 | ||
diff --git a/lisp/subr.el b/lisp/subr.el index d0c8517c543..a9edff6166f 100644 --- a/lisp/subr.el +++ b/lisp/subr.el | |||
| @@ -4514,7 +4514,8 @@ EVALD, FUNC, ARGS, FLAGS are as in `mapbacktrace'." | |||
| 4514 | (defun backtrace () | 4514 | (defun backtrace () |
| 4515 | "Print a trace of Lisp function calls currently active. | 4515 | "Print a trace of Lisp function calls currently active. |
| 4516 | Output stream used is value of `standard-output'." | 4516 | Output stream used is value of `standard-output'." |
| 4517 | (let ((print-level (or print-level 8))) | 4517 | (let ((print-level (or print-level 8)) |
| 4518 | (print-escape-control-characters t)) | ||
| 4518 | (mapbacktrace #'backtrace--print-frame 'backtrace))) | 4519 | (mapbacktrace #'backtrace--print-frame 'backtrace))) |
| 4519 | 4520 | ||
| 4520 | (defun backtrace-frames (&optional base) | 4521 | (defun backtrace-frames (&optional base) |
diff --git a/lisp/term/w32-win.el b/lisp/term/w32-win.el index fda93884c40..be895a040da 100644 --- a/lisp/term/w32-win.el +++ b/lisp/term/w32-win.el | |||
| @@ -396,7 +396,7 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.") | |||
| 396 | ;;; Fix interface to (X-specific) mouse.el | 396 | ;;; Fix interface to (X-specific) mouse.el |
| 397 | (defun w32--set-selection (type value) | 397 | (defun w32--set-selection (type value) |
| 398 | (if (eq type 'CLIPBOARD) | 398 | (if (eq type 'CLIPBOARD) |
| 399 | (w32-set-clipboard-data value) | 399 | (w32-set-clipboard-data (replace-regexp-in-string "\0" "\\0" value t t)) |
| 400 | (put 'x-selections (or type 'PRIMARY) value))) | 400 | (put 'x-selections (or type 'PRIMARY) value))) |
| 401 | 401 | ||
| 402 | (defun w32--get-selection (&optional type data-type) | 402 | (defun w32--get-selection (&optional type data-type) |