From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Neil Jerram Newsgroups: gmane.lisp.guile.user Subject: Breakpoint doc Date: Fri, 29 Apr 2005 19:32:08 +0100 Message-ID: <42727DA8.20501@ossau.uklinux.net> NNTP-Posting-Host: main.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit X-Trace: sea.gmane.org 1114970395 31798 80.91.229.2 (1 May 2005 17:59:55 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Sun, 1 May 2005 17:59:55 +0000 (UTC) Original-X-From: guile-user-bounces+guile-user=m.gmane.org@gnu.org Sun May 01 19:59:51 2005 Return-path: Original-Received: from lists.gnu.org ([199.232.76.165]) by ciao.gmane.org with esmtp (Exim 4.43) id 1DSIj1-0004jc-Jv for guile-user@m.gmane.org; Sun, 01 May 2005 19:59:28 +0200 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1DSIpl-0001SC-En for guile-user@m.gmane.org; Sun, 01 May 2005 14:06:25 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1DSIEr-0005jL-Qy for guile-user@gnu.org; Sun, 01 May 2005 13:28:17 -0400 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1DSIEp-0005hT-Dn for guile-user@gnu.org; Sun, 01 May 2005 13:28:16 -0400 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1DSI3b-0000Uk-K9 for guile-user@gnu.org; Sun, 01 May 2005 13:16:39 -0400 Original-Received: from [199.232.41.67] (helo=mx20.gnu.org) by monty-python.gnu.org with esmtp (TLS-1.0:RSA_ARCFOUR_SHA:16) (Exim 4.34) id 1DSI6t-00053d-VW for guile-user@gnu.org; Sun, 01 May 2005 13:20:04 -0400 Original-Received: from [80.84.72.33] (helo=mail3.uklinux.net) by mx20.gnu.org with esmtp (Exim 4.34) id 1DRaM7-0003XO-IB for guile-user@gnu.org; Fri, 29 Apr 2005 14:36:51 -0400 Original-Received: from laruns (host81-130-142-214.in-addr.btopenworld.com [81.130.142.214]) by mail3.uklinux.net (Postfix) with ESMTP id 089AC409FB9 for ; Fri, 29 Apr 2005 18:32:38 +0000 (UTC) Original-Received: from [127.0.0.1] (laruns [127.0.0.1]) by laruns (Postfix) with ESMTP id C8E746FEAF for ; Fri, 29 Apr 2005 19:32:08 +0100 (BST) User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.7) Gecko/20050420 Debian/1.7.7-2 X-Accept-Language: en Original-To: Guile Gnu X-BeenThere: guile-user@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: General Guile related discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: guile-user-bounces+guile-user=m.gmane.org@gnu.org Errors-To: guile-user-bounces+guile-user=m.gmane.org@gnu.org Xref: news.gmane.org gmane.lisp.guile.user:4424 X-Report-Spam: http://spam.gmane.org/gmane.lisp.guile.user:4424 In case it triggers some feedback, here is some specification-masquerading-as-documentation in my continuing mission to implement a useful breakpoint facility for Guile. (The starting point for this is the trap documentation at www.ossau.uklinux.net/guile-debugging.) Neil 4.5 Setting and Managing Breakpoints ==================================== While they are an important piece of infrastructure, and directly usable in some scenarios, traps are still too low level to meet some of the requirements of interactive development. For example, in my experience a very common scenario is that a newly written procedure is not working properly, and so you'd like to be able to step or trace through its code to find out why. Ideally this should be possible from the IDE and without having to modify the source code. There are two problems with using traps directly in this scenario. 1. They are too detailed: constructing and installing a trap requires you to say what kind of trap you want and to specify fairly low level options for it, whereas what you really want is just to say "break here using the most efficient means possible." 2. The most efficient kinds of trap -- that is, `' and `' -- can only be specified and installed _after_ the code that they refer to has been loaded. This is an inconvenient detail for the user to deal with, and in some applications it might be very difficult to effect an instruction to install the required trap in between when the code is loaded and when the procedure concerned is first called. It would be better to be able to tell Guile about the requirement upfront, and for it to deal with installing the trap when possible. We solve these problems by introducing breakpoints. A breakpoint is something which says "I want to break at location X, or in procedure P -- just make it happen", and can be set regardless of whether the relevant code has already been loaded. Breakpoints use traps to do their work, but that is a detail that the user will usually not have to care about. Breakpoints are provided by a combination of Scheme code in the client program, and facilities for setting and managing breakpoints in the GDS front end. On the Scheme side the entry points are as follows. -- Getter with Setter: default-breakpoint-behaviour A "getter with setter" procedure that can be used to get or set the default behaviour for new breakpoints. When a new default behaviour is set, by calling (set! (default-breakpoint-behaviour) NEW-BEHAVIOUR) the new behaviour applies to all following `break-in' and `break-at' calls, but does not affect breakpoints which have already been set. NEW-BEHAVIOUR should be a behaviour procedure with the signature (lambda (trap-context) ...) as described in *Note Specifying Trap Behaviour::. -- Procedure: break-in procedure-name [options] Set a breakpoint on entry to the procedure named PROCEDURE-NAME, which should be a symbol. The available options are: `#:module MODULE-NAME' Specifies the name of the module that the target procedure is in. `#:behaviour BEHAVIOUR' Specifies a behaviour for this breakpoint other than the default. -- Procedure: break-at file-regexp line [options] -- Procedure: break-at file-regexp from-line to-line [options] -- Procedure: break-at file-regexp line from-column to-column [options] -- Procedure: break-at file-regexp from-line from-column to-line to-column [options] Set a breakpoint in the file matching FILE-REGEXP on all code expressions that begin in the specified range of lines and/or columns. FROM-COLUMN and all line numbers are inclusive; TO-COLUMN is exclusive. The available options are: `#:behaviour BEHAVIOUR' Specifies a behaviour for this breakpoint other than the default. -- Procedure: set-gds-breakpoints Ask the GDS front end for a list of breakpoints to set, and set these using `break-in' and `break-at' as appropriate. `default-breakpoint-behaviour', `break-in' and `break-at' allow an application's startup code to specify any breakpoints that it needs inline in that code. For example, to trace calls and arguments to a group of procedures to handle HTTP requests, one might write something like this: (use-modules (ossau breakpoints) (ossau trace)) (set! (default-breakpoint-behaviour) trace-trap) (break-in 'handle-http-request #:module '(web http)) (break-in 'read-http-request #:module '(web http)) (break-in 'decode-form-data #:module '(web http)) (break-in 'send-http-response #:module '(web http)) `set-gds-breakpoints' can be used as well as or instead of the above, and is intended to be the most practical option if you are using GDS. The idea is that you only need to add this one call somewhere in your application's startup code, like this: (use-modules (ossau breakpoints)) (set-gds-breakpoints) and then all the details of the breakpoints that you want to set can be managed through GDS. 4.5.1 Managing Breakpoints in GDS --------------------------------- You can create a breakpoint in GDS by typing `C-x ' in a Scheme mode buffer. To create a breakpoint on calls to a procedure -- i.e. the equivalent of calling `break-in' -- place the cursor on the procedure's name and type `C-x '. To create breakpoints on a particular expression, or on the series of expressions in a particular region -- i.e. as with `break-at' -- select the expression or region in the usual way and type `C-x '. In general, GDS assumes that you want a `break-at' breakpoint if there is an active region, and a `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 _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 `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.(1) (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.) ---------- Footnotes ---------- (1) 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. _______________________________________________ Guile-user mailing list Guile-user@gnu.org http://lists.gnu.org/mailman/listinfo/guile-user