123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- (define-module (ice-9 debugging ice-9-debugger-extensions)
- #:use-module (ice-9 debugger))
- ;;; Upgrade the debugger state object so that it can carry a flag
- ;;; indicating whether the debugging session is continuable.
- (cond ((string>=? (version) "1.7")
- (use-modules (ice-9 debugger state))
- (define-module (ice-9 debugger state)))
- (else
- (define-module (ice-9 debugger))))
- (set! state-rtd (make-record-type "debugger-state" '(stack index flags)))
- (set! state? (record-predicate state-rtd))
- (set! make-state
- (let ((make-state-internal (record-constructor state-rtd
- '(stack index flags))))
- (lambda (stack index . flags)
- (make-state-internal stack index flags))))
- (set! state-stack (record-accessor state-rtd 'stack))
- (set! state-index (record-accessor state-rtd 'index))
- (define state-flags (record-accessor state-rtd 'flags))
- ;;; Add commands that (ice-9 debugger) doesn't currently have, for
- ;;; continuing or single stepping program execution.
- (cond ((string>=? (version) "1.7")
- (use-modules (ice-9 debugger command-loop))
- (define-module (ice-9 debugger command-loop)
- #:use-module (ice-9 debugger)
- #:use-module (ice-9 debugger state)
- #:use-module (ice-9 debugging traps))
- (define new-define-command define-command)
- (set! define-command
- (lambda (name argument-template documentation procedure)
- (new-define-command name argument-template procedure))))
- (else
- (define-module (ice-9 debugger))))
- (use-modules (ice-9 debugging steps)
- (ice-9 debugging trace))
- (define (assert-continuable state)
- ;; Check that debugger is in a state where `continuing' makes sense.
- ;; If not, signal an error.
- (or (memq #:continuable (state-flags state))
- (user-error "This debug session is not continuable.")))
- (define (debugger:continue state)
- "Tell the program being debugged to continue running. (In fact this is
- the same as the @code{quit} command, because it exits the debugger
- command loop and so allows whatever code it was that invoked the
- debugger to continue.)"
- (assert-continuable state)
- (throw 'exit-debugger))
- (define (debugger:finish state)
- "Continue until evaluation of the current frame is complete, and
- print the result obtained."
- (assert-continuable state)
- (at-exit (- (stack-length (state-stack state))
- (state-index state))
- (list trace-trap debug-trap))
- (debugger:continue state))
- (define (debugger:step state n)
- "Tell the debugged program to do @var{n} more steps from its current
- position. One @dfn{step} means executing until the next frame entry
- or exit of any kind. @var{n} defaults to 1."
- (assert-continuable state)
- (at-step debug-trap (or n 1))
- (debugger:continue state))
- (define (debugger:next state n)
- "Tell the debugged program to do @var{n} more steps from its current
- position, but only counting frame entries and exits where the
- corresponding source code comes from the same file as the current
- stack frame. (See @ref{Step Traps} for the details of how this
- works.) If the current stack frame has no source code, the effect of
- this command is the same as of @code{step}. @var{n} defaults to 1."
- (assert-continuable state)
- (at-step debug-trap
- (or n 1)
- (frame-file-name (stack-ref (state-stack state)
- (state-index state)))
- (if (memq #:return (state-flags state))
- #f
- (- (stack-length (state-stack state)) (state-index state))))
- (debugger:continue state))
- (define-command "continue" '()
- "Continue program execution."
- debugger:continue)
- (define-command "finish" '()
- "Continue until evaluation of the current frame is complete, and
- print the result obtained."
- debugger:finish)
- (define-command "step" '('optional exact-integer)
- "Continue until entry to @var{n}th next frame."
- debugger:step)
- (define-command "next" '('optional exact-integer)
- "Continue until entry to @var{n}th next frame in same file."
- debugger:next)
- ;;; Export a couple of procedures for use by (ice-9 debugging trace).
- (cond ((string>=? (version) "1.7"))
- (else
- (define-module (ice-9 debugger))
- (export write-frame-short/expression
- write-frame-short/application)))
- ;;; Provide a `debug-trap' entry point in (ice-9 debugger). This is
- ;;; designed so that it can be called to explore the stack at a
- ;;; breakpoint, and to single step from the breakpoint.
- (define-module (ice-9 debugger))
- (use-modules (ice-9 debugging traps))
- (define *not-yet-introduced* #t)
- (cond ((string>=? (version) "1.7"))
- (else
- (define (debugger-command-loop state)
- (read-and-dispatch-commands state (current-input-port)))))
- (define-public (debug-trap trap-context)
- "Invoke the Guile debugger to explore the stack at the specified @var{trap}."
- (start-stack 'debugger
- (let* ((stack (tc:stack trap-context))
- (flags1 (let ((trap-type (tc:type trap-context)))
- (case trap-type
- ((#:return #:error)
- (list trap-type
- (tc:return-value trap-context)))
- (else
- (list trap-type)))))
- (flags (if (tc:continuation trap-context)
- (cons #:continuable flags1)
- flags1))
- (state (apply make-state stack 0 flags)))
- (if *not-yet-introduced*
- (let ((ssize (stack-length stack)))
- (display "This is the Guile debugger -- for help, type `help'.\n")
- (set! *not-yet-introduced* #f)
- (if (= ssize 1)
- (display "There is 1 frame on the stack.\n\n")
- (format #t "There are ~A frames on the stack.\n\n" ssize))))
- (write-state-short-with-source-location state)
- (debugger-command-loop state))))
- (define write-state-short-with-source-location
- (cond ((string>=? (version) "1.7")
- write-state-short)
- (else
- (lambda (state)
- (let* ((frame (stack-ref (state-stack state) (state-index state)))
- (source (frame-source frame))
- (position (and source (source-position source))))
- (format #t "Frame ~A at " (frame-number frame))
- (if position
- (display-position position)
- (display "unknown source location"))
- (newline)
- (write-char #\tab)
- (write-frame-short frame)
- (newline))))))
|