[PATCH] Make Guile Debugger less flaky.

[ Thread Index | Date Index | More lilynet.net/frogs Archives ]


Move break-point and trace routines to a separate .scm file.

Update Debugging Chapter in CG.
---
 Documentation/contributor/programming-work.itexi |  504 +++++++---------=
------
 ly/guile-debugger.ly                             |   49 +--
 scm/guile-debugger.scm                           |   59 +++
 scm/lily.scm                                     |   22 +-
 4 files changed, 245 insertions(+), 389 deletions(-)
 create mode 100755 scm/guile-debugger.scm

diff --git a/Documentation/contributor/programming-work.itexi b/Documenta=
tion/contributor/programming-work.itexi
index 17e4bc9..a161b47 100644
--- a/Documentation/contributor/programming-work.itexi
+++ b/Documentation/contributor/programming-work.itexi
@@ -14,7 +14,6 @@
 * Engraver tutorial::
 * Callback tutorial::
 * LilyPond scoping::
-* LilyPond miscellany::
 @end menu
=20
 @node Overview of LilyPond architecture
@@ -28,6 +27,7 @@ execution is found in Erik Sandberg's
 @uref{http://lilypond.org/web/images/thesis-erik-sandberg.pdf, master's
 thesis}.
=20
+
 The first stage of LilyPond processing is @emph{parsing}.  In the parsin=
g
 process, music expressions in LilyPond input format are converted to mus=
ic
 expressions in Scheme format.  In Scheme format, a music expression is a=
 list
@@ -656,7 +656,10 @@ Do not run make po/po-update with GNU gettext < 0.10=
..35
 @section Debugging LilyPond
=20
 The most commonly used tool for debugging LilyPond is the GNU debugger
-gdb.  Use of gdb is described in this section.
+gdb.
+The gdb tool is used for investigating and debugging core Lilypond code =
written in C++.
+Another tool is available for debugging Scheme code using the Guile debu=
gger,
+This section describes using both gdb and the Guile Debugger.
=20
 @subsection Debugging overview
=20
@@ -671,9 +674,9 @@ the sequence in which functions are called and the ar=
guments to the
 various function calls.
=20
=20
-@subsection Compiling with debugging information
+@subsection Compiling LilyPond for use with gdb
=20
-In order to use a debugger with LilyPond, it is necessary to compile
+In order to use gdb with LilyPond, it is necessary to compile
 LilyPond with debugging information.  This is accomplished by running
 the following commands in the main LilyPond source directory.
=20
@@ -683,51 +686,40 @@ the following commands in the main LilyPond source =
directory.
 make
 @end example
=20
-This will create a version of LilyPond that contains the debugging
+This will create a version of LilyPond containing debugging
 information that will allow the debugger to tie the source code
 to the compiled code.
=20
 You should not do @var{make install} if you want to use a debugger
-with LilyPond.  @var{make install} will strip the debugging information
+with LilyPond.  The @var{make install} command will strip debugging info=
rmation
 from the LilyPond binary.
=20
-To set breakpoints in Scheme functions, put
-
-@example
-\include "guile-debugger.ly"
-@end example
+@subsection Typical gdb usage
=20
-in your input file after any scheme procedures you have defined in
-that file.  When your input file is processed, a guile prompt
-will be displayed.  At the guile prompt, you can set breakpoints with
-the @code{break!} procedure:
+Once you have compiled the Lilypond image with the necessary debugging i=
nformation it will=20
+have been written to a location in a subfolder of your current working d=
irectory:
=20
 @example
-guile> (break! my-scheme-procedure)
+out/bin/lilypond
 @end example
=20
-Once you have set the desired breakpoints, you exit the guile repl frame
-by typing:
-
+This is important as you will need to let gdb know where to find the ima=
ge.=20
+You can invoke gdb from the command line using
 @example
-guile> (quit)
+$ gdb out/bin/lilypond
 @end example
-
-When one of the scheme routines for which you have set breakpoints is
-entered, guile will interrupt execution in a debug frame.  At this point=
,
-you will have access to guile debugging commands.  For a listing of thes=
e
-commands, type:
-
+or you may use a graphical interface to gdb such as ddd
 @example
