1 ;;;; "break.scm" Breakpoints for debugging in Scheme.
2 ;;; Copyright (C) 1991, 1992, 1993, 1995 Aubrey Jaffer.
4 ;Permission to copy this software, to redistribute it, and to use it
5 ;for any purpose is granted, subject to the following restrictions and
8 ;1. Any copy made of this software must include this copyright notice
11 ;2. I have made no warrantee or representation that the operation of
12 ;this software will be error-free, and I am under no obligation to
13 ;provide any services, by way of maintenance, update, or otherwise.
15 ;3. In conjunction with products arising from the use of this
16 ;material, there shall be no use of my name in any advertising,
17 ;promotional, or sales literature without prior written consent in
24 ;;; Typing (init-debug) at top level sets up a continuation for
25 ;;; breakpoint. When (breakpoint arg1 ...) is then called it returns
26 ;;; from the top level continuation and pushes the continuation from
27 ;;; which it was called on breakpoint:continuation-stack. If
28 ;;; (continue) is later called, it pops the topmost continuation off
29 ;;; of breakpoint:continuation-stack and returns #f to it.
31 (define breakpoint:continuation-stack '())
33 (define debug:breakpoint
34 (let ((call-with-current-continuation call-with-current-continuation)
35 (apply apply) (qpn qpn)
36 (cons cons) (length length))
38 (if (provided? 'trace) (print-call-stack (current-error-port)))
39 (apply qpn "BREAKPOINT:" args)
41 (call-with-current-continuation
43 (set! breakpoint:continuation-stack
44 (cons x breakpoint:continuation-stack))
45 (debug:top-continuation
46 (length breakpoint:continuation-stack))))))
47 (cond ((not (eq? ans breakpoint:continuation-stack)) ans))))))
49 (define debug:continue
50 (let ((null? null?) (car car) (cdr cdr))
52 (cond ((null? breakpoint:continuation-stack)
53 (display "; no break to continue from")
56 (let ((cont (car breakpoint:continuation-stack)))
57 (set! breakpoint:continuation-stack
58 (cdr breakpoint:continuation-stack))
59 (if (null? args) (cont #f)
60 (apply cont args))))))))
62 (define debug:top-continuation
63 (if (provided? 'abort)
64 (lambda (val) (display val) (newline) (abort))
65 (begin (display "; type (init-debug)") #f)))
68 (call-with-current-continuation
69 (lambda (x) (set! debug:top-continuation x))))
71 (define breakpoint debug:breakpoint)
72 (define bkpt debug:breakpoint)
73 (define continue debug:continue)
76 (let ((null? null?) ;These bindings are so that
77 (not not) ;breakf will not break on parts
78 (car car) (cdr cdr) ;of itself.
79 (eq? eq?) (+ +) (zero? zero?) (modulo modulo)
80 (apply apply) (display display) (breakpoint debug:breakpoint))
81 (lambda (function . optname)
82 ;; (set! trace:indent 0)
83 (let ((name (if (null? optname) function (car optname))))
85 (cond ((and (not (null? args))
86 (eq? (car args) 'debug:unbreak-object)
90 (breakpoint name args)
91 (apply function args))))))))
93 ;;; the reason I use a symbol for debug:unbreak-object is so
94 ;;; that functions can still be unbreaked if this file is read in twice.
96 (define (unbreakf function)
97 ;; (set! trace:indent 0)
98 (function 'debug:unbreak-object))
100 ;;;;The break: functions wrap around the debug: functions to provide
101 ;;; niceties like keeping track of breakd functions and dealing with
105 (define break:adder (alist-associator eq?))
106 (define break:deler (alist-remover eq?))
108 (define *breakd-procedures* '())
109 (define (break:breakf fun sym)
110 (cond ((not (procedure? fun))
111 (display "WARNING: not a procedure " (current-error-port))
112 (display sym (current-error-port))
113 (newline (current-error-port))
114 (set! *breakd-procedures* (break:deler *breakd-procedures* sym))
117 (let ((p (assq sym *breakd-procedures*)))
118 (cond ((and p (eq? (cdr p) fun))
121 (let ((tfun (breakf fun sym)))
122 (set! *breakd-procedures*
123 (break:adder *breakd-procedures* sym tfun))
126 (define (break:unbreakf fun sym)
127 (let ((p (assq sym *breakd-procedures*)))
128 (set! *breakd-procedures* (break:deler *breakd-procedures* sym))
129 (cond ((not (procedure? fun)) fun)
135 ;;;; Finally, the macros break and unbreak
139 `(begin ,@(map (lambda (x) `(set! ,x (break:breakf ,x ',x)))
140 (map car *breakd-procedures*))
141 (map car *breakd-procedures*))
142 `(begin ,@(map (lambda (x) `(set! ,x (break:breakf ,x ',x))) xs))))
146 `(begin ,@(map (lambda (x) `(set! ,x (break:unbreakf ,x ',x)))
147 (map car *breakd-procedures*))
148 '',(map car *breakd-procedures*)))
149 `(begin ,@(map (lambda (x) `(set! ,x (break:unbreakf ,x ',x))) xs))))