diff options
author | Neil Jerram <neil@ossau.uklinux.net> | 2006-08-11 16:21:14 +0000 |
---|---|---|
committer | Neil Jerram <neil@ossau.uklinux.net> | 2006-08-11 16:21:14 +0000 |
commit | 62ae95577a503e89114584ae8571b2b128d79ca5 (patch) | |
tree | 370ebdfe3574f074537f98474f3b85426e841ef8 /doc/ref/scheme-using.texi | |
parent | 5af872e136b2e7c74b566b68bbab97b288464578 (diff) | |
download | guile-62ae95577a503e89114584ae8571b2b128d79ca5.tar.gz |
* scheme-using.texi (Run To Frame Exit): Improved doc for finish.
(Continue Execution): Improved doc for continue.
(Using Guile in Emacs): Lots of new docs about the Emacs
interface.
* api-debug.texi (Low Level Trap Calls): New.
(Using Traps): Removed, material incorporated into Low Level Trap
Calls.
(High Level Traps): New.
(Breakpoints): New.
* scheme-using.texi (Single Stepping): Improve doc for step and
next.
* api-debug.texi (Debug on Error): Note need to handling of errors
in C.
Diffstat (limited to 'doc/ref/scheme-using.texi')
-rw-r--r-- | doc/ref/scheme-using.texi | 783 |
1 files changed, 778 insertions, 5 deletions
diff --git a/doc/ref/scheme-using.texi b/doc/ref/scheme-using.texi index b596ce50a..f7f49a45d 100644 --- a/doc/ref/scheme-using.texi +++ b/doc/ref/scheme-using.texi @@ -309,11 +309,16 @@ however it may be continued over multiple lines. [to be completed] @deffn {Debugger Command} step [n] -Continue until entry to @var{n}th next frame. +Tell the debugged program to do @var{n} single-steps to the next frame +entry or exit of any kind. @var{n} defaults to 1. @end deffn @deffn {Debugger Command} next [n] -Continue until entry to @var{n}th next frame in same file. +Tell the debugged program to do @var{n} single-steps to the entry or +exit of a frame whose code comes from the same source file as the +selected stack frame. (See @ref{Step Traps} for the details of how +this works.) If the selected stack frame has no source, the effect of +this command is the same as of @code{step}. @var{n} defaults to 1. @end deffn @@ -323,8 +328,9 @@ Continue until entry to @var{n}th next frame in same file. [to be completed] @deffn {Debugger Command} finish -Continue until evaluation of the current frame is complete, and -print the result obtained. +Tell the program being debugged to continue running until the +completion of the selected stack frame, and at that time to print the +result and reenter the command line debugger. @end deffn @deffn {Debugger Command} trace-finish @@ -338,7 +344,7 @@ Trace until evaluation of the current frame is complete. [to be completed] @deffn {Debugger Command} continue -Continue program execution. +Tell the program being debugged to continue running. @end deffn @@ -405,7 +411,774 @@ can also run a program until it hits a breakpoint, then examine, modify and reevaluate some of the relevant code, and then tell the program to continue running. +@ignore +GDS is a user interface for working on Guile Scheme programs in Emacs. +It aims to provide whatever facilities are needed to make the writing, +debugging and maintenance of Scheme code in Emacs as fluid and +productive as possible. These facilities currently include the +following. + +@table @asis +@item Displaying the Scheme stack +When running Scheme code hits a trap or throws an exception, GDS can +display the stack at the point of the trap or exception. The +presentation makes it very easy to move up and down the stack, showing +whenever possible the source code for each frame in another Emacs +buffer, and allowing you to evaluate test expressions in the context of +the selected frame. + +@item Continuing execution from a trap +When GDS is showing the stack for code that has hit a trap, it also +allows you to control how execution continues from that point. For +example you can select a stack frame and tell Guile to run until that +frame completes, at which point GDS will display the frame's return +value. + +@item Evaluating Scheme code +GDS allows you to select a region of a Scheme buffer and send it to +Guile for evaluation, or to enter a Scheme expression to be evaluated in +the Emacs minibuffer. In both cases the evaluation results are popped +up in a temporary Emacs window. + +@item Setting breakpoints in Scheme code +GDS makes it easy to set breakpoints in Scheme code from within Emacs. +Deep down this uses the traps described in previous chapters, but GDS +makes the practicalities as simple as typing @kbd{C-x @key{SPC}}. When +a GDS breakpoint is hit, the stack at that point is popped up in Emacs. +GDS also remembers your breakpoints between editing sessions, so you +don't have to set them again when you visit the relevant files. + +@item Access to Guile's built in help system +GDS makes it easy to query Guile's ``help'' and ``apropos'' commands, +and pops up the results in a temporary Emacs window. + +@item Symbol completion +GDS provides a keystroke which tries to complete a partially entered +symbol by asking Guile to match it against all the accessible bindings. +@end table + +(For a hands-on, tutorial introduction to using GDS, use Emacs to open +the file @file{gds-tutorial.txt}, which is included with the +guile-debugging distribution, and then follow the steps in that file.) + +GDS can provide these facilities for any number of Guile Scheme programs +(which we often call ``clients'') at once, and these programs can be +started either completely independently of GDS, including outside Emacs, +or specifically @emph{by} GDS. The two common cases are: +@itemize +@item +a Guile application, such as @uref{http://www.gnucash.org, GnuCash}, +which is started from your desktop, and which connects to GDS as a +result of some incantation added to its startup code + +@item +a ``utility'' Guile process which is run by GDS to provide help, +completion and evaluation for Scheme code that you are working on in +Emacs. +@end itemize + +@noindent +The user experience --- in other words the ways that the GDS front end +allows you to interact with the client --- is much the same in all +cases. + +Communication between the Guile client program and GDS uses a TCP +socket, which means that it is orthogonal to any other interfaces that +the client program has. In particular GDS does not interfere with a +program's standard input and output. +@end ignore + +@menu +* GDS Setup:: +* How To Use GDS:: +* Displaying the Scheme Stack:: +* Continuing Execution:: +* Evaluating Scheme Code:: +* Setting and Managing Breakpoints:: +* Access to Guile Help and Completion:: +* Associating Buffers with Clients:: +* An Example GDS Session:: +* GDS Architecture:: +@end menu + + +@node GDS Setup +@subsection GDS Setup + +GDS's Scheme and Emacs Lisp files will have been installed in +the correct places system-wide when the @code{guile-debugging} package +as a whole was installed. To enable the use of GDS in your own Emacs +sessions, simply add + +@lisp +(require 'gds) +@end lisp + +@noindent +somewhere in your @file{.emacs} file. + + +@node How To Use GDS +@subsection How To Use GDS + +There are lots of ways to use GDS, but they boil down to two overall +approaches. + +@enumerate +@item +When you are writing Scheme code in Emacs, you can use GDS while you are +writing to help with things like name completion, looking up help, and +evaluating fragments of code to check that they do what you expect. + +The first time you do something that needs a running Guile process, GDS +will automatically create one as an Emacs subprocess. This Guile +program does nothing but wait for and act on instructions from GDS, and +we refer to it as a @dfn{utility} Guile client. + +Over time this utility Guile will accumulate the code that you ask it to +evaluate, and you can also tell it to load complete files or modules by +sending it @code{load} or @code{use-modules} expressions. You can set +breakpoints and evaluate code which hits those breakpoints, and GDS will +pop up the stack at the breakpoint so you can explore your code by +single-stepping and evaluating test expressions. + +@item +Alternatively, you can use GDS to explore and debug a Guile program or +script which is started independently of GDS. This could be a script +that you invoke from the command line, or a graphical Guile-using +application which is launched from your desktop's start menu. + +In this case the program has to put something in its startup code to +cause it to connect to GDS at some point: either immediately during the +startup processing, or later when an error occurs or a trap is hit. +Several possibilities for this are described below. + +Under certain conditions, then, the program will stop, pass its current +Scheme stack to GDS, and then wait for instruction before continuing +execution. At such points you can use GDS to explore the stack, +obviously, but also to set or delete other breakpoints, modify the +program's code (by editing and then reevaluating it from Emacs), and use +the help and completion facilities, before eventually telling the +program to single-step or to continue running normally. +@end enumerate + +Here are some of the ways that a Guile program or script can arrange in +its startup code to use GDS. + +@subsubsection Invoking GDS when an Exception Occurs + +@lisp +(use-modules (ice-9 gds-client) + (ice-9 debugging traps)) + +(on-lazy-handler-dispatch gds-debug-trap) +@end lisp + +This means that the program will use GDS to display the stack whenever +it hits an exception that is protected by a @code{lazy-catch} using +Guile's standard @code{lazy-catch-handler} (defined in +@file{boot-9.scm}). + +@code{lazy-catch-handler} is used by the @code{stack-catch} procedure, +provided by the @code{(ice-9 stack-catch)} module, so this will include +exceptions within a @code{stack-catch}. @code{lazy-catch-handler} is +also used by the standard Guile REPL, when you run Guile interactively, +so you can add the above lines to your @file{.guile} file if you want to +use GDS whenever something that you type into the REPL throws an +exception. + +@subsubsection Setting GDS-managed Breakpoints + +@lisp +(use-modules (ice-9 gds-client)) +(set-gds-breakpoints) +@end lisp + +These lines tell the program to connect to GDS immediately and download +a set of breakpoint definitions. The program sets those breakpoints in +its code, then continues running. + +When the program later hits one of the breakpoints, it will use GDS to +display the stack and wait for instruction on what to do next, as +described above. + +@subsubsection Setting Specific Breakpoints + +@lisp +(use-modules (ice-9 debugging breakpoints) + (ice-9 gds-client)) + +(break-in 'fact2 "ice-9/debugging/example-fns" + #:behaviour gds-debug-trap) +@end lisp + +In this example, the program chooses to define its breakpoint explicitly +in its code, rather than downloading definitions from GDS, but it still +uses GDS to control what happens when the breakpoint is hit, by +specifying @code{gds-debug-trap} as the breakpoint behaviour. + +@subsubsection Accepting GDS Instructions at Any Time + +In addition to setting breakpoints and/or an exception handler as +described above, a Guile program can in principle set itself up to +accept new instructions from GDS at any time, not just when it has +stopped at a breakpoint or exception. This would allow the GDS user to +set new breakpoints or to evaluate code in the context of the running +program, without having to wait for the program to stop first. + +@lisp +(use-modules (ice-9 gds-client)) +(gds-accept-input #t) +@end lisp + +@code{gds-accept-input} causes the calling program to loop processing +instructions from GDS, until GDS sends the @code{continue} instruction. +This blocks the thread that calls it, however, so it will normally be +more practical for the program to set up a dedicated GDS thread and call +@code{gds-accept-input} from that thread. + +For @code{select}-driven applications, an alternative approach would be +for the GDS client code to provide an API which allowed the application +to + +@itemize +@item +discover the file descriptors (or Scheme ports) that are used for +receiving instruction from the GDS front end, so that it could include +these in its @code{select} call + +@item +call the GDS instruction handler when @code{select} indicated data +available for reading on those descriptors/ports. +@end itemize + +@noindent +This approach is not yet implemented, though. + +@subsubsection Utility Guile Implementation + +We bring this subsection full circle by noting that the ``utility'' Guile +client, which GDS starts automatically when you use GDS as described +under approach 1 above, is really just a special case of ``a Guile +program or script which is started independently'' (approach 2), and +provides the services that the GDS front end needs by a simple +combination of some of the code fragments just described. + +To be precise, the code for the utility Guile client is essentially +this: + +@lisp +(use-modules (ice-9 gds-client)) + +(set-gds-breakpoints) +(named-module-use! '(guile-user) '(ice-9 session)) +(gds-accept-input #f)) +@end lisp + +@code{set-gds-breakpoints} works as already described. The +@code{named-module-use!} line ensures that the client can process +@code{help} and @code{apropos} expressions, which is what the front end +sends to implement lookups in Guile's online help. The @code{#f} +parameter to @code{gds-accept-input} means that the @code{continue} +instruction will not cause the instruction loop to exit, which makes +sense here because the utility client has nothing to do except to +process GDS instructions. + +(The utility client does not use @code{on-lazy-handler-dispatch}, +because it has its own mechanism for catching and reporting exceptions +in the code that it is asked to evaluate. This mechanism summarizes the +exception and gives the user a button they can click to see the full +stack, so the end result is very similar to what +@code{on-lazy-handler-dispatch} provides.) + + +@node Displaying the Scheme Stack +@subsection Displaying the Scheme Stack + +When you specify @code{gds-debug-trap} as the behaviour for a trap or +a breakpoint and the Guile program concerned hits that trap or +breakpoint, GDS displays the stack and the relevant Scheme source code +in Emacs, allowing you to explore the state of the program and then +decide what to do next. The same applies if the program calls +@code{(on-lazy-handler-dispatch gds-debug-trap)} and then throws an +exception that passes through @code{lazy-handler-dispatch}, except +that in this case you can only explore; it isn't possible to continue +normal execution after an exception. + +The following commands are available in the stack buffer for exploring +the state of the program. + +@table @asis +@item @kbd{u}, @kbd{C-p}, @kbd{@key{up}} +@findex gds-up +Select the stack frame one up from the currently selected frame +(@code{gds-up}). GDS displays stack frames with the innermost at the +top, so moving ``up'' means selecting a more ``inner'' frame. + +@item @kbd{d}, @kbd{C-n}, @kbd{@key{down}} +@findex gds-down +Select the stack frame one down from the currently selected frame +(@code{gds-down}). GDS displays stack frames with the innermost at the +top, so moving ``down'' means selecting a more ``outer'' frame. + +@item @kbd{@key{RET}} +@findex gds-select-stack-frame +Select the stack frame at point (@code{gds-select-stack-frame}). This +is useful after clicking somewhere in the stack trace with the mouse. +@end table + +Selecting a frame means that GDS will display the source code +corresponding to that frame in the adjacent window, and that +subsequent frame-sensitive commands, such as @code{gds-evaluate} (see +below) and @code{gds-step-over} (@pxref{Continuing Execution}), will +refer to that frame. + +@table @kbd +@item e +@findex gds-evaluate +Evaluate a variable or expression in the local environment of the +selected stack frame (@code{gds-evaluate}). The result is displayed in +the echo area. + +@item I +@findex gds-frame-info +Show summary information about the selected stack frame +(@code{gds-frame-info}). This includes what type of frame it is, the +associated expression, and the frame's source location, if any. + +@item A +@findex gds-frame-args +For an application frame, display the frame's arguments +(@code{gds-frame-args}). + +@item S +@findex gds-proc-source +For an application frame, show the Scheme source code of the procedure +being called (@code{gds-proc-source}). The source code (where +available) is displayed in the echo area. +@end table + +@kbd{S} (@code{gds-proc-source}) is useful when the procedure being +called was created by an anonymous @code{(lambda @dots{})} expression. +Such procedures appear in the stack trace as @code{<procedure #f +(@dots{})>}, which doesn't give you much clue as to what will happen +next. @kbd{S} will show you the procedure's code, which is usually +enough for you to identify it. + + +@node Continuing Execution +@subsection Continuing Execution + +If it makes sense to continue execution from the stack which is being +displayed, GDS provides the following further commands in the stack +buffer. + +@table @asis +@item @kbd{g}, @kbd{c}, @kbd{q} +@findex gds-go +Tell the program to continue running (@code{gds-go}). It may of course +stop again if it hits another trap, or another occurrence of the same +trap. + +The multiple keystrokes reflect that you can think of this as ``going'', +``continuing'' or ``quitting'' (in the sense of quitting the GDS +display). + +@item @kbd{@key{SPC}} +@findex gds-step-file +Tell the program to do a single-step to the next entry or exit of a +frame whose code comes from the same source file as the selected stack +frame (@code{gds-step-file}). + +In other words, you can hit @kbd{@key{SPC}} repeatedly to step through +the code in a given file, automatically stepping @emph{over} any +evaluations or procedure calls that use code from other files (or from +no file). + +If the selected stack frame has no source, the effect of this command is +the same as that of @kbd{i}, described next. + +@item @kbd{i} +@findex gds-step-into +Tell the debugged program to do a single-step to the next frame entry or +exit of any kind (@code{gds-step-into}). @kbd{i} therefore steps +through code at the most detailed level possible. + +@item @kbd{o} +@findex gds-step-over +Tell the debugged program to continue running until the selected stack +frame completes, and then to display its result (@code{gds-step-over}). +Note that the program may stop before then if it hits another trap; in +this case the trap telling it to stop when the marked frame completes +remains in place and so will still fire at the appropriate point. +@end table + + +@node Evaluating Scheme Code +@subsection Evaluating Scheme Code + +The following keystrokes and commands provide various ways of sending +code to a Guile client process for evaluation. + +@table @kbd +@item M-C-x +@findex gds-eval-defun +Evaluate the ``top level defun'' that the cursor is in, in other words +the smallest balanced expression which includes the cursor and whose +opening parenthesis is in column 0 (@code{gds-eval-defun}). + +@item C-x C-e +@findex gds-eval-last-sexp +Evaluate the expression that ends just before the cursor +(@code{gds-eval-last-sexp}). This is designed so that it is easy to +evaluate an expression that you have just finished typing. + +@item C-c C-e +@findex gds-eval-expression +Read a Scheme expression using the minibuffer, and evaluate that +expression (@code{gds-eval-expression}). + +@item C-c C-r +@findex gds-eval-region +Evaluate the Scheme code in the marked region of the current buffer +(@code{gds-eval-region}). Note that GDS does not check whether the +region contains a balanced expression, or try to expand the region so +that it does; it uses the region exactly as it is. +@end table + + +@node Setting and Managing Breakpoints +@subsection Setting and Managing Breakpoints + +You can create a breakpoint in GDS by typing @kbd{C-x @key{SPC}} in a +Scheme mode buffer. To create a breakpoint on calls to a procedure +--- i.e. the equivalent of calling @code{break-in} --- place the +cursor on the procedure's name and type @kbd{C-x @key{SPC}}. To +create breakpoints on a particular expression, or on the series of +expressions in a particular region --- i.e. as with @code{break-at} +--- select the expression or region in the usual way and type @kbd{C-x +@key{SPC}}. In general, GDS assumes that you want a @code{break-at} +breakpoint if there is an active region, and a @code{break-in} +breakpoint otherwise. + +When you create a breakpoint like this, two things happen. Firstly, +if the current buffer is associated with a Guile client program, the +new breakpoint definition is immediately sent to that client (or, if +the client cannot accept input immediately, it is held in readiness to +pass to the client at the next possible opportunity). This allows the +new breakpoint to take effect as soon as possible in the relevant +client program. + +Secondly, it is added to GDS's @emph{global} list of all breakpoints. +This list holds the breakpoint information that will be given to any +client program that asks for it by calling @code{set-gds-breakpoints}. +The fact that this list is global, rather than client-specific, means +that the breakpoints you have set will automatically be recreated if +the program you are debugging has to be stopped and restarted --- +which in my experience happens often.@footnote{An important point here +is that there is nothing that unambiguously relates two subsequent +runs of the same client program, which might allow GDS to pass on +breakpoint settings more precisely.} + +(The only possible downside of this last point is that if you are +debugging two programs in parallel, which have some code in common, +you might not want a common code breakpoint in one program to be set +in the other program as well. But this feels like a small concern in +comparison to the benefit of breakpoints persisting as just described.) + + +@node Access to Guile Help and Completion +@subsection Access to Guile Help and Completion + +The following keystrokes provide fast and convenient access to Guile's +built in help, and to completion with respect to the set of defined and +accessible symbols. + +@table @kbd +@item C-h g +@findex gds-help-symbol +Get Guile help for a particular symbol, with the same results as if +you had typed @code{(help SYMBOL)} into the Guile REPL +(@code{gds-help-symbol}). The symbol to query defaults to the word at +or before the cursor but can also be entered or edited in the +minibuffer. The available help is popped up in a temporary Emacs +window. + +@item C-h C-g +@findex gds-apropos +List all accessible Guile symbols matching a given regular expression, +with the same results as if you had typed @code{(apropos REGEXP)} into +the Guile REPL (@code{gds-apropos}). The regexp to query defaults to +the word at or before the cursor but can also be entered or edited in +the minibuffer. The list of matching symbols is popped up in a +temporary Emacs window. + +@item M-@key{TAB} +@findex gds-complete-symbol +Try to complete the symbol at the cursor by matching it against the +set of all defined and accessible bindings in the associated Guile +process (@code{gds-complete-symbol}). If there are any extra +characters that can be definitively added to the symbol at point, they +are inserted. Otherwise, if there are any completions available, they +are popped up in a temporary Emacs window, where one of them can be +selected using either @kbd{@key{RET}} or the mouse. +@end table + + +@node Associating Buffers with Clients +@subsection Associating Buffers with Clients + +The first time that you use one of GDS's evaluation, help or completion +commands from a given Scheme mode buffer, GDS will ask which Guile +client program you want to use for the operation, or if you want to +start up a new ``utility'' client. After that GDS considers the buffer +to be ``associated'' with the selected client, and so sends all further +requests to that client, but you can override this by explicitly +associating the buffer with a different client, or by removing the +default association. + +@table @kbd +@item M-x gds-associate-buffer +Associate (or re-associate) the current buffer with a particular Guile +client program. The available clients are listed, and you can also +choose to start up a new ``utility'' client for this buffer to associate +with. + +@item M-x gds-dissociate-buffer +Dissociate the current buffer from its client, if any. This means that +the next time you use an evaluation, help or completion command, GDS +will ask you again which client to send the request to. +@end table + +When a buffer is associated with a client program, the buffer's modeline +shows whether the client is currently able to accept instruction from +GDS. This is done by adding one of the following suffixes to the +``Scheme'' major mode indicator: + +@table @asis +@item :ready +The client program (or one of its threads, if multithreaded) is +currently ready to accept instruction from GDS. In other words, if you +send it a help or evaluation request, you should see the result pretty +much immediately. + +@item :running +The client program is not currently able to accept instruction from +GDS. This means that it (or all of its threads, if multithreaded) is +busy, or waiting for input other than from GDS. + +@item :debug +The client program (or one of its threads, if multithreaded) is stopped +in ``debugging mode'' with GDS displaying the stack for a trap or +exception. It is waiting for instruction from GDS on what to do next. +@end table + + +@node An Example GDS Session +@subsection An Example GDS Session + +Create a file, @file{testgds.scm} say, for experimenting with GDS and +Scheme code, and type this into it: + +@lisp +(use-modules (ice-9 debugging traps) + (ice-9 gds-client) + (ice-9 debugging example-fns)) +(install-trap (make <procedure-trap> + #:behaviour gds-debug-trap + #:procedure fact1)) +@end lisp + +@noindent +Now select all of this code and type @kbd{C-c C-r} to send the selected +region to Guile for evaluation. GDS will ask you which Guile process to +use; unless you know that you already have another Guile application +running and connected to GDS, choose the ``Start a new Guile'' option, +which starts one of the ``utility'' processes described in @ref{How To +Use GDS}. + +The results of the evaluation pop up in a window like this: + +@lisp +(use-modules (ice-9 debugging traps)\n @dots{} + +;;; Evaluating subexpression 1 in current module (guile-user) + @result{} no (or unspecified) value + +;;; Evaluating subexpression 2 in current module (guile-user) + @result{} no (or unspecified) value + +--:** *Guile Evaluation* (Scheme:ready)--All------------ +@end lisp + +@noindent +this tells you that the evaluation was successful but that the return +values were unspecified. Its effect was to load a module of example +functions and set a trap on one of these functions, @code{fact1}, that +calculates the factorial of its argument. + +If you now call @code{fact1}, you can see the trap and GDS's stack +display in action. To do this add + +@lisp +(fact1 4) +@end lisp + +@noindent +to your @file{testgds.scm} buffer and type @kbd{C-x C-e} (which +evaluates the expression that the cursor is just after the end of). The +result is: + +@lisp +(fact1 4) + +;;; Evaluating in current module (guile-user) + @result{} 24 + +--:** *Guile Evaluation* (Scheme:ready)--All------------ +@end lisp + +@noindent +which is correct, but indicates that we forgot the step needed to enable +the trap mechanism. To do this, type @kbd{C-c C-e} and then enter + +@lisp +(trap-enable 'traps) +@end lisp + +@noindent +into the minibuffer. (You could equally have typed this into your test +file and evaluated it from there; we use @kbd{C-c C-e} here to +demonstrate the minibuffer option and because you typically wouldn't +want to leave this kind of global setting in the source code that you +are working on.) + +If you now type @kbd{C-x C-e} to evaluate @code{(fact1 4)} again, a GDS +stack window like the following appears: + +@lisp +Calling procedure: +=> s [fact1 4] + s [primitive-eval (fact1 4)] + + +--:** PID 28729 (Guile-Debug)--All------------ +@end lisp + +GDS's most compelling feature is its single-stepping. To get an +immediate feel for what this is like, make sure your Emacs is prepared +as described in @ref{GDS Setup}, then type the following code into an +interactive Guile session. + +@lisp +(fact1 4) +@end lisp + +@noindent +This will cause the GDS Guile-Debug window to pop up in Emacs, where +you can then press @kbd{i} once and @kbd{@key{SPC}} repeatedly to +single-step through the code from the point of the initial trap. + +(@kbd{i} is needed as the first keystroke rather than @kbd{@key{SPC}}, +because the aim here is to step through code in the @code{(ice-9 +debugging example-fns)} module, whose source file is +@file{@dots{}/ice-9/debugging/example-fns.scm}, but the initial +@code{(fact1 4)} call comes from the Guile session, whose ``source +file'' Guile presents as @file{standard input}. If the user starts by +pressing @kbd{@key{SPC}} instead of @kbd{i}, the effect is that the +program runs until it hits the first recursive call @code{(fact1 (- n +1))}, where it stops because of the trap on @code{fact1} firing again. +At this point, the source file @emph{is} +@file{@dots{}/ice-9/debugging/example-fns.scm}, because the recursive +@code{(fact1 (- n 1))} call comes from code in that file, so further +pressing of @kbd{@key{SPC}} successfully single-steps through this +file.) + + +@node GDS Architecture +@subsection GDS Architecture + +Ths following information may be of interest to readers who would like +to know how GDS works. Please note that understanding the details of +this subsection is completely optional so far as just using GDS is +concerned! + +GDS consists of three components. + +@itemize +@item +The GDS @dfn{interface} code is written in Emacs Lisp and runs inside +Emacs. This code, consisting of the installed files @file{gds.el} and +@file{gds-server.el}, is responsible for displaying information from +Guile in Emacs windows, and for responding to Emacs commands and +keystrokes by sending instructions back to the Guile program being +debugged. + +@item +The GDS @dfn{server} code is written in Scheme and runs as an Emacs +inferior process. It acts as a multiplexer between the (possibly +multiple) Guile programs being debugged and the interface code running +in Emacs. The server code is the installed file +@file{gds-server.scm}. + +@item +The GDS @dfn{client} code is written in Scheme (installed file +@file{gds-client.scm}), and is loaded as a module by each Guile +program that wants to use GDS for debugging. When a trap occurs whose +behaviour is @code{gds-debug-trap}, it feeds information about the +trap context through the server to Emacs, then waits for instruction +back from the Emacs interface on what to do next. +@end itemize + +@noindent +Summarized in glorious ASCII art, this looks as follows. + +@example ++------------+ +| Program #1 | +| | +| +--------+ | +| | Client |-_ +| +--------+ |-_ +---------------+ ++------------+ -_TCP | Emacs | + -_ | | + -_+--------+ | +-----------+ | + _| Server |-----| Interface | | ++------------+ _- +--------+ | +-----------+ | +| Program #2 | _- +---------------+ +| | _- TCP +| +--------+ _- +| | Client |-| +| +--------+ | ++------------+ +@end example + +@noindent +@cindex TCP, use of +The communication between the client and server components is over a +TCP connection, which has two implications. Firstly, that GDS is +independent of whatever other interfaces the programs being debugged +have, whether graphical or through standard input and output. +Secondly, that the server and Emacs interface can be on a different +computer from the programs being debugged (only theoretically, though, +because GDS doesn't yet provide an interface to connect to any server +other than the default, on localhost at TCP port 8333). The data +exchanged between client and server components, and between server and +interface components, is in the form of sexps that are organized so as +to be directly readable by both Scheme and Emacs Lisp. + + +@subsubsection Security Note + +@cindex Security +GDS currently has no authentication between its client and server +components, so in an untrusted environment the use of TCP probably +raises important security issues. If you are thinking of using GDS in +such an environment, please consider any such issues carefully before +proceeding! + + @c Local Variables: @c TeX-master: "guile.texi" @c End: |