-debug> help
+$ ddd out/bin/lilypond
 @end example
+You can also use sets of standard gdb commands stored in a .gdbinit file=
 (see next=20
+section).
=20
-@subsection Typical gdb usage
-
+=20
 @subsection Typical .gdbinit files
=20
-The behavior of gdb can be readily customized through the use of
-@var{.gdbinit} files.  A @var{.gdbinit} file is a file named
+The behavior of gdb can be readily customized through the use of a
+@var{.gdbinit} file.  A @var{.gdbinit} file is a file named
 @var{.gdbinit} (notice the @qq{.} at the beginning of the file name)
 that is placed in a user's home directory.
=20
@@ -756,10 +748,16 @@ define pmusic
 end
 @end example
=20
+@subsection Debugging Scheme Code
+Scheme code can be developed using the Guile command line interpreter @c=
ode{top-repl}.
+You can either investigate interactively using just Guile or you can use=
 the debugging=20
+tools available within Guile.
+
+
 @subsection Using Guile interactively with LilyPond
=20
 In order to experiment with Scheme programming in the LilyPond
-environment, it is convenient to have a Guile interpreter that
+environment, it is necessary to have a Guile interpreter that
 has all the LilyPond modules loaded.  This requires the following
 steps.
=20
@@ -771,7 +769,7 @@ in the .ly file:
                  'lilypond-module (current-module))
 @end example
=20
-Second, place a Scheme function in the .ly file that gives an interactiv=
e Guile
+Now, place a Scheme function in the .ly file that gives an interactive G=
uile
 prompt:
=20
 @example
@@ -779,15 +777,15 @@ prompt:
 @end example
=20
 When the .ly file is compiled, this causes the compilation to be interru=
pted
-and an interactive guile prompt to appear.  When the guile prompt appear=
s,
+and an interactive guile prompt to appear.  Once the guile prompt appear=
s,
 the LilyPond active module must be set as the current guile module:
=20
 @example
 guile> (set-current-module lilypond-module)
 @end example
=20
-Proper operation of these commands can be demonstrated by typing the nam=
e
-of a LilyPond public scheme function to see if it's properly defined:
+You can demonstrate these commands are operating properly by typing the =
name
+of a LilyPond public scheme function to check it has been define:
=20
 @example
 guile> fret-diagram-verbose-markup
@@ -815,6 +813,106 @@ guile> (quit)
=20
 The compilation of the .ly file will then continue.
=20
+@subsection Using the Guile debugger
+
+To set breakpoints and/or enable tracing in Scheme functions, put
+
+@example
+\include "guile-debugger.ly"
+@end example
+
+in your input file after any scheme procedures you have defined in
+that file. =20
+This will invoke the Guile command-line and have set up the environment =
for the debug=20
+command lines.
+When your input file is processed, a guile prompt will be displayed. =20
+You may now enter commands to set up breakpoints and enable tracing by t=
he Guile debugger.
+
+@subsection Using Breakpoints
+
+At the guile prompt, you can set breakpoints with
+the @code{set-break!} procedure:
+
+@example
+guile> (set-break! my-scheme-procedure)
+@end example
+
+Once you have set the desired breakpoints, you exit the guile repl frame
+by typing:
+
+@example
+guile> (quit)
+@end example
+
+When one of the scheme routines for which you have set breakpoints is
+entered, guile will interrupt execution in a debug frame.  At this point=
,
+you will have access to guile debugging commands.  For a listing of thes=
e
+commands, type:
+
+@example
+debug> help
+@end example
+
+Alternatively you may code the breakpoints in your Lilypond source file =
using a command=20
+such as:
+@example
+#(set-break! my-scheme-procedure)
+@end example
+immediately after the @code{\include} statement.  In this case the break=
point will be set=20
+straight after you enter the @code{(quit)} command at the guile prompt.
+
+Embedding breakpoint commands like this is particularly useful if you wa=
nt to look at how=20
+the Scheme procedures in the @var{.scm} files supplied with LilyPond wor=
k.
+
+In this case you can edit the file in the relevant directory to add this=
 line near the top:
