]> git.donarmstrong.com Git - lilypond.git/blobdiff - guile18/ice-9/debugger.scm
Import guile-1.8 as multiple upstream tarball component
[lilypond.git] / guile18 / ice-9 / debugger.scm
diff --git a/guile18/ice-9/debugger.scm b/guile18/ice-9/debugger.scm
new file mode 100644 (file)
index 0000000..0ad0148
--- /dev/null
@@ -0,0 +1,146 @@
+;;;; Guile Debugger
+
+;;; Copyright (C) 1999, 2001, 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 2.1 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 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! lazy-handler-dispatch
+       (if syms
+           (lambda (key . args)
+             (if (memq key syms)
+                 (begin
+                   (debug-stack (make-stack #t lazy-handler-dispatch)
+                                #:with-introduction
+                                #:continuable)
+                   (throw 'abort key)))
+             (apply default-lazy-handler key args))
+           default-lazy-handler)))
+
+;;; (ice-9 debugger) ends here.