source: branches/0.16.x/abcl/src/org/armedbear/lisp/debug.lisp

Last change on this file was 12105, checked in by Mark Evenson, 16 years ago

Split StackFrame? abstraction into Java and Lisp stack frames.

From the original patch/idea from Tobias Rittweiler this introduces
more information of primary interest to ABCL implemnters such as when
a form like (make-thread #'(lambda ())) is evaluated

All users of EXT:BACKTRACE-AS-LIST should now use SYS:BACKTRACE, the
results of which is a list of the new builtin classes JAVA_STACK_FRAME
or LISP_STACK_FRAME. The methods SYS:FRAME-TO-STRING and
SYS:FRAME-TO-LIST are defined to break these new objects into
inspectable parts. As a convenience, there is a SYS:BACKTRACE-AS-LIST
which calls SYS:FRAME-TO-LIST to each element of the computed
backtrace.

Refactorings have occurred on the Java side: the misnamed
LispThread?.backtrace() is now LispThread?.printBacktrace().
LispThread?.backtraceAsList() is now LispThread?.backtrace() as it is
a shorter name, and more to the point.

Java stack frames only appear after a call through Lisp.error(), which
has only the top level as a restart as an option.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 5.3 KB
Line 
1;;; debug.lisp
2;;;
3;;; Copyright (C) 2003-2007 Peter Graves
4;;; $Id: debug.lisp 12105 2009-08-19 14:51:56Z mevenson $
5;;;
6;;; This program is free software; you can redistribute it and/or
7;;; modify it under the terms of the GNU General Public License
8;;; as published by the Free Software Foundation; either version 2
9;;; of the License, or (at your option) any later version.
10;;;
11;;; This program is distributed in the hope that it will be useful,
12;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
13;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14;;; GNU General Public License for more details.
15;;;
16;;; You should have received a copy of the GNU General Public License
17;;; along with this program; if not, write to the Free Software
18;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19;;;
20;;; As a special exception, the copyright holders of this library give you
21;;; permission to link this library with independent modules to produce an
22;;; executable, regardless of the license terms of these independent
23;;; modules, and to copy and distribute the resulting executable under
24;;; terms of your choice, provided that you also meet, for each linked
25;;; independent module, the terms and conditions of the license of that
26;;; module.  An independent module is a module which is not derived from
27;;; or based on this library.  If you modify this library, you may extend
28;;; this exception to your version of the library, but you are not
29;;; obligated to do so.  If you do not wish to do so, delete this
30;;; exception statement from your version.
31
32;;; Adapted from SBCL.
33
34(in-package #:extensions)
35
36(export '(*debug-condition* *debug-level* show-restarts))
37
38(defvar *debug-condition* nil)
39
40(defvar *debug-level* 0)
41
42(in-package #:system)
43
44(defun show-restarts (restarts stream)
45  (when restarts
46    (fresh-line stream)
47    (%format stream "Restarts:~%")
48    (let ((max-name-len 0))
49      (dolist (restart restarts)
50        (let ((name (restart-name restart)))
51          (when name
52            (let ((len (length (princ-to-string name))))
53              (when (> len max-name-len)
54                (setf max-name-len len))))))
55      (let ((count 0))
56        (dolist (restart restarts)
57          (let ((name (restart-name restart))
58                (report-function (restart-report-function restart)))
59            (%format stream "  ~D: ~A" count name)
60            (when (functionp report-function)
61              (dotimes (i (1+ (- max-name-len (length (princ-to-string name)))))
62                (write-char #\space stream))
63              (funcall report-function stream))
64            (terpri stream))
65          (incf count))))))
66
67(defun internal-debug ()
68  (if (fboundp 'tpl::repl)
69      (let* ((current-debug-io
70              (if (typep *debug-io* 'synonym-stream)
71                  (symbol-value (synonym-stream-symbol *debug-io*))
72                  *debug-io*))
73             (in (two-way-stream-input-stream current-debug-io))
74             (out (two-way-stream-output-stream current-debug-io)))
75        (loop
76          (tpl::repl in out)))
77      (quit)))
78
79(defun debug-loop ()
80  (let ((*debug-level* (1+ *debug-level*)))
81    (show-restarts (compute-restarts) *debug-io*)
82    (internal-debug)))
83
84(defun invoke-debugger-report-condition (condition)
85  (when condition
86    (fresh-line *debug-io*)
87    (with-standard-io-syntax
88      (let ((*print-structure* nil))
89        (when (and *load-truename* (streamp *load-stream*))
90          (simple-format *debug-io*
91                         "Error loading ~A at line ~D (offset ~D)~%"
92                         *load-truename*
93                         (stream-line-number *load-stream*)
94                         (stream-offset *load-stream*)))
95        (simple-format *debug-io*
96                       (if (fboundp 'tpl::repl)
97                           "Debugger invoked on condition of type ~A:~%"
98                           "Unhandled condition of type ~A:~%")
99                       (type-of condition))
100        (simple-format *debug-io* "  ~A~%" condition)))))
101
102(defun invoke-debugger (condition)
103  (let ((*saved-backtrace* (sys:backtrace)))
104    (when *debugger-hook*
105      (let ((hook-function *debugger-hook*)
106            (*debugger-hook* nil))
107        (funcall hook-function condition hook-function)))
108    (invoke-debugger-report-condition condition)
109    (unless (fboundp 'tpl::repl)
110      (quit))
111    (let ((original-package *package*))
112      (with-standard-io-syntax
113        (let ((*package* original-package)
114              (*print-readably* nil) ; Top-level default.
115              (*print-structure* nil)
116              (*debug-condition* condition)
117              (level *debug-level*))
118          (clear-input)
119          (if (> level 0)
120              (with-simple-restart (abort "Return to debug level ~D." level)
121                (debug-loop))
122              (debug-loop)))))))
123
124(defun break (&optional (format-control "BREAK called") &rest format-arguments)
125  (let ((*debugger-hook* nil)) ; Specifically required by ANSI.
126    (with-simple-restart (continue "Return from BREAK.")
127      (invoke-debugger
128       (%make-condition 'simple-condition
129                        (list :format-control format-control
130                              :format-arguments format-arguments))))
131    nil))
132
133(defun backtrace-as-list (&optional (n 0))
134  "Return BACKTRACE with each element converted to a list."
135  (mapcar #'sys::frame-to-list (sys:backtrace n)))
Note: See TracBrowser for help on using the repository browser.