1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-20 11:40:18 +02:00

remove (ice-9 debugger) and (ice-9 debugging)

* module/ice-9/debugger.scm:
* module/ice-9/debugger/command-loop.scm:
* module/ice-9/debugger/commands.scm:
* module/ice-9/debugger/state.scm:
* module/ice-9/debugger/trc.scm:
* module/ice-9/debugger/utils.scm:
* module/ice-9/debugging/breakpoints.scm:
* module/ice-9/debugging/example-fns.scm:
* module/ice-9/debugging/ice-9-debugger-extensions.scm:
* module/ice-9/debugging/load-hooks.scm:
* module/ice-9/debugging/steps.scm:
* module/ice-9/debugging/trace.scm:
* module/ice-9/debugging/traps.scm:
* module/ice-9/debugging/trc.scm: Remove these files, as we will favor
  the REPL's implementation of a debugger, and (system vm traps) and
  (system vm trap-state). But these old files will continue to inspire
  the rest of the new debugger interface.
This commit is contained in:
Andy Wingo 2010-09-24 18:24:41 +02:00
parent 3b494f511a
commit d2c7e7de40
15 changed files with 0 additions and 3047 deletions

View file

@ -353,16 +353,6 @@ NOCOMP_SOURCES = \
ice-9/quasisyntax.scm \
system/base/lalr.upstream.scm \
system/repl/describe.scm \
ice-9/debugger/command-loop.scm \
ice-9/debugger/commands.scm \
ice-9/debugger/state.scm \
ice-9/debugger/trc.scm \
ice-9/debugger/utils.scm \
ice-9/debugging/example-fns.scm \
ice-9/debugging/steps.scm \
ice-9/debugging/trace.scm \
ice-9/debugging/traps.scm \
ice-9/debugging/trc.scm \
sxml/sxml-match.ss \
sxml/upstream/SSAX.scm \
sxml/upstream/SXML-tree-trans.scm \

View file

