3 (declaim (optimize (safety 2) (space 3)))
7 #-gcl
(:compile-toplevel
:execute
)
9 (defmacro f
(op &rest args
)
10 `(the fixnum
(,op
,@ (mapcar #'(lambda (x) `(the fixnum
,x
)) args
))))
12 (defmacro fb
(op &rest args
)
13 `(,op
,@ (mapcar #'(lambda (x) `(the fixnum
,x
)) args
))))
15 ;; This function is not documented and not used in Maxima core or share.
17 (loop for v in
*baktrcl
*
22 ($print
(format nil
"~a:~a:" (nth 1 (cadar v
))
23 (nth 0 (cadar v
))) v
)))
25 ;; *mlambda-call-stack*
26 ;; #(NIL ($X) (1) $FF ($BIL $X) ($Y) (36) $JOE ($Y $BIL $X) ($JJX) (36)
27 ;; to get to current values in ff need to unbind bindlist downto ($BIL $X)
28 ;; to get to current values in joe need to unbind bindlist downto ($Y $BIL $X)
30 (defvar *current-frame
* 0)
32 (defvar $mdebug_print_length
100 "Length of forms to print out in debugger")
34 (defmacro bak-top-form
(x) x
)
38 (let* ((ar *mlambda-call-stack
*)
40 fname vals params backtr lineinfo bdlist
)
42 ;; just in case we do not have an even multiple
43 (setq m
(f - m
(f mod m
5) (* n
5)))
44 (if (<= m
0) (return-from frame-info nil
))
45 (setq fname
(aref ar
(f- m
1)))
46 (setq vals
(aref ar
(f- m
2)))
47 (setq params
(aref ar
(f- m
3)))
48 (setq backtr
(aref ar
(f- m
4)))
49 (setq bdlist
(if (< m
(fill-pointer ar
)) (aref ar m
) bindlist
))
50 ; (setq lineinfo (get-lineinfo backtr))
51 (setq lineinfo
(if ( < m
(fill-pointer ar
))
52 (get-lineinfo (bak-top-form (aref ar
(f+ m
1))))
53 (get-lineinfo (bak-top-form *last-meval1-form
*))))
54 ;; #+if-you-use-baktrcl
55 ;; (if ( < m (fill-pointer ar))
56 ;; (get-lineinfo (bak-top-form (aref ar (f+ m 1))))
57 ;; (or (get-lineinfo (bak-top-form *last-meval1-form*
60 ;; ;(get-lineinfo (bak-top-form (cdr baktrcl)))
62 (values fname vals params backtr lineinfo bdlist
)))
64 (defun print-one-frame (n print-frame-number
&aux val
(st *debug-io
*))
66 (fname vals params backtr lineinfo bdlist
)
69 (princ (if print-frame-number
70 ($sconcat
"#" n
": " fname
"(")
73 (loop for v on params for w in vals
74 do
(setq val
($sconcat w
))
75 (if (> (length val
) 100)
76 (setq val
($sconcat
(subseq val
0 100) "...")))
77 (format st
"~(~a~)=~a~a" ($sconcat
(car v
)) val
81 (format st
(intl:gettext
"(~a line ~a)")
82 (short-name (cadr lineinfo
)) (car lineinfo
)))
84 (values fname vals params backtr lineinfo bdlist
))
87 ;; these are in the system package in gcl...
90 (defun break-call (key args prop
&aux fun
)
91 (setq fun
(complete-prop key
'keyword prop
))
93 (or fun
(return-from break-call nil
))
94 (setq fun
(get fun prop
))
97 (setf (symbol-function gen
) fun
) (setf (get key prop
) gen
)
100 (setq args
(cons fun args
))
102 #+gcl
(evalhook args nil nil
*break-env
*)
105 (t (format *debug-io
*
106 (intl:gettext
"~&~S is an undefined break command.~%")
109 (defun complete-prop (sym package prop
&optional return-list
)
110 (cond ((and (symbolp sym
)(get sym prop
)(equal (symbol-package sym
)
111 (find-package package
)))
112 (return-from complete-prop sym
)))
113 (loop for vv being the symbols of package
114 when
(and (get vv prop
)
115 (eql #+gcl
(string-match sym vv
)
116 #-gcl
(search (symbol-name sym
)
122 (cond (return-list (return-from complete-prop all
))
124 ;; NOTE TO TRANSLATORS: MEANING OF FOLLOWING IS UNKNOWN
127 "~&Not unique with property ~(~a: ~{~s~^, ~}~).")
131 (intl:gettext
"~& No such break command: ~a") sym
))
132 (t (return-from complete-prop
135 (defun $backtrace
(&optional
(n 30))
138 for j from
*current-frame
*
139 while
(print-one-frame j t
))))
141 ;; the following are in the maxima package....
142 ;; they are DIFFERENT from ones in si package..
144 ;; if this is NIL then nothing more is checked in eval
146 (defvar *break-points
* nil
)
147 (defvar *break-point-vector
* (make-array 10 :fill-pointer
0 :adjustable t
))
149 (defun init-break-points ()
150 (setf (fill-pointer *break-point-vector
*) 0)
151 (setf *break-points
* *break-point-vector
*))
153 (defvar *break-step
* nil
)
154 (defvar *step-next
* nil
)
156 (defun step-into (&optional
(n 1))
157 ;;FORM is the next form about to be evaluated.
159 (or *break-points
* (init-break-points))
160 (setq *break-step
* 'break-step-into
)
163 (defun step-next (&optional
(n 1))
165 (let ((fun (current-step-fun)))
166 (setq *step-next
* (cons n fun
))
167 (or *break-points
* (init-break-points))
168 (setq *break-step
* 'break-step-next
)
171 (defun maybe-break (form line-info fun env
&aux pos
)
172 (declare (ignore env
))
173 (cond ((setq pos
(position form line-info
))
174 (setq *break-step
* nil
)
175 (or (> (length *break-points
*) 0)
176 (setf *break-points
* nil
))
177 (break-dbm-loop (make-break-point fun line-info pos
))
180 ;; These following functions, when they are the value of *break-step*
181 ;; are invoked by an inner hook in eval. They may choose to stop things.
182 (defvar *break-step
* nil
)
183 (defun break-step-into (form &optional env
)
184 (let ((fun (current-step-fun)))
185 (let ((line-info (set-full-lineinfo fun
)))
187 (maybe-break form line-info fun env
)))))
189 (defun break-step-next (form &optional env
)
190 (let ((fun (current-step-fun)))
191 (cond ((eql (cdr *step-next
*) fun
)
192 (let ((line-info (set-full-lineinfo fun
)))
193 (maybe-break form line-info fun env
))))))
195 (defvar *lineinfo-array-internal
* nil
)
197 ;; the lineinfo for a function will be a vector of forms
198 ;; such that each one is the first form on a line.
199 ;; we will walk thru the tree taking the first occurrence
201 (defun set-full-lineinfo (fname &aux te
)
202 (let ((body (get fname
'lineinfo
)))
203 (cond ((atom body
) (return-from set-full-lineinfo body
))
204 (t (cond ((null *lineinfo-array-internal
*)
205 (setq *lineinfo-array-internal
*
206 (make-array 20 :fill-pointer
0 :adjustable t
)))
207 (t (setf (fill-pointer *lineinfo-array-internal
*) 0)))
208 (cond ((setq te
(get-lineinfo body
))
209 (vector-push (car te
) *lineinfo-array-internal
*)
210 (walk-get-lineinfo body
*lineinfo-array-internal
*)))
211 (cond ((> (fill-pointer *lineinfo-array-internal
*) 0)
212 (setf (get fname
'lineinfo
)
213 (copy-seq *lineinfo-array-internal
*)))
214 (t (setf (get fname
'lineinfo
) nil
)))))))
216 (defun walk-get-lineinfo (form ar
&aux
(i 0) tem
)
217 (declare (type (vector t
) ar
) (fixnum i
))
218 (cond ((atom form
) nil
)
219 ((setq tem
(get-lineinfo form
))
220 (setq i
(f -
(line-info-line tem
) (aref ar
0) -
1))
221 (cond ((< i
(fill-pointer ar
))
223 (setf (aref ar i
) form
)))
225 (unless (< i
(array-total-size ar
))
226 (setq ar
(adjust-array ar
(+ i
20) :fill-pointer
228 (loop for j from
(fill-pointer ar
) below i
229 do
(setf (aref ar j
) nil
))
230 (setf (fill-pointer ar
) (f + i
1))
231 (setf (aref ar i
) form
)))
232 (loop for v in
(cdr form
)
234 (walk-get-lineinfo v ar
))))))
236 (defun first-form-line (form line
&aux tem
)
237 (cond ((atom form
) nil
)
238 ((and (setq tem
(get-lineinfo form
)) (eql (car tem
) line
))
240 (t (loop for v in
(cdr form
)
241 when
(setq tem
(first-form-line v line
))
242 do
(return-from first-form-line tem
)))))
244 (defvar *last-dbm-command
* nil
)
246 ;; split string into a list of strings, split by any of a list of characters
247 ;; in bag. Returns a list. They will have fill pointers..
248 (defun split-string (string bag
&optional
(start 0) &aux all pos v l
)
249 (declare (fixnum start
) (type string string
))
250 (loop for i from start below
(length string
)
251 do
(setq pos
(position (setq v
(aref string i
)) bag
))
252 (setq start
(+ start
1))
253 (cond ((null pos
) (push v all
))
254 (t (if all
(loop-finish))))
257 (return-from split-string
259 (make-array (setq l
(length all
))
262 :initial-contents
(nreverse all
)
264 ' #.
(array-element-type "ab"))
265 (split-string string bag start
))))))
267 (declaim (special *mread-prompt
*))
269 ;; RLT: What is the repeat-if-newline option for? A grep of the code
270 ;; indicates that dbm-read is never called with more than 3 args. Can
271 ;; we just flush it? Can probably get rid of the &aux stuff too.
273 (defvar *need-prompt
* t
)
275 (defun dbm-read (&optional
(stream *standard-input
*) (eof-error-p t
)
276 (eof-value nil
) repeat-if-newline
&aux tem ch
277 (mprompt *mread-prompt
*) (*mread-prompt
* ""))
278 (if (and *need-prompt
* (> (length mprompt
) 0))
280 (fresh-line *standard-output
*)
281 (princ mprompt
*standard-output
*)
282 (force-output *standard-output
*)
283 (setf *prompt-on-read-hang
* nil
))
285 (setf *prompt-on-read-hang
* t
)
286 (setf *read-hang-prompt
* mprompt
)))
288 ;; Read a character to see what we should do.
291 (setq ch
(read-char stream eof-error-p eof-value
))
292 (cond ((or (eql ch
#\newline
) (eql ch
#\return
))
293 (if (and repeat-if-newline
*last-dbm-command
*)
294 (return-from dbm-read
*last-dbm-command
*))
297 (return-from dbm-read eof-value
)))
298 ;; Put that character back, so we can reread the line correctly.
299 (unread-char ch stream
))
301 ;; Figure out what to do
303 ;; This is a Maxima debugger command (I think)
304 (let* ((line (read-line stream eof-error-p eof-value
))
308 (read-from-string line
)
309 (setq fun
(complete-prop keyword
'keyword
'break-command
))
310 (and (consp fun
) (setq fun
(car fun
)))
311 ;;(print (list 'line line))
312 (setq *last-dbm-command
*
313 (cond ((null fun
) '(:_none
))
314 ((get fun
'maxima-read
)
315 (cons keyword
(mapcar 'macsyma-read-string
316 (split-string line
" " n
))))
318 ($sconcat
"(" (string-right-trim ";" line
)
320 ;;(print (list 'tem tem))
321 (read (make-string-input-stream tem
)
322 eof-error-p eof-value
)))))))
324 ;; Process "?" lines. This is either a call to describe or a
325 ;; quick temporary escape to Lisp to call some Lisp function.
327 ;; First, read and discard the #\? since we don't need it anymore.
329 (let ((next (peek-char nil stream nil
)))
330 (cond ((member next
'(#\space
#\tab
#\
!))
331 ;; Got "? <stuff>" or "?! <stuff>".
332 ;; Invoke exact search on <stuff>.
333 (let* ((line (string-trim
334 '(#\space
#\tab
#\
; #\$)
336 (read-line stream eof-error-p eof-value
) 1))))
337 `((displayinput) nil
(($describe
) ,line $exact
))))
339 ;; Got "?? <stuff>". Invoke inexact search on <stuff>.
340 (let* ((line (string-trim
341 '(#\space
#\tab
#\
; #\$)
343 (read-line stream eof-error-p eof-value
) 1))))
344 `((displayinput) nil
(($describe
) ,line $inexact
))))
346 ;; Got "?<stuff>" This means a call to a Lisp
347 ;; function. Pass this on to mread which can handle
350 ;; Note: There appears to be a bug in Allegro 6.2
351 ;; where concatenated streams don't wait for input
352 ;; on *standard-input*.
353 (mread (make-concatenated-stream
354 (make-string-input-stream "?") stream
)
357 (setq *last-dbm-command
* nil
)
358 (let ((result (mread stream eof-value
))
359 (next-char (read-char-no-hang stream eof-error-p eof-value
)))
361 ((or (eql next-char nil
) (equal next-char
'(nil)))
362 (setf *need-prompt
* t
))
363 ((member next-char
'(#\newline
#\return
))
364 (setf *need-prompt
* t
))
366 (setf *need-prompt
* nil
)
367 (unread-char next-char stream
)))
370 (defvar *break-level
* nil
)
371 (defvar *break-env
* nil
)
372 (defvar *top-eof
* (cons nil nil
))
373 (defvar *quit-tag
* 'macsyma-quit
)
375 ;;(defvar *quit-tag* 'si::*quit-tag*)
377 (defvar *quit-tags
* nil
)
379 (defun set-env (bkpt)
381 (intl:gettext
"(~a ~a~@[ in ~a~])")
382 (short-name (bkpt-file bkpt
))
383 (bkpt-file-line bkpt
)
384 nil
) ; (bkpt-function bkpt)
385 (format *debug-io
* "~&\x1a\x1a~a:~a::~%" (bkpt-file bkpt
)
386 (bkpt-file-line bkpt
)))
388 (defvar *diff-mspeclist
* nil
)
389 (defvar *diff-bindlist
* nil
)
391 (defun break-dbm-loop (at)
392 (let* ((*quit-tags
* (cons (cons *break-level
* *quit-tag
*) *quit-tags
*))
393 (*break-level
* (if (not at
) *break-level
* (cons t
*break-level
*)))
394 (*quit-tag
* (cons nil nil
))
395 (*break-env
* *break-env
*)
397 (*diff-bindlist
* nil
)
398 (*diff-mspeclist
* nil
)
400 (declare (special *mread-prompt
*))
401 (and (consp at
) (set-env at
))
403 (break-frame 0 nil
)))
404 (catch 'step-continue
408 (format-prompt *debug-io
* "~a"
409 (format nil
"~&~@[(~a:~a) ~]"
410 (unless (stringp at
) "dbm")
411 (length *quit-tags
*)))
412 (finish-output *debug-io
*)
415 (let ((res (dbm-read *debug-io
* nil
*top-eof
* t
)))
416 (declare (special *mread-prompt
*))
417 (cond ((and (consp res
) (keywordp (car res
)))
418 (let ((value (break-call (car res
)
421 (cond ((eq value
:resume
) (return)))))
423 (funcall (get :top
'break-command
)))
425 (setq $__
(nth 2 res
))
426 (setq $%
(meval* $__
))
431 (throw-macsyma-top)))
432 (restore-bindings))))))
434 (defun break-quit (&optional
(level 0)
435 &aux
(current-level (length *break-level
*)))
436 (when (and (>= level
0) (< level current-level
))
437 (let ((x (nth (- current-level level
1) *quit-tags
*)))
438 (if (eq (cdr x
) 'macsyma-quit
)
439 (throw 'macsyma-quit
'top
)
440 (throw (cdr x
) (cdr x
)))))
441 (throw 'macsyma-quit
'top
))
443 (defun break-current ()
446 (intl:gettext
"Back to level ~:@(~S~).")
447 (length *break-level
*))
448 (format *debug-io
* (intl:gettext
"~&Top level.")))
451 (defun def-break (keyword fun doc
)
452 (setf (get keyword
'break-command
) fun
)
453 (and doc
(setf (get keyword
'break-doc
) doc
)))
455 (defun break-help (&optional key
)
458 (dolist (v (complete-prop key
'keyword
'break-doc t
))
459 (format t
"~&~%~(~s~) ~a" v
(get v
'break-doc
)))))
461 (loop for vv being the symbols of
'keyword
462 when
(get vv
'break-command
)
463 collect
(cons vv
(or (get vv
'break-doc
) "Undocumented"))
465 finally
(setq all
(sort all
'alphalessp
))
466 (format t
(intl:gettext
"~
467 Break commands start with ':'. Any unique substring may be used,~%~
468 eg :r :re :res all work for :resume.~2%~
469 Command Description~%~
470 ----------- --------------------------------------"))
472 do
(format t
"~% ~(~12s~)" (car vv
))
476 (def-break :help
'break-help
477 "Print help on a break command or with no arguments on
480 ;; What is this debug command for?
481 (def-break :_none
#'(lambda()) nil
)
483 (def-break :next
'step-next
484 "Like :step, except that subroutine calls are stepped over")
486 (def-break :step
'step-into
487 "Step program until it reaches a new source line")
489 ;;(def-break :location 'loc "" )
491 (def-break :quit
'break-quit
494 (def-break :top
#'(lambda( &rest l
)l
(throw 'macsyma-quit
'top
))
495 "Throw to top level")
497 (defstruct (line-info (:type list
)) line file
)
499 (defstruct (bkpt (:type list
)) form file file-line function
)
501 (defun *break-points
* (form)
502 (let ((pos(position form
*break-points
* :key
'car
)))
503 (format t
"Bkpt ~a:" pos
)
504 (break-dbm-loop (aref *break-points
* pos
))))
506 ;; fun = function name eg '$|odeSeriesSolve| and
507 ;; li = offset from beginning of function.
508 ;; Or fun = string (filename) and li = absolute position.
510 (defun break-function (fun &optional
(li 0) absolute
511 &aux i tem info form fun-line
)
513 (format t
"~&Turning on debugging debugmode(true)")
516 (let ((file fun
) start
)
517 (loop named joe for vv being the symbols of
'maxima with tem with linfo
518 when
(and (typep (setq tem
(set-full-lineinfo vv
))
520 (setq linfo
(get-lineinfo (aref tem
1)))
521 (equal file
(cadr linfo
))
522 (fb >= li
(setq start
(aref tem
0)))
523 (fb <= li
(+ start
(length (the vector tem
)))))
524 do
(setq fun vv li
(f- li start -
1))
525 ; (print (list 'found fun fun li (aref tem 0)))
526 (return-from joe nil
)
528 (format t
"No line info for ~a " fun
)
529 (return-from break-function nil
)))))
530 (setq fun
($concat fun
))
531 ; (print (list 'fun fun 'hi))
532 (cond ((and (setq tem
(second (mgetl fun
'(mexpr mmacro
))))
533 (setq info
(get-lineinfo (setq form
(third tem
))))
534 (eq (third info
) 'src
))
535 (setq fun-line
(fifth info
))
536 (or (fixnump fun-line
) (setq fun-line
(line-info-line info
)))
537 ; (print (list 'fun-line fun-line))
538 (setq form
(first-form-line
541 (if absolute
0 fun-line
) li
))))
544 (return-from break-function
(break-function fun
1)))
545 (format t
"~& No instructions recorded for this line ~a of ~a" li
547 (return-from break-function nil
))
548 (let ((n (insert-break-point (make-bkpt :form form
550 :file
(line-info-file info
)
552 (format t
"~&Bkpt ~a for ~a (in ~a line ~a) ~%"
553 n
($sconcat fun
) (line-info-file info
) i
)
555 (t (format t
"No line info for ~a " fun
))))
557 ;; note need to make the redefine function, fixup the break point list..
559 (defun make-break-point (fun ar i
)
560 (declare (fixnum i
) (type (vector t
) ar
))
561 (let* ((tem (aref ar i
))
562 (linfo (get-lineinfo tem
)))
563 (and linfo
(list tem
(cadr linfo
) (car linfo
) fun
))))
565 (defun dbm-up (n &aux
(cur *current-frame
*) (m (length *mlambda-call-stack
*)))
566 (declare (fixnum n m cur
))
567 (setq m
(quotient m
5))
575 (defun insert-break-point (bpt &aux at
)
576 (or *break-points
* (init-break-points))
577 (setq at
(or (position nil
*break-points
*)
578 (prog1 (length *break-points
*)
579 (vector-push-extend nil
*break-points
*))))
580 (let ((fun (bkpt-function bpt
)))
581 (push at
(get fun
'break-points
)))
582 (setf (aref *break-points
* at
) bpt
)
585 (defun short-name (name)
586 (let ((pos (position #\
/ name
:from-end t
)))
587 (if pos
(subseq name
(f + 1 pos
)) name
)))
589 (defun show-break-point (n &aux disabled
)
590 (let ((bpt (aref *break-points
* n
)))
592 (when (eq (car bpt
) nil
)
594 (setq bpt
(cdr bpt
)))
595 (format t
"Bkpt ~a:(~a line ~a)~@[(disabled)~]"
596 n
(short-name (second bpt
))
597 (third bpt
) disabled
)
598 (let ((fun (fourth bpt
)))
599 (format t
"(line ~a of ~a)" (relative-line fun
(nth 2 bpt
))
602 (defun relative-line (fun l
)
603 (let ((info (set-full-lineinfo fun
)))
604 (if info
(f - l
(aref info
0))
607 (defun iterate-over-bkpts (l action
)
608 (dotimes (i (length *break-points
*))
611 (let ((tem (aref *break-points
* i
)))
612 (setf (aref *break-points
* i
)
616 (pop tem
)) ; disabled or already deleted bkpt
618 (setf (get (bkpt-function tem
) 'break-points
)
620 (get (bkpt-function tem
) 'break-points
))))
623 (if (eq (car tem
) nil
) (cdr tem
) tem
))
625 (if (and tem
(not (eq (car tem
) nil
)))
629 (when tem
(show-break-point i
)
633 ;; get the most recent function on the stack with step info.
635 (defun current-step-fun ( &aux fun
)
636 (loop for i below
100000
637 while
(setq fun
(frame-info i
))
638 do
(cond ((and (symbolp fun
) (set-full-lineinfo fun
))
639 (return-from current-step-fun fun
)))))
641 (def-break :bt
'$backtrace
"Print a backtrace of the stack frames")
643 (def-break :info
#'(lambda (&optional type
)
645 (:bkpt
(iterate-over-bkpts nil
:show
)(values))
648 "usage: :info :bkpt -- show breakpoints"))))
649 "Print information about item")
651 (defmacro lisp-quiet
(&rest l
)
652 (setq *mread-prompt
* "")
653 (eval (cons 'progn l
)))
655 (def-break :lisp-quiet
'lisp-quiet
656 "Evaluate the lisp form without printing a prompt")
658 (def-break :lisp
'lisp-eval
659 "Evaluate the lisp form following on the line")
661 (defmacro lisp-eval
(&rest l
)
662 (dolist (v (multiple-value-list (eval (cons 'progn l
))))
663 (fresh-line *standard-output
*)
666 (def-break :delete
#'(lambda (&rest l
) (iterate-over-bkpts l
:delete
) (values))
667 "Delete all breakpoints, or if arguments are supplied delete the
668 specified breakpoints")
670 (def-break :frame
'break-frame
671 "With an argument print the selected stack frame.
672 Otherwise the current frame.")
674 (def-break :resume
#'(lambda () :resume
)
675 "Continue the computation.")
677 (def-break :continue
#'(lambda () :resume
)
678 "Continue the computation.")
681 #'(lambda (&rest l
) (iterate-over-bkpts l
:disable
)(values))
682 "Disable the specified breakpoints, or all if none are specified")
684 (def-break :enable
#'(lambda (&rest l
) (iterate-over-bkpts l
:enable
)(values))
685 "Enable the specified breakpoints, or all if none are specified")
687 (def-break :break
'do-break
688 "Set a breakpoint in the specified FUNCTION at the
689 specified LINE offset from the beginning of the function.
690 If FUNCTION is given as a string, then it is presumed to be
691 a FILE and LINE is the offset from the beginning of the file.")
693 ;; force the rest of the line to be broken at spaces,
694 ;; and each item read as a maxima atom.
695 (setf (get :break
'maxima-read
) t
)
697 (defmacro do-break
(&optional name
&rest l
)
698 (declare (special *last-dbl-break
*))
701 (let ((fun (nth 3 *last-dbl-break
*)))
702 (break-function fun
(nth 2 *last-dbl-break
*) t
))))
703 (t (eval `(break-function ',name
,@l
)))))
705 ;; this just sets up a counter for each stream.. we want
706 ;; it to start at one.
708 (defun get-lineinfo (form)
710 (if (consp (cadar form
))
712 (if (consp (caddar form
))
717 ;; restore-bindings from an original binding list.
718 (defun restore-bindings ()
719 (mbind *diff-bindlist
* *diff-mspeclist
* nil
)
720 (setf *diff-bindlist
* nil
*diff-mspeclist
* nil
))
722 (defun remove-bindings (the-bindlist)
723 (loop for v on bindlist with var
725 until
(eq v the-bindlist
)
728 (push var
*diff-bindlist
*)
729 (push (symbol-value var
) *diff-mspeclist
*)
730 (cond ((eq (car mspeclist
) munbound
)
732 (setq $values
(delete var $values
:count
1 :test
#'eq
)))
733 (t (let ((munbindp t
)) (mset var
(car mspeclist
)))))
734 (setq mspeclist
(cdr mspeclist
) bindlist
(cdr bindlist
))))
736 (defun break-frame (&optional
(n 0) (print-frame-number t
))
738 (multiple-value-bind (fname vals params backtr lineinfo bdlist
)
739 (print-one-frame n print-frame-number
)
740 backtr params vals fname
741 (remove-bindings bdlist
)
743 (fresh-line *debug-io
*)
744 (format *debug-io
* "\x1a\x1a~a:~a::~%" (cadr lineinfo
) (+ 0 (car lineinfo
))))