1 ;;;; miscellaneous stuff that needs to be in the cold load which would
2 ;;;; otherwise be byte-compiled
4 ;;;; This software is part of the SBCL system. See the README file for
7 ;;;; This software is derived from the CMU CL system, which was
8 ;;;; written at Carnegie Mellon University and released into the
9 ;;;; public domain. The software is in the public domain and is
10 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
11 ;;;; files for more information.
13 (in-package "SB!KERNEL")
15 (defvar *break-on-signals* nil
17 "When (TYPEP condition *BREAK-ON-SIGNALS*) is true, then calls to SIGNAL will
18 enter the debugger prior to signalling that condition.")
20 (defun signal (datum &rest arguments)
22 "Invokes the signal facility on a condition formed from DATUM and
23 ARGUMENTS. If the condition is not handled, NIL is returned. If
24 (TYPEP condition *BREAK-ON-SIGNALS*) is true, the debugger is invoked
25 before any signalling is done."
26 (let ((condition (coerce-to-condition datum
30 (*handler-clusters* *handler-clusters*))
31 (let ((old-bos *break-on-signals*)
32 (*break-on-signals* nil))
33 (when (typep condition old-bos)
34 (break "~A~%BREAK was entered because of *BREAK-ON-SIGNALS* (now NIL)."
37 (unless *handler-clusters* (return))
38 (let ((cluster (pop *handler-clusters*)))
39 (dolist (handler cluster)
40 (when (typep condition (car handler))
41 (funcall (cdr handler) condition)))))
44 ;;; COERCE-TO-CONDITION is used in SIGNAL, ERROR, CERROR, WARN, and
45 ;;; INVOKE-DEBUGGER for parsing the hairy argument conventions into a single
46 ;;; argument that's directly usable by all the other routines.
47 (defun coerce-to-condition (datum arguments default-type function-name)
48 (cond ((typep datum 'condition)
50 (cerror "Ignore the additional arguments."
54 :format-control "You may not supply additional arguments ~
55 when giving ~S to ~S."
56 :format-arguments (list datum function-name)))
58 ((symbolp datum) ; roughly, (SUBTYPEP DATUM 'CONDITION)
59 (apply #'make-condition datum arguments))
60 ((or (stringp datum) (functionp datum))
61 (make-condition default-type
63 :format-arguments arguments))
65 (error 'simple-type-error
67 :expected-type '(or symbol string)
68 :format-control "bad argument to ~S: ~S"
69 :format-arguments (list function-name datum)))))
71 ;;; a shared idiom in ERROR, CERROR, and BREAK: The user probably
72 ;;; doesn't want to hear that the error "occurred in" one of these
73 ;;; functions, so we try to point the top of the stack to our caller
75 (eval-when (:compile-toplevel :execute)
76 (defmacro-mundanely maybe-find-stack-top-hint ()
77 `(or sb!debug:*stack-top-hint*
78 (nth-value 1 (sb!kernel:find-caller-name-and-frame)))))
80 (defun error (datum &rest arguments)
82 "Invoke the signal facility on a condition formed from datum and arguments.
83 If the condition is not handled, the debugger is invoked."
84 (/show0 "entering ERROR, argument list=..")
86 (/show0 "printing ERROR arguments one by one..")
87 #!+sb-show (dolist (argument arguments)
88 (sb!impl::cold-print argument))
89 (sb!kernel:infinite-error-protect
90 (let ((condition (coerce-to-condition datum arguments
91 'simple-error 'error))
92 (sb!debug:*stack-top-hint* (maybe-find-stack-top-hint)))
93 (let ((sb!debug:*stack-top-hint* nil))
95 (invoke-debugger condition))))
97 (defun cerror (continue-string datum &rest arguments)
98 (sb!kernel:infinite-error-protect
100 (continue "~A" (apply #'format nil continue-string arguments))
101 (let ((condition (if (typep datum 'condition)
103 (coerce-to-condition datum
107 (sb!debug:*stack-top-hint* (maybe-find-stack-top-hint)))
108 (with-condition-restarts condition (list (find-restart 'continue))
109 (let ((sb!debug:*stack-top-hint* nil))
111 (invoke-debugger condition)))))
114 ;;; like BREAK, but without rebinding *DEBUGGER-HOOK* to NIL, so that
115 ;;; we can use it in system code (e.g. in SIGINT handling) without
116 ;;; messing up --noprogrammer mode (which works by setting
118 (defun %break (what &optional (datum "break") &rest arguments)
119 ;; FIXME: Do we really want INFINITE-ERROR-PROTECT in BREAKish stuff?
120 (sb!kernel:infinite-error-protect
121 (with-simple-restart (continue "Return from ~S." what)
122 (let ((sb!debug:*stack-top-hint* (maybe-find-stack-top-hint)))
124 (coerce-to-condition datum arguments 'simple-condition what)))))
127 (defun break (&optional (datum "break") &rest arguments)
129 "Print a message and invoke the debugger without allowing any possibility
130 of condition handling occurring."
131 (let ((*debugger-hook* nil)) ; as specifically required by ANSI
132 (apply #'%break 'break datum arguments)))
134 (defun warn (datum &rest arguments)
136 "Warn about a situation by signalling a condition formed by DATUM and
137 ARGUMENTS. While the condition is being signaled, a MUFFLE-WARNING restart
138 exists that causes WARN to immediately return NIL."
139 (/noshow0 "entering WARN")
140 ;; KLUDGE: The current cold load initialization logic causes several calls
141 ;; to WARN, so we need to be able to handle them without dying. (And calling
142 ;; FORMAT or even PRINC in cold load is a good way to die.) Of course, the
143 ;; ideal would be to clean up cold load so that it doesn't call WARN..
145 (if (not *cold-init-complete-p*)
147 (/show0 "ignoring WARN in cold init, arguments=..")
148 #!+sb-show (dolist (argument arguments)
149 (sb!impl::cold-print argument)))
150 (sb!kernel:infinite-error-protect
151 (let ((condition (coerce-to-condition datum arguments
152 'simple-warning 'warn)))
153 (enforce-type condition warning)
154 (restart-case (signal condition)
156 :report "Skip warning."
157 (return-from warn nil)))
158 (let ((badness (etypecase condition
159 (style-warning 'style-warning)
160 (warning 'warning))))
161 (format *error-output*
162 "~&~@<~S: ~3i~:_~A~:>~%"