+
+@example
+(use-modules (scm guile-debugger)
+@end example
+Now you can set a breakpoint after the procedure you are interested in h=
as been declared.
+For example if you are working on routines called by @var{print-book-wit=
h} in=20
+@var{lily-library.scm}:
+
+@example
+(define (print-book-with parser book process-procedure)
+  (let* ((paper (ly:parser-lookup parser '$defaultpaper))
+	 (layout (ly:parser-lookup parser '$defaultlayout))
+	 (outfile-name (get-outfile-name parser)))
+    (process-procedure book paper layout outfile-name)))
+
+(define-public (print-book-with-defaults parser book)
+  (print-book-with parser book ly:book-process))
+
+(define-public (print-book-with-defaults-as-systems parser book)
+  (print-book-with parser book ly:book-process-to-systems))
+
+@end example
+
+At this point in the code you could add this to set a breakpoint at prin=
t-book-with:
+
+@example
+
+(set-break print-book-with)
+
+@end example
+
+@strong{Tracing}
+
+In the above example you will note that trace-points have also been set.=
  There are two=20
+forms of trace available:
+
+@example
+(set-trace! my-scheme-procedure)
+@end example
+and
+@example
+(set-trace-subtree! my-scheme-procedure)
+@end example
+
+@code{set-trace!} allows Scheme to log a line to the standard output to =
show when the
+procedure is called and when it exits.  @code{set-trace-subtree!} traces=
 each line in the
+body of the procedure as it is executed.
+
 @node Adding or modifying features
 @section Adding or modifying features
=20
@@ -1059,8 +1157,7 @@ to the left of the issue name.
=20
 If the changes were in response to a feature request on the Google
 issue tracker for LilyPond, the author should change the status to
-Fixed and a tag @q{fixed_x_y_z} should be added, where the patch was
-fixed in version x.y.z.  If
+@q{Fixed_x_y_z} where the patch was fixed in version x.y.z.  If
 the author does not have privileges to change the status, an email
 should be sent to bug-lilypond requesting the BugMeister to change
 the status.
@@ -1251,330 +1348,37 @@ foo =3D 1
 @end example
=20
 @noindent with @code{\paper}, @code{\midi} and @code{\header} being
-nested scope inside the @file{.ly} file-level scope.  @w{@code{foo =3D 1=
}}
-is translated in to a scheme variable definition.
+nested scope inside the .ly file-level scope.  @w{@code{foo =3D 1}} is
+translated in to a scheme variable definition.
=20
 This implemented using modules, with each scope being an anonymous
 module that imports its enclosing scope's module.
=20
-Lilypond's core, loaded from @file{.scm} files, is usually placed in the
-@code{lily} module, outside the @file{.ly} level.  In the case of
+The reason to put some functions (@qq{builtin}) outside the .ly level,
+is that in case of
=20
 @example
 lilypond a.ly b.ly
 @end example
=20
 @noindent
-we want to reuse the built-in definitions, without changes effected in
-user-level @file{a.ly} leaking into the processing of @file{b.ly}.
-
-The user-accessible definition commands have to take care to avoid
-memory leaks that could occur when running multiple files.  All
-information belonging to user-defined commands and markups is stored in
-a manner that allows it to be garbage-collected when the module is
-dispersed, either by being stored module-locally, or in weak hash
-tables.
-
-@node LilyPond miscellany
-@section LilyPond miscellany
-
-This is a place to dump information that may be of use to developers
-but doesn't yet have a proper home.  Ideally, the length of this section
-would become zero as items are moved to other homes.
-
-@subsection Info from Han-Wen Email
-
-In 2004, Douglas Linhardt decided to try starting a document that would
-explain LilyPond architecture and design principles.  The material below
-is extracted from that email, which can be found at
-@uref{http://thread.gmane.org/gmane.comp.gnu.lilypond.devel/2992}.
-The headings reflect questions from Doug or comments from Han-Wen;
-the body text are Han-Wen's answers.
-
-@unnumberedsubsubsec Figuring out how things work.
-
-I must admit that when I want to know how a program works, I use grep
-and emacs and dive into the source code. The comments and the code
-itself are usually more revealing than technical documents.
-
-@unnumberedsubsubsec What's a grob, and how is one used?
-
-Graphical object - they are created from within engravers, either as
-Spanners (derived class) -slurs, beams- or Items (also a derived
-class) -notes, clefs, etc.
-
-There are two other derived classes System (derived from Spanner,
-contaning a "line of music") and Paper_column (derived from Item, it
-contains all items that happen at the same moment). They are separate
-classes because they play a special role in the linebreaking process.
-
-@unnumberedsubsubsec What's a smob, and how is one used?
-
-A C(++) object that is encapsulated so it can be used as a Scheme
-object.  See GUILE info, "19.3 Defining New Types (Smobs)"
-
-@unnumberedsubsubsec When is each C++ class constructed and used
-
-@itemize
-
-@item
-Music classes
-
-In the parser.yy see the macro calls MAKE_MUSIC_BY_NAME().
-
-@item
-Contexts
-
-Constructed during "interpreting" phase.
-
-@item
-Engravers
-
-Executive branch of Contexts, plugins that create grobs, usually one
-engraver per grob type. Created  together with context.
-
-@item
-Layout Objects
-
-=3D grobs
-
-@item
-Grob Interfaces
-
-These are not C++ classes per se. The idea of a Grob interface hasn't
-crystallized well. ATM, an interface is a symbol, with a bunch of grob
-properties. They are not objects that are created or destroyed.
-
-@item
-Iterators
-
-Objects that walk through different music classes, and deliver events
-in a synchronized way, so that notes that play together are processed
-at the same moment and (as a result) end up on the same horizontal posit=
ion.
-
-Created during interpreting phase.
-
-BTW, the entry point for interpreting is ly:run-translator
-(ly_run_translator on the C++ side)
-
-@end itemize
-
-@unnumberedsubsubsec Can you get to Context properties from a Music obje=
ct?
-
-You can create music object with a Scheme function that reads context
-properties (the \applycontext syntax). However, that function is
-executed during Interpreting, so you can not really get Context
-properties from Music objects, since music objects are not directly
-connected to Contexts. That connection is made by the  Music_iterators
-
-@unnumberedsubsubsec Can you get to Music properties from a Context obje=
ct?
-
-Yes, if you are given the music object within a Context
-object. Normally, the music objects enter Contexts in synchronized
-fashion, and the synchronization is done by Music_iterators.
-
-@unnumberedsubsubsec What is the relationship between C++ classes and Sc=
heme objects?
-
-Smobs are C++ objects in Scheme. Scheme objects (lists, functions) are
-manipulated from C++ as well using the GUILE C function interface
-(prefix: scm_)
-
-@unnumberedsubsubsec How do Scheme procedures get called from C++ functi=
ons?
-
-scm_call_*, where * is an integer from 0 to 4.
-Also scm_c_eval_string (), scm_eval ()
-
-@unnumberedsubsubsec How do C++ functions get called from Scheme procedu=
res?
-
-Export a C++ function to Scheme with LY_DEFINE.
-
-@unnumberedsubsubsec What is the flow of control in the program?
-
-Good question.  Things used to be clear-cut, but we have Scheme
-and SMOBs now, which means that interactions do not follow a very
-rigid format anymore. See below for an overview, though.
-
-@unnumberedsubsubsec Does the parser make Scheme procedure calls or C++ =
function calls?
-
-Both. And the Scheme calls can call C++ and vice versa. It's nested,
-with the SCM datatype as lubrication between the interactions
-
-(I think the word "lubrication" describes the process better than the
-traditional word "glue")
-
-@unnumberedsubsubsec How do the front-end and back-end get started?
-
-Front-end: a file is parsed, the rest follows from that. Specifically,
-
-Parsing leads to a Music + Music_output_def object (see parser.yy,
-definition of toplevel_expression )
-
-A Music + Music_output_def object leads to a Global_context object (see
-ly_run_translator ())
-
-During interpreting, Global_context + Music leads to a bunch of
-Contexts. (see Global_translator::run_iterator_on_me () )
-
-After interpreting, Global_context contains a Score_context (which
-contains staves, lyrics etc.) as a child. Score_context::get_output ()
-spews a Music_output object (either a Paper_score object for notation
-or Performance object for MIDI).
-
-The Music_output object is the entry point for the backend. (see
-ly_render_output () )
-
-The main steps of the backend itself are in
-
-@itemize
-
-@item
-paper-score.cc , Paper_score::process_
-
-@item
-system.cc , System::get_lines()
-
-@item
-The step, where things go from grobs to output, is in
-System::get_line(): each grob delivers a Stencil (a Device
-independent output description), which is interpreted by our
-outputting backends (scm/output-tex.scm and scm/output-ps.scm)
-to produce TeX and PS.
-
-@end itemize
-
-Interactions between grobs and putting things into .tex and .ps files
-have gotten a little more complex lately. Jan has implemented
-page-breaking, so now the backend also involves Paper_book,
-Paper_lines and other things. This area is still heavily in flux, and
-perhaps not something you should want to look at.
-
-@unnumberedsubsubsec How do the front-end and back-end communicate?
-
-There is no communication from backend to front-end. From front-end to
-backend is simply the program flow: music + definitions gives
-contexts, contexts yield output, after processing, output is written
-to disk.
-
-@unnumberedsubsubsec Where is the functionality associated with KEYWORDs=
?
-
-See my-lily-lexer.cc (keywords, there aren't that many) and ly/*.ly
-(most of the other backslashed \words are identifiers)
-
-@unnumberedsubsubsec What Contexts/Properties/Music/etc. are available w=
hen they are processed?
-
-What do you mean exactly with this question?
-
-See ly/engraver-init.ly for contexts, see scm/define-*.scm for other
-objects.
-
-@unnumberedsubsubsec How do you decide if something is a Music, Context,=
 or Grob property?
-Why is part-combine-status a Music property when it seems (IMO)
-to be related to the Staff context?
-
-The Music_iterators and Context communicate through two channels
-
-Music_iterators can set and read context properties, idem for
-Engravers and Contexts
-
-Music_iterators can send "synthetic" music events (which aren't in
-the input) to a context. These are caught by Engravers. This is
-mostly a one way communication channel.
-
-part-combine-status is part of such a synthetic event, used by
-Part_combine_iterator to communicate with Part_combine_engraver.
-
-
-@unnumberedsubsubsec I'm adding a property to affect how \autochange wor=
ks.  It seems to
-me that it should be a context property, but the Scheme autochange
-procecure has a Music argument.  Does this mean I should use
-a Music property?
-
-\autochange is one of these extra strange beasts: it requires
-look-ahead to decide when to change staves. This is achieved by
-running the interpreting step twice (see scm/part-combiner.scm , at
-the bottom), and storing the result of the first step (where to switch
-staves) in a Music property.  Since you want to influence that
-where-to-switch list, your must affect the code in
-make-autochange-music (scm/part-combiner.scm). That code is called
-directly from the parser and there are no official "parsing
-properties" yet, so there is no generic way to tune \autochange. We
-would have to invent something new for this, or add a separate
-argument,
-
-@example
-    \autochange #around-central-C ..music..
-@end example
-
-@noindent
-where around-central-C is some function that is called from
-make-autochange-music.
+we want to reuse the built-in definitions, without changes
+effected in a.ly leaking into the processing of b.ly.
=20
-@unnumberedsubsubsec I get lost figuring out what environment the code I=
'm looking at is in when it executes.
-I found both the C++ and Scheme autochange code.  Then I was
-trying to figure out where the code got called from.  I finally figured =
out that
-the Scheme procedure was called before the C++ iterator code, but it too=
k me a
-while to figure that out, and I still didn't know who did the calling in=
 the
-first place.  I only know a little bit about Flex and Bison, so reading =
those
-files helped only a little bit.
+Maintaining this scoping when one .ly file can be included in another
+.ly file can be challenging.  A @code{define-public-toplevel} macro
+has been created in order to handle a difficulty caused by the modules
+being not the same when a .ly file is included into another.
+This provided a way to define all markup commands in the same module.
+At this time, we have found no easier way to define a function in a give=
n
+module (not the current one) than to define this macro.
=20
-@emph{Han-Wen:} GDB can be of help here. Set a breakpoint in C++, and ru=
n. When you
-hit the breakpoint, do a backtrace. You can inspect Scheme objects
-along the way by doing
+With this architecture, the guile module system is not bypassed:
+module-define!, module-export!  and module-ref are all guile module
+primitives.
=20
-@example
-p ly_display_scm(obj)
-@end example
-
-this will display OBJ through GUILE.
-
-@subsection Music functions and GUILE debugging
-
-Ian Hulin was trying to do some debugging in music functions, and
-came up with the following question
-
-HI all,
-I'm working on the Guile Debugger Stuff, and would like to try
-debugging a music function definition such as:
-
-@example
-conditionalMark =3D #(define-music-function (parser location) ()
-=C2=A0=C2=A0=C2=A0 #@{ \tag #'instrumental-part @{\mark \default@}=C2=A0=
 #@} )
-@end example
-
-It appears conditionalMark does not get set up as an
-equivalent of a Scheme
-
-@example
-(define conditionalMark =3D define-music-function(parser location () ...
-@end example
-
-@noindent
-although something gets defined because Scheme apparently recognizes
-
-@example
-#(set-break! conditionalMark)
-@end example
-
-@noindent
-later on in the file without signalling any Guile errors.
-
-However the breakpoint trap is never encountered as
-define-music-function passed things on to ly:make-music-function,
-which is really C++ code ly_make_music_function, so Guile never
-finds out about the breakpoint.
-
-Han-Wen answered as follows:
-
-You can see the defintion by doing
-
-@example
-#(display conditionalMark)
-@end example
+A second reason for using this current architecture is to avoid memory
+leaks that could occur when running multiple files if toplevel
+functions were registered permanently.
=20
-noindent
-inside the .ly file.
=20
-The breakpoint failing may have to do with the call sequence.  See
-parser.yy, run_music_function().  The function is called directly from
-C++, without going through the GUILE evaluator, so I think that is why
-there is no debugger trap.
diff --git a/ly/guile-debugger.ly b/ly/guile-debugger.ly
index f6e63d3..05bea81 100644
--- a/ly/guile-debugger.ly
+++ b/ly/guile-debugger.ly
@@ -22,35 +22,28 @@
 %%  help
 %%  at the debug prompt to get a list of possible commands.
 %%  For more information, see the Contributor's Guide.
-
-
 \version "2.13.4"
-
-#(use-modules
-  (ice-9 debugger)
-  (ice-9 debugging trace)
-  (ice-9 debugging steps)
-  (ice-9 debugging ice-9-debugger-extensions))
-
-#(define (break! proc)
-   (install-trap (make <procedure-trap>
-                   #:procedure proc
-                   #:behaviour debug-trap)))
-
-#(define (trace! proc)
-   (install-trap (make <procedure-trap>
-                   #:procedure proc
-                   #:behaviour (list trace-trap
-                                     trace-at-exit))))
-
-#(define (trace-subtree! proc)
-   (install-trap (make <procedure-trap>
-                   #:procedure proc
-                   #:behaviour (list trace-trap
-                                     trace-until-exit))))
-
+% define lilypond-module as a variable in the guile-user module set to t=
he current Scheme module
+% (which will be the lilypond top-level module)
+%
 #(module-define! (resolve-module '(guile-user))
-                 'lilypond-module
-                 (current-module))
+                 'lilypond-module (current-module))
+%
+% Ensure we have command-line recall available at guile> prompt
+%
+#(use-modules (ice-9 readline))
+#(activate-readline)
+#(display "\n Guile debugger for Lilypond\n")
+#(newline)
+%
+% Ensure debugger definitions are available in lilypond-module and guile=
-user
+%
+#(use-modules (scm guile-debugger))
+#(debug-help)
+#(ly:module-copy (resolve-module '(guile-user)) (resolve-module '(scm gu=
ile-debugger)))
 #(top-repl)
+%
+% top-repl has re-set the module to guile-user,=20
+%  so we need to set it back to lilypond-module
+%
 #(set-current-module lilypond-module)
diff --git a/scm/guile-debugger.scm b/scm/guile-debugger.scm
new file mode 100755
index 0000000..4109196
--- /dev/null
+++ b/scm/guile-debugger.scm
@@ -0,0 +1,59 @@
+(define-module ( scm guile-debugger) =20
+  #:use-module  (ice-9 debugger)=20
+  #:use-module  (ice-9 debugging traps)
+  #:use-module  (ice-9 debugging trace)
+  #:use-module  (ice-9 debugging steps)=20
+  #:use-module  (ice-9 debugging ice-9-debugger-extensions)=20
+  #:use-module  (ice-9 readline)
+  #:export     (set-break!
+                clear-break!
+                set-trace-call!
+                clear-trace-call!
+                set-trace-subtree!
+                clear-trace-subtree!
+                debug-help))
+
+(define (set-break! proc)
+       (install-trap (make <procedure-trap>
+                       #:procedure proc
+                       #:behaviour debug-trap)))
+(define (clear-break! proc)
+       (uninstall-trap (make <procedure-trap>
+                       #:procedure proc
+                       #:behaviour debug-trap)))
+
+
+(define (set-trace-call! proc)
+       (install-trap (make <procedure-trap>
+                       #:procedure proc
+                       #:behaviour (list trace-trap
+                                         trace-at-exit))))
+(define (clear-trace-call! proc)
+       (uninstall-trap (make <procedure-trap>
+                       #:procedure proc
+                       #:behaviour (list trace-trap
+                                         trace-at-exit))))
+
+(define (set-trace-subtree! proc)
+       (install-trap (make <procedure-trap>
+                       #:procedure proc
+                       #:behaviour (list trace-trap
+                                         trace-until-exit))))
+
+(define (clear-trace-subtree! proc)
+       (uninstall-trap (make <procedure-trap>
+                       #:procedure proc
+                       #:behaviour (list trace-trap
+                                         trace-until-exit))))
+
+(define (debug-help )
+    (display "You may add the following commands as debugging statements=
 in your source file:\n\n")
+    (display "\t set-break! <procedure> \t\tto cause guile to halt on a =
call to <procedure>\n")
+    (display "\t clear-break! <procedure> \t\tto disable a breakpoint pr=
eviously set on a call to <procedure>\n")
+    (display "\t set-trace-call! <procedure> \t\tScheme will print out a=
 line when it enters or exits <procedure>\n")
+    (display "\t clear-trace-call! <procedure> \t\tScheme will no longer=
 print out a line when it enters or exits <procedure>\n")
+    (display "\t set-trace-subtree! <procedure> \tto display each line o=
f Scheme code executed during a call to <procedure>\n")
+    (display "\t clear-trace-subtree! <procedure> \tto turn off tracing =
code during calls to <procedure>\n\n")
+    (display "\t- use (set-current-module lilypond-module)\n")
+    (display "\t  to access your procedures or Lilypond Procedures")
+    (newline))
diff --git a/scm/lily.scm b/scm/lily.scm
index fca7857..9a152ed 100644
--- a/scm/lily.scm
+++ b/scm/lily.scm
@@ -190,17 +190,17 @@ messages into errors.")
 					;(set-debug-cell-accesses! 1000)
=20
 (use-modules (ice-9 regex)
-	     (ice-9 safe)
-	     (ice-9 format)
-	     (ice-9 rdelim)
-             (ice-9 optargs)
-	     (oop goops)
-	     (srfi srfi-1)
-	     (srfi srfi-13)
-	     (srfi srfi-14)
-	     (scm clip-region)
-	     (scm memory-trace)
-	     (scm coverage))
+              (ice-9 safe)
+              (ice-9 format)
+              (ice-9 rdelim)
+              (ice-9 optargs)
+              (oop goops)
+              (srfi srfi-1)
+              (srfi srfi-13)
+              (srfi srfi-14)
+              (scm clip-region)
+              (scm memory-trace)
+              (scm coverage))
=20
 (define-public fancy-format
   format)
--=20
1.6.3.3


--------------020105070901000704090506--

---
----
Join the Frogs!


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/