@ -1,167 +0,0 @@
;;;; Guile Debugger
;;; Copyright (C) 1999, 2001, 2002, 2006, 2010 Free Software Foundation, Inc.
;;;
;;;; This library is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public
;;;; License as published by the Free Software Foundation; either
;;;; version 3 of the License, or (at your option) any later version.
;;;;
;;;; This library is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;;;; Lesser General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU Lesser General Public
;;;; License along with this library; if not, write to the Free Software
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
(define-module (ice-9 debugger)
#:use-module (ice-9 debugger command-loop)
#:use-module (ice-9 debugger state)
#:use-module (ice-9 debugger utils)
#:use-module (ice-9 debugging traps)
#:use-module (ice-9 scm-style-repl)
#:use-module (ice-9 save-stack)
#:use-module (ice-9 format)
#:export (debug-stack
debug
debug-last-error
debugger-error
debugger-quit
debugger-input-port
debugger-output-port
debug-on-error)
#:no-backtrace)
;;; The old (ice-9 debugger) has been factored into its constituent
;;; parts:
;;;
;;; (ice-9 debugger) - public interface to all of the following
;;;
;;; (... commands) - procedures implementing the guts of the commands
;;; provided by the interactive debugger
;;;
;;; (... command-loop) - binding these commands into the interactive
;;; debugger command loop
;;;
;;; (... state) - implementation of an object that tracks current
;;; debugger state
;;;
;;; (... utils) - utilities for printing out frame and stack
;;; information in various formats
;;;
;;; The division between (... commands) and (... command-loop) exists
;;; because I (NJ) have another generic command loop implementation
;;; under development, and I want to be able to switch easily between
;;; that and the command loop implementation here. Thus the
;;; procedures in this file delegate to a debugger command loop
;;; implementation via the `debugger-command-loop-*' interface. The
;;; (ice-9 debugger command-loop) implementation can be replaced by
;;; any other that implements the `debugger-command-loop-*' interface
;;; simply by changing the relevant #:use-module line above.
;;;
;;; - Neil Jerram <neil@ossau.uklinux.net> 2002-10-26, updated 2005-07-09
(define *not-yet-introduced* #t)
(define (debug-stack stack . flags)
"Invoke the Guile debugger to explore the specified @var{stack}.
@var{flags}, if present, are keywords indicating characteristics of
the debugging session: the valid keywords are as follows.
@table @code
@item #:continuable
Indicates that the debugger is being invoked from a context (such as
an evaluator trap handler) where it is possible to return from the
debugger and continue normal code execution. This enables the
@dfn{continuing execution} commands, for example @code{continue} and
@code{step}.
@item #:with-introduction
Indicates that the debugger should display an introductory message.
@end table"
(start-stack 'debugger
(let ((state (apply make-state stack 0 flags)))
(with-input-from-port (debugger-input-port)
(lambda ()
(with-output-to-port (debugger-output-port)
(lambda ()
(if (or *not-yet-introduced*
(memq #:with-introduction flags))
(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 state)
(debugger-command-loop state))))))))
(define (debug)
"Invoke the Guile debugger to explore the context of the last error."
(let ((stack (fluid-ref the-last-stack)))
(if stack
(debug-stack stack)
(display "Nothing to debug.\n"))))
(define debug-last-error debug)
(define (debugger-error message)
"Signal a debugger usage error with message @var{message}."
(debugger-command-loop-error message))
(define (debugger-quit)
"Exit the debugger."
(debugger-command-loop-quit))
;;; {Debugger Input and Output Ports}
(define debugger-input-port
(let ((input-port (current-input-port)))
(make-procedure-with-setter
(lambda () input-port)
(lambda (port) (set! input-port port)))))
(define debugger-output-port
(let ((output-port (current-output-port)))
(make-procedure-with-setter
(lambda () output-port)
(lambda (port) (set! output-port port)))))
;;; {Debug on Error}
(define (debug-on-error syms)
"Enable or disable debug on error."
(set! default-pre-unwind-handler
(if syms
(lambda (key . args)
(if (memq key syms)
(begin
(debug-stack (make-stack #t default-pre-unwind-handler)
#:with-introduction
#:continuable)
(throw 'abort key)))
(apply default-pre-unwind-handler key args))
default-pre-unwind-handler)))
;;; Also provide a `debug-trap' entry point. This maps from a
;;; trap-context to a debug-stack call.
(define-public (debug-trap trap-context)
"Invoke the Guile debugger to explore the stack at the specified @var{trap-context}."
(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)))
(apply debug-stack stack flags)))
;;; (ice-9 debugger) ends here.

View file

@ -1,552 +0,0 @@
;;;; Guile Debugger command loop
;;; Copyright (C) 1999, 2001, 2002, 2003, 2006, 2010 Free Software Foundation, Inc.
;;;
;;;; This library is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public
;;;; License as published by the Free Software Foundation; either
;;;; version 3 of the License, or (at your option) any later version.
;;;;
;;;; This library is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;;;; Lesser General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU Lesser General Public
;;;; License along with this library; if not, write to the Free Software
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
(define-module (ice-9 debugger command-loop)
#:use-module ((ice-9 debugger commands) :prefix debugger:)
#:use-module (ice-9 debugger)
#:use-module (ice-9 debugger state)
#:use-module (ice-9 debugging traps)
#:use-module (ice-9 save-stack)
#:export (debugger-command-loop
debugger-command-loop-error
debugger-command-loop-quit)
#:no-backtrace)
;;; {Interface used by (ice-9 debugger).}
(define (debugger-command-loop state)
(read-and-dispatch-commands state (current-input-port)))
(define (debugger-command-loop-error message)
(user-error message))
(define (debugger-command-loop-quit)
(throw 'exit-debugger))
;;; {Implementation.}
(define debugger-prompt "debug> ")
(define (debugger-handler key . args)
(case key
((exit-debugger) #f)
((signal)
(apply display-error #f (current-error-port) args))
(else
(display "Internal debugger error:\n")
(save-stack debugger-handler)
(apply throw key args)))
(throw 'exit-debugger)) ;Pop the stack
(define (read-and-dispatch-commands state port)
(catch 'exit-debugger
(lambda ()
(lazy-catch #t
(lambda ()
(with-fluids ((last-command #f))
(let loop ()
(read-and-dispatch-command state port)
(loop))))
debugger-handler))
(lambda args
*unspecified*)))
(define set-readline-prompt! #f)
(define (read-and-dispatch-command state port)
(if (using-readline?)
(begin
;; Import set-readline-prompt! if we haven't already.
(or set-readline-prompt!
(set! set-readline-prompt!
(module-ref (resolve-module '(ice-9 readline))
'set-readline-prompt!)))
(set-readline-prompt! debugger-prompt debugger-prompt))
(display debugger-prompt))
(force-output) ;This should not be necessary...
(let ((token (read-token port)))
(cond ((eof-object? token)
(throw 'exit-debugger))
((not token)
(discard-rest-of-line port)
(catch-user-errors port (lambda () (run-last-command state))))
(else
(catch-user-errors port
(lambda ()
(dispatch-command token command-table state port)))))))
(define (run-last-command state)
(let ((procedure (fluid-ref last-command)))
(if procedure
(procedure state))))
(define (catch-user-errors port thunk)
(catch 'debugger-user-error
thunk
(lambda (key . objects)
(apply user-warning objects)
(discard-rest-of-line port))))
(define last-command (make-fluid))
(define (user-warning . objects)
(for-each (lambda (object)
(display object))
objects)
(newline))
(define (user-error . objects)
(apply throw 'debugger-user-error objects))
;;;; Command dispatch
(define (dispatch-command string table state port)
(let ((value (command-table-value table string)))
(if value
(dispatch-command/value value state port)
(user-error "Unknown command: " string))))
(define (dispatch-command/value value state port)
(cond ((command? value)
(dispatch-command/command value state port))
((command-table? value)
(dispatch-command/table value state port))
((list? value)
(dispatch-command/name value state port))
(else
(error "Unrecognized command-table value: " value))))
(define (dispatch-command/command command state port)
(let ((procedure (command-procedure command))
(arguments ((command-parser command) port)))
(let ((procedure (lambda (state) (apply procedure state arguments))))
(warn-about-extra-args port)
(fluid-set! last-command procedure)
(procedure state))))
(define (warn-about-extra-args port)
;; **** modify this to show the arguments.
(let ((char (skip-whitespace port)))
(cond ((eof-object? char) #f)
((char=? #\newline char) (read-char port))
(else
(user-warning "Extra arguments at end of line: "
(read-rest-of-line port))))))
(define (dispatch-command/table table state port)
(let ((token (read-token port)))
(if (or (eof-object? token)
(not token))
(user-error "Command name too short.")
(dispatch-command token table state port))))
(define (dispatch-command/name name state port)
(let ((value (lookup-command name)))
(cond ((not value)
(apply user-error "Unknown command name: " name))
((command-table? value)
(apply user-error "Partial command name: " name))
(else
(dispatch-command/value value state port)))))
;;;; Command definition
(define (define-command name argument-template procedure)
(let ((name (canonicalize-command-name name)))
(add-command name
(make-command name
(argument-template->parser argument-template)
(procedure-documentation procedure)
procedure)
command-table)
name))
(define (define-command-alias name1 name2)
(let ((name1 (canonicalize-command-name name1)))
(add-command name1 (canonicalize-command-name name2) command-table)
name1))
(define (argument-template->parser template)
;; Deliberately handles only cases that occur in "commands.scm".
(cond ((eq? 'tokens template)
(lambda (port)
(let loop ((tokens '()))
(let ((token (read-token port)))
(if (or (eof-object? token)
(not token))
(list (reverse! tokens))
(loop (cons token tokens)))))))
((null? template)
(lambda (port)
'()))
((and (pair? template)
(null? (cdr template))
(eq? 'object (car template)))
(lambda (port)
(list (read port))))
((and (pair? template)
(equal? ''optional (car template))
(pair? (cdr template))
(null? (cddr template)))
(case (cadr template)
((token)
(lambda (port)
(let ((token (read-token port)))
(if (or (eof-object? token)
(not token))
(list #f)
(list token)))))
((exact-integer)
(lambda (port)
(list (parse-optional-exact-integer port))))
((exact-nonnegative-integer)
(lambda (port)
(list (parse-optional-exact-nonnegative-integer port))))
((object)
(lambda (port)
(list (parse-optional-object port))))
(else
(error "Malformed argument template: " template))))
(else
(error "Malformed argument template: " template))))
(define (parse-optional-exact-integer port)
(let ((object (parse-optional-object port)))
(if (or (not object)
(and (integer? object)
(exact? object)))
object
(user-error "Argument not an exact integer: " object))))
(define (parse-optional-exact-nonnegative-integer port)
(let ((object (parse-optional-object port)))
(if (or (not object)
(and (integer? object)
(exact? object)
(not (negative? object))))
object
(user-error "Argument not an exact non-negative integer: " object))))
(define (parse-optional-object port)
(let ((terminator (skip-whitespace port)))
(if (or (eof-object? terminator)
(eq? #\newline terminator))
#f
(let ((object (read port)))
(if (eof-object? object)
#f
object)))))
;;;; Command tables
(define (lookup-command name)
(let loop ((table command-table) (strings name))
(let ((value (command-table-value table (car strings))))
(cond ((or (not value) (null? (cdr strings))) value)
((command-table? value) (loop value (cdr strings)))
(else #f)))))
(define (command-table-value table string)
(let ((entry (command-table-entry table string)))
(and entry
(caddr entry))))
(define (command-table-entry table string)
(let loop ((entries (command-table-entries table)))
(and (not (null? entries))
(let ((entry (car entries)))
(if (and (<= (cadr entry)
(string-length string)
(string-length (car entry)))
(= (string-length string)
(match-strings (car entry) string)))
entry
(loop (cdr entries)))))))
(define (match-strings s1 s2)
(let ((n (min (string-length s1) (string-length s2))))
(let loop ((i 0))
(cond ((= i n) i)
((char=? (string-ref s1 i) (string-ref s2 i)) (loop (+ i 1)))
(else i)))))
(define (write-command-name name)
(display (car name))
(for-each (lambda (string)
(write-char #\space)
(display string))
(cdr name)))
(define (add-command name value table)
(let loop ((strings name) (table table))
(let ((entry
(or (let loop ((entries (command-table-entries table)))
(and (not (null? entries))
(if (string=? (car strings) (caar entries))
(car entries)
(loop (cdr entries)))))
(let ((entry (list (car strings) #f #f)))
(let ((entries
(let ((entries (command-table-entries table)))
(if (or (null? entries)
(string<? (car strings) (caar entries)))
(cons entry entries)
(begin
(let loop ((prev entries) (this (cdr entries)))
(if (or (null? this)
(string<? (car strings) (caar this)))
(set-cdr! prev (cons entry this))
(loop this (cdr this))))
entries)))))
(compute-string-abbreviations! entries)
(set-command-table-entries! table entries))
entry))))
(if (null? (cdr strings))
(set-car! (cddr entry) value)
(loop (cdr strings)
(if (command-table? (caddr entry))
(caddr entry)
(let ((table (make-command-table '())))
(set-car! (cddr entry) table)
table)))))))
(define (canonicalize-command-name name)
(cond ((and (string? name)
(not (string-null? name)))
(list name))
((let loop ((name name))
(and (pair? name)
(string? (car name))
(not (string-null? (car name)))
(or (null? (cdr name))
(loop (cdr name)))))
name)
(else
(error "Illegal command name: " name))))
(define (compute-string-abbreviations! entries)
(let loop ((entries entries) (index 0))
(let ((groups '()))
(for-each
(lambda (entry)
(let* ((char (string-ref (car entry) index))
(group (assv char groups)))
(if group
(set-cdr! group (cons entry (cdr group)))
(set! groups
(cons (list char entry)
groups)))))
entries)
(for-each
(lambda (group)
(let ((index (+ index 1)))
(if (null? (cddr group))
(set-car! (cdadr group) index)
(loop (let ((entry
(let loop ((entries (cdr group)))
(and (not (null? entries))
(if (= index (string-length (caar entries)))
(car entries)
(loop (cdr entries)))))))
(if entry
(begin
(set-car! (cdr entry) index)
(delq entry (cdr group)))
(cdr group)))
index))))
groups))))
;;;; Data structures
(define command-table-rtd (make-record-type "command-table" '(entries)))
(define make-command-table (record-constructor command-table-rtd '(entries)))
(define command-table? (record-predicate command-table-rtd))
(define command-table-entries (record-accessor command-table-rtd 'entries))
(define set-command-table-entries!
(record-modifier command-table-rtd 'entries))
(define command-rtd
(make-record-type "command"
'(name parser documentation procedure)))
(define make-command
(record-constructor command-rtd
'(name parser documentation procedure)))
(define command? (record-predicate command-rtd))
(define command-name (record-accessor command-rtd 'name))
(define command-parser (record-accessor command-rtd 'parser))
(define command-documentation (record-accessor command-rtd 'documentation))
(define command-procedure (record-accessor command-rtd 'procedure))
;;;; Character parsing
(define (read-token port)
(letrec
((loop
(lambda (chars)
(let ((char (peek-char port)))
(cond ((eof-object? char)
(do-eof char chars))
((char=? #\newline char)
(do-eot chars))
((char-whitespace? char)
(do-eot chars))
((char=? #\# char)
(read-char port)
(let ((terminator (skip-comment port)))
(if (eof-object? char)
(do-eof char chars)
(do-eot chars))))
(else
(read-char port)
(loop (cons char chars)))))))
(do-eof
(lambda (eof chars)
(if (null? chars)
eof
(do-eot chars))))
(do-eot
(lambda (chars)
(if (null? chars)
#f
(list->string (reverse! chars))))))
(skip-whitespace port)
(loop '())))
(define (skip-whitespace port)
(let ((char (peek-char port)))
(cond ((or (eof-object? char)
(char=? #\newline char))
char)
((char-whitespace? char)
(read-char port)
(skip-whitespace port))
((char=? #\# char)
(read-char port)
(skip-comment port))
(else char))))
(define (skip-comment port)
(let ((char (peek-char port)))
(if (or (eof-object? char)
(char=? #\newline char))
char
(begin
(read-char port)
(skip-comment port)))))
(define (read-rest-of-line port)
(let loop ((chars '()))
(let ((char (read-char port)))
(if (or (eof-object? char)
(char=? #\newline char))
(list->string (reverse! chars))
(loop (cons char chars))))))
(define (discard-rest-of-line port)
(let loop ()
(if (not (let ((char (read-char port)))
(or (eof-object? char)
(char=? #\newline char))))
(loop))))
;;;; Commands
(define command-table (make-command-table '()))
(define-command "help" 'tokens
(lambda (state tokens)
"Type \"help\" followed by a command name for full documentation."
(let loop ((name (if (null? tokens) '("help") tokens)))
(let ((value (lookup-command name)))
(cond ((not value)
(write-command-name name)
(display " is not a known command name.")
(newline))
((command? value)
(display (command-documentation value))
(newline)
(if (equal? '("help") (command-name value))
(begin
(display "Available commands are:")
(newline)
(for-each (lambda (entry)
(if (not (list? (caddr entry)))
(begin
(display " ")
(display (car entry))
(newline))))
(command-table-entries command-table)))))
((command-table? value)
(display "The \"")
(write-command-name name)
(display "\" command requires a subcommand.")
(newline)
(display "Available subcommands are:")
(newline)
(for-each (lambda (entry)
(if (not (list? (caddr entry)))
(begin
(display " ")
(write-command-name name)
(write-char #\space)
(display (car entry))
(newline))))
(command-table-entries value)))
((list? value)
(loop value))
(else
(error "Unknown value from lookup-command:" value)))))
state))
(define-command "frame" '('optional exact-nonnegative-integer) debugger:frame)
(define-command "position" '() debugger:position)
(define-command "up" '('optional exact-integer) debugger:up)
(define-command "down" '('optional exact-integer) debugger:down)
(define-command "backtrace" '('optional exact-integer) debugger:backtrace)
(define-command "evaluate" '(object) debugger:evaluate)
(define-command '("info" "args") '() debugger:info-args)
(define-command '("info" "frame") '() debugger:info-frame)
(define-command "quit" '()
(lambda (state)
"Exit the debugger."
(debugger-command-loop-quit)))
(define-command-alias "f" "frame")
(define-command-alias '("info" "f") '("info" "frame"))
(define-command-alias "bt" "backtrace")
(define-command-alias "where" "backtrace")
(define-command-alias "p" "evaluate")
(define-command-alias '("info" "stack") "backtrace")
(define-command "continue" '() debugger:continue)
(define-command "finish" '() debugger:finish)
(define-command "step" '('optional exact-integer) debugger:step)
(define-command "next" '('optional exact-integer) debugger:next)

View file

@ -1,208 +0,0 @@
;;;; (ice-9 debugger commands) -- debugger commands
;;; Copyright (C) 2002, 2006, 2009, 2010 Free Software Foundation, Inc.
;;;
;;;; This library is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public
;;;; License as published by the Free Software Foundation; either
;;;; version 3 of the License, or (at your option) any later version.
;;;;
;;;; This library is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;;;; Lesser General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU Lesser General Public
;;;; License along with this library; if not, write to the Free Software
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
(define-module (ice-9 debugger commands)
#:use-module ((ice-9 scm-style-repl) #:select (bad-throw))
#:use-module (ice-9 debugger)
#:use-module (ice-9 debugger state)
#:use-module (ice-9 debugger utils)
#:use-module (ice-9 debugging steps)
#:export (backtrace
evaluate
info-args
info-frame
position
up
down
frame
continue
finish
step
next))
(define (backtrace state n-frames)
"Print backtrace of all stack frames, or innermost COUNT frames.
With a negative argument, print outermost -COUNT frames.
If the number of frames isn't explicitly given, the debug option
`depth' determines the maximum number of frames printed."
(let ((stack (state-stack state)))
;; Kludge around lack of call-with-values.
(let ((values
(lambda (start end)
(display-backtrace stack
(current-output-port)
(if (memq 'backwards (debug-options))
start
(- end 1))
(- end start))
)))
(let ((end (stack-length stack)))
(cond ((not n-frames) ;(>= (abs n-frames) end))
(values 0 (min end (cadr (memq 'depth (debug-options))))))
((>= n-frames 0)
(values 0 n-frames))
(else
(values (+ end n-frames) end)))))))
(define (eval-handler key . args)
(let ((stack (make-stack #t eval-handler)))
(if (= (length args) 4)
(apply display-error stack (current-error-port) args)
;; We want display-error to be the "final common pathway"
(catch #t
(lambda ()
(apply bad-throw key args))
(lambda (key . args)
(apply display-error stack (current-error-port) args)))))
(throw 'continue))
;; FIXME: no longer working due to no more local-eval
(define (evaluate state expression)
"Evaluate an expression in the environment of the selected stack frame.
The expression must appear on the same line as the command, however it
may be continued over multiple lines."
(let ((source (frame-source (stack-ref (state-stack state)
(state-index state)))))
(if (not source)
(display "No environment for this frame.\n")
(catch 'continue
(lambda ()
(lazy-catch #t
(lambda ()
(let* ((expr
;; We assume that no one will
;; really want to evaluate a
;; string (since it is
;; self-evaluating); so if we
;; have a string here, read the
;; expression to evaluate from
;; it.
(if (string? expression)
(with-input-from-string expression
read)
expression))
(env (memoized-environment source))
(value (local-eval expr env)))
(write expr)
(display " => ")
(write value)
(newline)))
eval-handler))
(lambda args args)))))
(define (info-args state)
"Display the argument variables of the current stack frame.
Arguments can also be seen in the backtrace, but are presented more
clearly by this command."
(let ((index (state-index state)))
(let ((frame (stack-ref (state-stack state) index)))
(write-frame-index-long frame)
(write-frame-args-long frame))))
(define (info-frame state)
"Display a verbose description of the selected frame. The
information that this command provides is equivalent to what can be
deduced from the one line summary for the frame that appears in a
backtrace, but is presented and explained more clearly."
(write-state-long state))
(define (position state)
"Display the name of the source file that the current expression
comes from, and the line and column number of the expression's opening
parenthesis within that file. This information is only available when
the 'positions read option is enabled."
(let* ((frame (stack-ref (state-stack state) (state-index state)))
(source (frame-source frame)))
(if (not source)
(display "No source available for this frame.")
(let ((position (source-position source)))
(if (not position)
(display "No position information available for this frame.")
(display-position position)))))
(newline))
(define (up state n)
"Move @var{n} frames up the stack. For positive @var{n}, this
advances toward the outermost frame, to lower frame numbers, to
frames that have existed longer. @var{n} defaults to one."
(set-stack-index! state (+ (state-index state) (or n 1)))
(write-state-short state))
(define (down state n)
"Move @var{n} frames down the stack. For positive @var{n}, this
advances toward the innermost frame, to higher frame numbers, to frames
that were created more recently. @var{n} defaults to one."
(set-stack-index! state (- (state-index state) (or n 1)))
(write-state-short state))
(define (frame state n)
"Select and print a stack frame.
With no argument, print the selected stack frame. (See also \"info frame\").
An argument specifies the frame to select; it must be a stack-frame number."
(if n (set-stack-index! state (frame-number->index n (state-stack state))))
(write-state-short state))
(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 (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 (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))
(continue state))
(define (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))
(continue state))
(define (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))))
(continue state))
;;; (ice-9 debugger commands) ends here.

View file

@ -1,47 +0,0 @@
;;;; (ice-9 debugger state) -- debugger state representation
;;; Copyright (C) 2002, 2006 Free Software Foundation, Inc.
;;;
;;;; This library is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public
;;;; License as published by the Free Software Foundation; either
;;;; version 3 of the License, or (at your option) any later version.
;;;;
;;;; This library is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;;;; Lesser General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU Lesser General Public
;;;; License along with this library; if not, write to the Free Software
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
(define-module (ice-9 debugger state)
#:export (make-state
state-stack
state-index
state-flags
set-stack-index!))
(define state-rtd (make-record-type "debugger-state" '(stack index flags)))
(define state? (record-predicate state-rtd))
(define make-state
(let ((make-state-internal (record-constructor state-rtd
'(stack index flags))))
(lambda (stack index . flags)
(make-state-internal stack index flags))))
(define state-stack (record-accessor state-rtd 'stack))
(define state-index (record-accessor state-rtd 'index))
(define state-flags (record-accessor state-rtd 'flags))
(define set-state-index! (record-modifier state-rtd 'index))
(define (set-stack-index! state index)
(let* ((stack (state-stack state))
(ssize (stack-length stack)))
(set-state-index! state
(cond ((< index 0) 0)
((>= index ssize) (- ssize 1))
(else index)))))
;;; (ice-9 debugger state) ends here.

View file

@ -1,63 +0,0 @@
;;;; (ice-9 debugger trc) -- tracing for Guile debugger code
;;; Copyright (C) 2002, 2006 Free Software Foundation, Inc.
;;;
;;;; This library is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public
;;;; License as published by the Free Software Foundation; either
;;;; version 3 of the License, or (at your option) any later version.
;;;;
;;;; This library is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;;;; Lesser General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU Lesser General Public
;;;; License along with this library; if not, write to the Free Software
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
(define-module (ice-9 debugger trc)
#:export (trc trc-syms trc-all trc-none trc-add trc-remove trc-port))
(define *syms* #f)
(define (trc-set! syms)
(set! *syms* syms))
(define (trc-syms . syms)
(trc-set! syms))
(define (trc-all)
(trc-set! #f))
(define (trc-none)
(trc-set! '()))
(define (trc-add sym)
(trc-set! (cons sym *syms*)))
(define (trc-remove sym)
(trc-set! (delq1! sym *syms*)))
(define (trc sym . args)
(if (or (not *syms*)
(memq sym *syms*))
(let ((port (trc-port)))
(write sym port)
(display ":" port)
(for-each (lambda (arg)
(display " " port)
(write arg port))
args)
(newline port))))
(define trc-port
(let ((port (current-error-port)))
(make-procedure-with-setter
(lambda () port)
(lambda (p) (set! port p)))))
;; Default to no tracing.
(trc-none)
;;; (ice-9 debugger trc) ends here.

View file

@ -1,203 +0,0 @@
(define-module (ice-9 debugger utils)
#:use-module (ice-9 debugger state)
#:export (display-position
source-position
write-frame-args-long
write-frame-index-long
write-frame-short/expression
write-frame-short/application
write-frame-long
write-state-long
write-state-short))
;;; Procedures in this module print information about a stack frame.
;;; The available information is as follows.
;;;
;;; * Source code location.
;;;
;;; For an evaluation frame, this is the location recorded at the time
;;; that the expression being evaluated was read, if the 'positions
;;; read option was enabled at that time.
;;;
;;; For an application frame, I'm not yet sure. Some applications
;;; seem to have associated source expressions.
;;;
;;; * Whether frame is still evaluating its arguments.
;;;
;;; Only applies to an application frame. For example, an expression
;;; like `(+ (* 2 3) 4)' goes through the following stages of
;;; evaluation.
;;;
;;; (+ (* 2 3) 4) -- evaluation
;;; [+ ... -- application; the car of the evaluation
;;; has been evaluated and found to be a
;;; procedure; before this procedure can
;;; be applied, its arguments must be evaluated
;;; [+ 6 ... -- same application after evaluating the
;;; first argument
;;; [+ 6 4] -- same application after evaluating all
;;; arguments
;;; 10 -- result
;;;
;;; * Whether frame is real or tail-recursive.
;;;
;;; If a frame is tail-recursive, its containing frame as shown by the
;;; debugger backtrace doesn't really exist as far as the Guile
;;; evaluator is concerned. The effect of this is that when a
;;; tail-recursive frame returns, it looks as though its containing
;;; frame returns at the same time. (And if the containing frame is
;;; also tail-recursive, _its_ containing frame returns at that time
;;; also, and so on ...)
;;;
;;; A `real' frame is one that is not tail-recursive.
(define (write-state-short 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)))
(define (write-state-short* stack index)
(write-frame-index-short stack index)
(write-char #\space)
(write-frame-short (stack-ref stack index))
(newline))
(define (write-frame-index-short stack index)
(let ((s (number->string (frame-number (stack-ref stack index)))))
(display s)
(write-char #\:)
(write-chars #\space (- 4 (string-length s)))))
(define (write-frame-short frame)
(if (frame-procedure? frame)
(write-frame-short/application frame)
(write-frame-short/expression frame)))
(define (write-frame-short/application frame)
(write-char #\[)
(write (let ((procedure (frame-procedure frame)))
(or (and (procedure? procedure)
(procedure-name procedure))
procedure)))
(if (frame-evaluating-args? frame)
(display " ...")
(begin
(for-each (lambda (argument)
(write-char #\space)
(write argument))
(frame-arguments frame))
(write-char #\]))))
;;; Use builtin function instead:
(set! write-frame-short/application
(lambda (frame)
(display-application frame (current-output-port) 12)))
(define (write-frame-short/expression frame)
(write (let* ((source (frame-source frame))
(copy (source-property source 'copy)))
(if (pair? copy)
copy
(unmemoize-expr source)))))
(define (write-state-long state)
(let ((index (state-index state)))
(let ((frame (stack-ref (state-stack state) index)))
(write-frame-index-long frame)
(write-frame-long frame))))
(define (write-frame-index-long frame)
(display "Stack frame: ")
(write (frame-number frame))
(if (frame-real? frame)
(display " (real)"))
(newline))
(define (write-frame-long frame)
(if (frame-procedure? frame)
(write-frame-long/application frame)
(write-frame-long/expression frame)))
(define (write-frame-long/application frame)
(display "This frame is an application.")
(newline)
(if (frame-source frame)
(begin
(display "The corresponding expression is:")
(newline)
(display-source frame)
(newline)))
(display "The procedure being applied is: ")
(write (let ((procedure (frame-procedure frame)))
(or (and (procedure? procedure)
(procedure-name procedure))
procedure)))
(newline)
(display "The procedure's arguments are")
(if (frame-evaluating-args? frame)
(display " being evaluated.")
(begin
(display ": ")
(write (frame-arguments frame))))
(newline))
(define (display-source frame)
(let* ((source (frame-source frame))
(copy (source-property source 'copy)))
(cond ((source-position source)
=> (lambda (p) (display-position p) (display ":\n"))))
(display " ")
(write (or copy (unmemoize-expr source)))))
(define (source-position source)
(let ((fname (source-property source 'filename))
(line (source-property source 'line))
(column (source-property source 'column)))
(and fname
(list fname line column))))
(define (display-position pos)
(format #t "~A:~D:~D" (car pos) (+ 1 (cadr pos)) (+ 1 (caddr pos))))
(define (write-frame-long/expression frame)
(display "This frame is an evaluation.")
(newline)
(display "The expression being evaluated is:")
(newline)
(display-source frame)
(newline))
(define (write-frame-args-long frame)
(if (frame-procedure? frame)
(let ((arguments (frame-arguments frame)))
(let ((n (length arguments)))
(display "This frame has ")
(write n)
(display " argument")
(if (not (= n 1))
(display "s"))
(write-char (if (null? arguments) #\. #\:))
(newline))
(for-each (lambda (argument)
(display " ")
(write argument)
(newline))
arguments))
(begin
(display "This frame is an evaluation frame; it has no arguments.")
(newline))))
(define (write-chars char n)
(do ((i 0 (+ i 1)))
((>= i n))
(write-char char)))

View file

@ -1,414 +0,0 @@
;;;; (ice-9 debugging breakpoints) -- practical breakpoints
;;; Copyright (C) 2005, 2010 Neil Jerram
;;;
;;;; This library is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public
;;;; License as published by the Free Software Foundation; either
;;;; version 3 of the License, or (at your option) any later version.
;;;;
;;;; This library is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;;;; Lesser General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU Lesser General Public
;;;; License along with this library; if not, write to the Free Software
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
;;; This module provides a practical interface for setting and
;;; manipulating breakpoints.
(define-module (ice-9 debugging breakpoints)
#:use-module (ice-9 debugger)
#:use-module (ice-9 ls)
#:use-module (ice-9 optargs)
#:use-module (ice-9 regex)
#:use-module (oop goops)
#:use-module (ice-9 debugging traps)
#:use-module (ice-9 debugging trc)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-13)
#:export (break-in
break-at
default-breakpoint-behaviour
delete-breakpoint
for-each-breakpoint
setup-before-load
setup-after-load
setup-after-read
setup-after-eval))
;; If the running Guile does not provide before- and after- load hooks
;; itself, install them using the (ice-9 debugging load-hooks) module.
(or (defined? 'after-load-hook)
(begin
(use-modules (ice-9 debugging load-hooks))
(install-load-hooks)))
;; Getter/setter for default breakpoint behaviour.
(define default-breakpoint-behaviour
(let ((behaviour debug-trap))
(make-procedure-with-setter
;; Getter: return current default behaviour.
(lambda ()
behaviour)
;; Setter: set default behaviour to given procedure.
(lambda (new-behaviour)
(set! behaviour new-behaviour)))))
;; Base class for breakpoints. (We don't need to use GOOPS to
;; represent breakpoints, but it's a nice way to describe a composite
;; object.)
(define-class <breakpoint> ()
;; This breakpoint's trap options, which include its behaviour.
(trap-options #:init-keyword #:trap-options)
;; All the traps relating to this breakpoint.
(traps #:init-value '())
;; Observer. This is a procedure that is called when the breakpoint
;; trap list changes.
(observer #:init-value #f))
;; Noop base class definitions of all the possible setup methods.
(define-method (setup-before-load (bp <breakpoint>) filename)
*unspecified*)
(define-method (setup-after-load (bp <breakpoint>) filename)
*unspecified*)
(define-method (setup-after-read (bp <breakpoint>) x)
*unspecified*)
(define-method (setup-after-eval (bp <breakpoint>) filename)
*unspecified*)
;; Call the breakpoint's observer, if it has one.
(define-method (call-observer (bp <breakpoint>))
(cond ((slot-ref bp 'observer)
=>
(lambda (proc)
(proc)))))
;; Delete a breakpoint.
(define (delete-breakpoint bp)
;; Remove this breakpoint from the global list.
(set! breakpoints (delq! bp breakpoints))
;; Uninstall and discard all its traps.
(for-each uninstall-trap (slot-ref bp 'traps))
(slot-set! bp 'traps '()))
;; Class for `break-in' breakpoints.
(define-class <break-in> (<breakpoint>)
;; The name of the procedure to break in.
(procedure-name #:init-keyword #:procedure-name)
;; The name of the module or file that the procedure is defined in.
;; A module name is a list of symbols that exactly names the
;; relevant module. A file name is a string, which can in fact be
;; any substring of the relevant full file name.
(module-or-file-name #:init-keyword #:module-or-file-name))
;; Class for `break-at' breakpoints.
(define-class <break-at> (<breakpoint>)
;; The name of the file to break in. This is a string, which can in
;; fact be any substring of the relevant full file name.
(file-name #:init-keyword #:file-name)
;; Line and column number to break at.
(line #:init-keyword #:line)
(column #:init-keyword #:column))
;; Global list of non-deleted breakpoints.
(define breakpoints '())
;; Add to the above list.
(define-method (add-to-global-breakpoint-list (bp <breakpoint>))
(set! breakpoints (append! breakpoints (list bp))))
;; break-in: create a `break-in' breakpoint.
(define (break-in procedure-name . options)
;; Sort out the optional args.
(let* ((module-or-file-name+options
(cond ((and (not (null? options))
(or (string? (car options))
(list? (car options))))
options)
(else
(cons (module-name (current-module)) options))))
(module-or-file-name (car module-or-file-name+options))
(trap-options (cdr module-or-file-name+options))
;; Create the new breakpoint object.
(bp (make <break-in>
#:procedure-name procedure-name
#:module-or-file-name module-or-file-name
#:trap-options (if (memq #:behaviour trap-options)
trap-options
(cons* #:behaviour
(default-breakpoint-behaviour)
trap-options)))))
;; Add it to the global breakpoint list.
(add-to-global-breakpoint-list bp)
;; Set the new breakpoint, if possible, in already loaded code.
(set-in-existing-code bp)
;; Return the breakpoint object to our caller.
bp))
;; break-at: create a `break-at' breakpoint.
(define (break-at file-name line column . trap-options)
;; Create the new breakpoint object.
(let* ((bp (make <break-at>
#:file-name file-name
#:line line
#:column column
#:trap-options (if (memq #:behaviour trap-options)
trap-options
(cons* #:behaviour
(default-breakpoint-behaviour)
trap-options)))))
;; Add it to the global breakpoint list.
(add-to-global-breakpoint-list bp)
;; Set the new breakpoint, if possible, in already loaded code.
(set-in-existing-code bp)
;; Return the breakpoint object to our caller.
bp))
;; Set a `break-in' breakpoint in already loaded code, if possible.
(define-method (set-in-existing-code (bp <break-in>))
;; Get the module or file name that was specified for this
;; breakpoint.
(let ((module-or-file-name (slot-ref bp 'module-or-file-name)))
;; Handling is simpler for a module name.
(cond ((list? module-or-file-name)
;; See if the named module exists yet.
(let ((m (module-if-already-loaded module-or-file-name)))
(maybe-break-in-module-proc m bp)))
((string? module-or-file-name)
;; Try all loaded modules.
(or-map (lambda (m)
(maybe-break-in-module-proc m bp))
(all-loaded-modules)))
(else
(error "Bad module-or-file-name:" module-or-file-name)))))
(define (make-observer bp trap)
(lambda (event)
(trap-target-gone bp trap)))
;; Set a `break-at' breakpoint in already loaded code, if possible.
(define-method (set-in-existing-code (bp <break-at>) . code)
;; Procedure to install a source trap on each expression that we
;; find matching this breakpoint.
(define (install-source-trap x)
(or (or-map (lambda (trap)
(and (is-a? trap <source-trap>)
(eq? (slot-ref trap 'expression) x)))
(slot-ref bp 'traps))
(let ((trap (apply make <source-trap>
#:expression x
(slot-ref bp 'trap-options))))
(slot-set! trap 'observer (make-observer bp trap))
(install-trap trap)
(trc 'install-source-trap (object-address trap) (object-address x))
(trap-installed bp trap #t))))
;; Scan the source whash, and install a trap on all code matching
;; this breakpoint.
(trc 'set-in-existing-code (length code))
(if (null? code)
(scan-source-whash (slot-ref bp 'file-name)
(slot-ref bp 'line)
(slot-ref bp 'column)
install-source-trap)
(scan-code (car code)
(slot-ref bp 'file-name)
(slot-ref bp 'line)
(slot-ref bp 'column)
install-source-trap)))
;; Temporary implementation of scan-source-whash - this _really_ needs
;; to be implemented in C.
(define (scan-source-whash file-name line column proc)
;; Procedure to call for each source expression in the whash.
(define (folder x props acc)
(if (and (= line (source-property x 'line))
(= column (source-property x 'column))
(let ((fn (source-property x 'filename)))
(trc 'scan-source-whash fn)
(and (string? fn)
(string-contains fn file-name))))
(proc x)))
;; Tracing.
(trc 'scan-source-whash file-name line column)
;; Apply this procedure to the whash.
(hash-fold folder 0 source-whash))
(define (scan-code x file-name line column proc)
(trc 'scan-code file-name line column)
(if (pair? x)
(begin
(if (and (eq? line (source-property x 'line))
(eq? column (source-property x 'column))
(let ((fn (source-property x 'filename)))
(trc 'scan-code fn)
(and (string? fn)
(string-contains fn file-name))))
(proc x))
(scan-code (car x) file-name line column proc)
(scan-code (cdr x) file-name line column proc))))
;; If a module named MODULE-NAME has been loaded, return its module
;; object; otherwise return #f.
(define (module-if-already-loaded module-name)
(nested-ref the-root-module (append '(%app modules) module-name)))
;; Construct and return a list of all loaded modules.
(define (all-loaded-modules)
;; This is the list that accumulates known modules. It has to be
;; defined outside the following functions, and accumulated using
;; set!, so as to avoid infinite loops - because of the fact that
;; all non-pure modules have a variable `app'.
(define known-modules '())
;; Return an alist of submodules of the given PARENT-MODULE-NAME.
;; Each element of the alist is (NAME . MODULE), where NAME is the
;; module's leaf name (i.e. relative to PARENT-MODULE-NAME) and
;; MODULE is the module object. By a "submodule of a parent
;; module", we mean any module value that is bound to a symbol in
;; the parent module, and which is not an interface module.
(define (direct-submodules parent-module-name)
(filter (lambda (name+value)
(and (module? (cdr name+value))
(not (eq? (module-kind (cdr name+value)) 'interface))))
(map (lambda (name)
(cons name (local-ref (append parent-module-name
(list name)))))
(cdar (lls parent-module-name)))))
;; Add all submodules (direct and indirect) of the module named
;; PARENT-MODULE-NAME to `known-modules', if not already there.
(define (add-submodules-of parent-module-name)
(let ((ds (direct-submodules parent-module-name)))
(for-each
(lambda (name+module)
(or (memq (cdr name+module) known-modules)
(begin
(set! known-modules (cons (cdr name+module) known-modules))
(add-submodules-of (append parent-module-name
(list (car name+module)))))))
ds)))
;; Add submodules recursively, starting from the root of all
;; modules.
(add-submodules-of '(%app modules))
;; Return the result.
known-modules)
;; Before-load setup for `break-at' breakpoints.
(define-method (setup-before-load (bp <break-at>) filename)
(let ((trap (apply make <location-trap>
#:file-regexp (regexp-quote (slot-ref bp 'file-name))
#:line (slot-ref bp 'line)
#:column (slot-ref bp 'column)
(slot-ref bp 'trap-options))))
(install-trap trap)
(trap-installed bp trap #f)
(letrec ((uninstaller
(lambda (file-name)
(uninstall-trap trap)
(remove-hook! after-load-hook uninstaller))))
(add-hook! after-load-hook uninstaller))))
;; After-load setup for `break-in' breakpoints.
(define-method (setup-after-load (bp <break-in>) filename)
;; Get the module that the loaded file created or was loaded into,
;; and the module or file name that were specified for this
;; breakpoint.
(let ((m (current-module))
(module-or-file-name (slot-ref bp 'module-or-file-name)))
;; Decide whether the breakpoint spec matches this load.
(if (or (and (string? module-or-file-name)
(string-contains filename module-or-file-name))
(and (list? module-or-file-name)
(equal? (module-name (current-module)) module-or-file-name)))
;; It does, so try to install the breakpoint.
(maybe-break-in-module-proc m bp))))
;; After-load setup for `break-at' breakpoints.
(define-method (setup-after-load (bp <break-at>) filename)
(if (string-contains filename (slot-ref bp 'file-name))
(set-in-existing-code bp)))
(define (maybe-break-in-module-proc m bp)
"If module M defines a procedure matching the specification of
breakpoint BP, install a trap on it."
(let ((proc (module-ref m (slot-ref bp 'procedure-name) #f)))
(if (and proc
(procedure? proc)
(let ((module-or-file-name (slot-ref bp 'module-or-file-name)))
(if (string? module-or-file-name)
(source-file-matches (procedure-source proc)
module-or-file-name)
#t))
(not (or-map (lambda (trap)
(and (is-a? trap <procedure-trap>)
(eq? (slot-ref trap 'procedure) proc)))
(slot-ref bp 'traps))))
;; There is, so install a <procedure-trap> on it.
(letrec ((trap (apply make <procedure-trap>
#:procedure proc
(slot-ref bp 'trap-options))))
(slot-set! trap 'observer (make-observer bp trap))
(install-trap trap)
(trap-installed bp trap #t)
;; Tell caller that we installed a trap.
#t)
;; Tell caller that we did not install a trap.
#f)))
;; After-read setup for `break-at' breakpoints.
(define-method (setup-after-read (bp <break-at>) x)
(set-in-existing-code bp x))
;; Common code for associating a newly created and installed trap with
;; a breakpoint object.
(define (trap-installed bp trap record?)
(if record?
;; Remember this trap in the breakpoint object.
(slot-set! bp 'traps (append! (slot-ref bp 'traps) (list trap))))
;; Update the breakpoint status.
(call-observer bp))
;; Common code for handling when the target of one of a breakpoint's
;; traps is being GC'd.
(define (trap-target-gone bp trap)
(trc 'trap-target-gone (object-address trap))
;; Remove this trap from the breakpoint's list.
(slot-set! bp 'traps (delq! trap (slot-ref bp 'traps)))
;; Update the breakpoint status.
(call-observer bp))
(define (source-file-matches source file-name)
"Return #t if any of the expressions in SOURCE have a 'filename
source property that includes FILE-NAME; otherwise return #f."
(and (pair? source)
(or (let ((source-file-name (source-property source 'filename)))
(and source-file-name
(string? source-file-name)
(string-contains source-file-name file-name)))
(let loop ((source source))
(and (pair? source)
(or (source-file-matches (car source) file-name)
(loop (cdr source))))))))
;; Install load hook functions.
(add-hook! before-load-hook
(lambda (fn)
(for-each-breakpoint setup-before-load fn)))
(add-hook! after-load-hook
(lambda (fn)
(for-each-breakpoint setup-after-load fn)))
;;; Apply generic function GF to each breakpoint, passing the
;;; breakpoint object and ARGS as args on each call.
(define (for-each-breakpoint gf . args)
(for-each (lambda (bp)
(apply gf bp args))
breakpoints))
;; Make sure that recording of source positions is enabled. Without
;; this break-at breakpoints will obviously not work.
(read-enable 'positions)
;;; (ice-9 debugging breakpoints) ends here.

View file

@ -1,17 +0,0 @@
(define-module (ice-9 debugging example-fns)
#:export (fact1 fact2 facti))
(define (fact1 n)
(if (= n 0)
1
(* n (fact1 (- n 1)))))
(define (facti n a)
(if (= n 0)
a
(facti (- n 1) (* a n))))
(define (fact2 n)
(facti n 1))
; Test: (fact2 3)

View file

@ -1,33 +0,0 @@
(define-module (ice-9 debugging load-hooks)
#:export (before-load-hook
after-load-hook
install-load-hooks
uninstall-load-hooks))
;; real-primitive-load: holds the real (C-implemented) definition of
;; primitive-load, when the load hooks are installed.
(define real-primitive-load #f)
;; The load hooks themselves. These are called with one argument, the
;; name of the file concerned.
(define before-load-hook (make-hook 1))
(define after-load-hook (make-hook 1))
;; primitive-load-with-hooks: our new definition for primitive-load.
(define (primitive-load-with-hooks filename)
(run-hook before-load-hook filename)
(real-primitive-load filename)
(run-hook after-load-hook filename))
(define (install-load-hooks)
(if real-primitive-load
(error "load hooks are already installed"))
(set! real-primitive-load primitive-load)
(set! primitive-load primitive-load-with-hooks))
(define (uninstall-load-hooks)
(or real-primitive-load
(error "load hooks are not installed"))
(set! primitive-load real-primitive-load)
(set! real-primitive-load #f))

View file

@ -1,106 +0,0 @@
;;;; (ice-9 debugging steps) -- stepping through code from the debugger
;;; Copyright (C) 2002, 2004 Free Software Foundation, Inc.
;;;
;;;; This library is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public
;;;; License as published by the Free Software Foundation; either
;;;; version 3 of the License, or (at your option) any later version.
;;;;
;;;; This library is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;;;; Lesser General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU Lesser General Public
;;;; License along with this library; if not, write to the Free Software
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
(define-module (ice-9 debugging steps)
#:use-module (ice-9 debugging traps)
#:use-module (ice-9 and-let-star)
#:use-module (ice-9 debugger)
#:use-module (ice-9 optargs)
#:export (at-exit
at-entry
at-apply
at-step
at-next))
;;; at-exit DEPTH BEHAVIOUR
;;;
;;; Install a behaviour to run when we exit the current frame.
(define (at-exit depth behaviour)
(install-trap (make <exit-trap>
#:depth depth
#:single-shot #t
#:behaviour behaviour)))
;;; at-entry BEHAVIOUR [COUNT]
;;;
;;; Install a behaviour to run when we get to the COUNT'th next frame
;;; entry. COUNT defaults to 1.
(define* (at-entry behaviour #:optional (count 1))
(install-trap (make <entry-trap>
#:skip-count (- count 1)
#:single-shot #t
#:behaviour behaviour)))
;;; at-apply BEHAVIOUR [COUNT]
;;;
;;; Install a behaviour to run when we get to the COUNT'th next
;;; application. COUNT defaults to 1.
(define* (at-apply behaviour #:optional (count 1))
(install-trap (make <apply-trap>
#:skip-count (- count 1)
#:single-shot #t
#:behaviour behaviour)))
;;; at-step BEHAVIOUR [COUNT [FILENAME [DEPTH]]
;;;
;;; Install BEHAVIOUR to run on the COUNT'th next application, frame
;;; entry or frame exit. COUNT defaults to 1. If FILENAME is
;;; specified and not #f, only frames that begin in the named file are
;;; counted.
(define* (at-step behaviour #:optional (count 1) filename (depth 1000))
(install-trap (make <step-trap>
#:file-name filename
#:exit-depth depth
#:skip-count (- count 1)
#:single-shot #t
#:behaviour behaviour)))
;; (or count (set! count 1))
;; (letrec ((proc (lambda (trap-context)
;; ;; Behaviour whenever we enter or exit a frame.
;; (set! count (- count 1))
;; (if (= count 0)
;; (begin
;; (remove-enter-frame-hook! step)
;; (remove-apply-frame-hook! step)
;; (behaviour trap-context)))))
;; (step (lambda (trap-context)
;; ;; Behaviour on frame entry: both execute the above
;; ;; and install it as an exit hook.
;; (if (or (not filename)
;; (equal? (frame-file-name (tc:frame trap-context))
;; filename))
;; (begin
;; (proc trap-context)
;; (at-exit (tc:depth trap-context) proc))))))
;; (at-exit depth proc)
;; (add-enter-frame-hook! step)
;; (add-apply-frame-hook! step)))
;;; at-next BEHAVIOUR [COUNT]
;;;
;;; Install a behaviour to run when we get to the COUNT'th next frame
;;; entry in the same source file as the current location. COUNT
;;; defaults to 1. If the current location has no filename, fall back
;;; silently to `at-entry' behaviour.
;;; (ice-9 debugging steps) ends here.

View file

@ -1,153 +0,0 @@
;;;; (ice-9 debugging trace) -- breakpoint trace behaviour
;;; Copyright (C) 2002, 2010 Free Software Foundation, Inc.
;;;
;;;; This library is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public
;;;; License as published by the Free Software Foundation; either
;;;; version 3 of the License, or (at your option) any later version.
;;;;
;;;; This library is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;;;; Lesser General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU Lesser General Public
;;;; License along with this library; if not, write to the Free Software
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
(define-module (ice-9 debugging trace)
#:use-module (ice-9 debugger)
#:use-module (ice-9 debugger utils)
#:use-module (ice-9 debugging steps)
#:use-module (ice-9 debugging traps)
#:export (trace-trap
trace-port
set-trace-layout
trace/pid
trace/stack-id
trace/stack-depth
trace/stack-real-depth
trace/stack
trace/source-file-name
trace/source-line
trace/source-column
trace/source
trace/type
trace/real?
trace/info
trace-at-exit
trace-until-exit))
(define trace-format-string #f)
(define trace-arg-procs #f)
(define (set-trace-layout format-string . arg-procs)
(set! trace-format-string format-string)
(set! trace-arg-procs arg-procs))
(define (trace/pid trap-context)
(getpid))
(define (trace/stack-id trap-context)
(stack-id (tc:stack trap-context)))
(define (trace/stack-depth trap-context)
(tc:depth trap-context))
(define (trace/stack-real-depth trap-context)
(tc:real-depth trap-context))
(define (trace/stack trap-context)
(format #f "~a:~a+~a"
(stack-id (tc:stack trap-context))
(tc:real-depth trap-context)
(- (tc:depth trap-context) (tc:real-depth trap-context))))
(define (trace/source-file-name trap-context)
(cond ((frame->source-position (tc:frame trap-context)) => car)
(else "")))
(define (trace/source-line trap-context)
(cond ((frame->source-position (tc:frame trap-context)) => cadr)
(else 0)))
(define (trace/source-column trap-context)
(cond ((frame->source-position (tc:frame trap-context)) => caddr)
(else 0)))
(define (trace/source trap-context)
(cond ((frame->source-position (tc:frame trap-context))
=>
(lambda (pos)
(format #f "~a:~a:~a" (car pos) (cadr pos) (caddr pos))))
(else "")))
(define (trace/type trap-context)
(case (tc:type trap-context)
((#:application) "APP")
((#:evaluation) "EVA")
((#:return) "RET")
((#:error) "ERR")
(else "???")))
(define (trace/real? trap-context)
(if (frame-real? (tc:frame trap-context)) " " "t"))
(define (trace/info trap-context)
(with-output-to-string
(lambda ()
(if (memq (tc:type trap-context) '(#:application #:evaluation))
((if (tc:expression trap-context)
write-frame-short/expression
write-frame-short/application) (tc:frame trap-context))
(begin
(display "=>")
(write (tc:return-value trap-context)))))))
(set-trace-layout "|~3@a: ~a\n" trace/stack-real-depth trace/info)
;;; trace-trap
;;;
;;; Trace the current location, and install a hook to trace the return
;;; value when we exit the current frame.
(define (trace-trap trap-context)
(apply format
(trace-port)
trace-format-string
(map (lambda (arg-proc)
(arg-proc trap-context))
trace-arg-procs)))
(set! (behaviour-ordering trace-trap) 50)
;;; trace-port
;;;
;;; The port to which trace information is printed.
(define trace-port
(let ((port (current-output-port)))
(make-procedure-with-setter
(lambda () port)
(lambda (new) (set! port new)))))
;;; trace-at-exit
;;;
;;; Trace return value on exit from the current frame.
(define (trace-at-exit trap-context)
(at-exit (tc:depth trap-context) trace-trap))
;;; trace-until-exit
;;;
;;; Trace absolutely everything until exit from the current frame.
(define (trace-until-exit trap-context)
(let ((step-trap (make <step-trap> #:behaviour trace-trap)))
(install-trap step-trap)
(at-exit (tc:depth trap-context)
(lambda (trap-context)
(uninstall-trap step-trap)))))
;;; (ice-9 debugging trace) ends here.

File diff suppressed because it is too large Load diff

View file

@ -1,63 +0,0 @@
;;;; (ice-9 debugging trc) -- tracing for Guile debugger code
;;; Copyright (C) 2002, 2004 Free Software Foundation, Inc.
;;;
;;;; This library is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public
;;;; License as published by the Free Software Foundation; either
;;;; version 3 of the License, or (at your option) any later version.
;;;;
;;;; This library is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;;;; Lesser General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU Lesser General Public
;;;; License along with this library; if not, write to the Free Software
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
(define-module (ice-9 debugging trc)
#:export (trc trc-syms trc-all trc-none trc-add trc-remove trc-port))
(define *syms* #f)
(define (trc-set! syms)
(set! *syms* syms))
(define (trc-syms . syms)
(trc-set! syms))
(define (trc-all)
(trc-set! #f))
(define (trc-none)
(trc-set! '()))
(define (trc-add sym)
(trc-set! (cons sym *syms*)))
(define (trc-remove sym)
(trc-set! (delq1! sym *syms*)))
(define (trc sym . args)
(if (or (not *syms*)
(memq sym *syms*))
(let ((port (trc-port)))
(write sym port)
(display ":" port)
(for-each (lambda (arg)
(display " " port)
(write arg port))
args)
(newline port))))
(define trc-port
(let ((port (current-error-port)))
(make-procedure-with-setter
(lambda () port)
(lambda (p) (set! port p)))))
;; Default to no tracing.
(trc-none)
;;; (ice-9 debugging trc) ends here.