document distributed with 4.1BSD
[unix-history] / usr / src / old / lisp / PSD.doc / ch11.n
CommitLineData
0165e2a3
NC
1.\" Copyright (c) 1980 Regents of the University of California.
2.\" All rights reserved. The Berkeley software License Agreement
3.\" specifies the terms and conditions for redistribution.
4.\"
836163c4 5.\" @(#)ch11.n 6.1 (Berkeley) %G%
0165e2a3 6.\"
836163c4
NC
7." $Header: ch11.n 1.1 83/01/31 07:08:25 jkf Exp $
8.Lc The\ Joseph\ Lister\ Trace\ Package 11
9.de Tf
10.sp 2v
11.ti -.5i
12\fB\\$1\fP -
13..
14.pp
15The Joseph Lister\*[\(dg\*] Trace package is an
16important tool for the interactive debugging of a Lisp
17program.
18.(f
19\*[\(dg\*]\fILister, Joseph\fP\ \ \ \
201st Baron Lister of Lyme Regis,
211827-1912; English surgeon: introduced antiseptic surgery.
22.)f
23It allows you to examine selected calls to a function or functions, and
24optionally to stop execution of the Lisp program to examine the values
25of variables.
26.pp
27The trace package is a set of Lisp programs located in the Lisp program
28library (usually in the file /usr/lib/lisp/trace.l).
29Although not normally loaded in the Lisp system, the package will
30be loaded in when the first call to \fItrace\fP is made.
31.Lf trace "[ls_arg1 ...]"
32.Wh
33the form of the ls_arg\fIi\fP is described below.
34.Re
35a list of the function sucessfully modified for tracing.
36If no arguments are given to
37.i trace ,
38a list of all functions currently being traced is returned.
39.Se
40The function definitions of the functions to trace are modified.
41.sp 2v
42.in 0
43The ls_arg\fIi\fP can have one of the following forms:
44.in .75i
45.Tf "foo"
46when foo is entered and exited, the trace information will be printed.
47.Tf "(foo break)"
48when foo is entered and exited the trace information will be printed.
49Also, just after the trace information for foo is printed upon entry,
50you will be put in a special break loop.
51The prompt is `T>' and you may type any Lisp expression, and see its
52value printed.
53The
54.i i th
55argument to the function just called can be accessed as (arg \fIi\fP).
56To leave the trace loop, just type ^D or (tracereturn)
57and execution will continue.
58Note that ^D will work only on UNIX systems.
59.Tf "(foo if expression)"
60when foo is entered and the expression evaluates to non-nil, then the
61trace information will be printed for both exit and entry.
62If expression evaluates to nil, then no trace information will be
63printed.
64.Tf "(foo ifnot expression)"
65when foo is entered and the expression evaluates to nil, then the
66trace information will be printed for both entry and exit.
67If both \fBif\fP and
68.b ifnot
69are specified, then the
70.b if
71expression must evaluate
72to non nil AND the
73.b ifnot
74expression must evaluate to nil for the trace
75information to be printed out.
76.Tf "(foo evalin expression)"
77when foo is entered and after the entry trace information is printed,
78expression will be evaluated.
79Exit trace information will be printed when foo exits.
80.Tf "(foo evalout expression)"
81when foo is entered, entry trace information will be printed.
82When foo exits, and before the exit trace information is printed,
83expression will be evaluated.
84.Tf "(foo evalinout expression)"
85this has the same effect as (trace (foo evalin expression evalout expression)).
86.Tf "(foo lprint)"
87this tells
88.i trace
89to use the level printer when printing the arguments to
90and the result of a call to foo.
91The level printer prints only the top levels of list structure.
92Any structure
93below three levels is printed as a &.
94This allows you to trace functions with massive arguments or results.
95.sp 2v
96.pp
97The following trace options permit one to have greater control over each
98action which takes place when a function is traced.
99These options are only meant to be used by people who need special hooks
100into the trace package.
101Most people should skip reading this section.
102.in .75i
103.Tf "(foo traceenter tefunc)"
104this tells
105.i trace
106that the function to be called when foo is entered is
107tefunc.
108tefunc should be a lambda of two arguments, the first argument will be
109bound to the name of the function being traced, foo in this case.
110The second argument will be bound to the list of arguments to which
111foo should be applied.
112The function tefunc should print some sort of "entering foo" message.
113It should not apply foo to the arguments, however.
114That is done later on.
115.Tf "(foo traceexit txfunc)"
116this tells
117.i trace
118that the function to be called when foo is exited is
119txfunc.
120txfunc should be a lambda of two arguments, the first argument will be
121bound to the name of the function being traced, foo in this case.
122The second argument will be bound to the result of the call to foo.
123The function txfunc should print some sort of "exiting foo" message.
124.Tf "(foo evfcn evfunc)"
125this tells
126.i trace
127that the form evfunc should be evaluated to get the value
128of foo applied to its arguments.
129This option is a bit different from the other special options since evfunc
130will usually be an expression, not just the name of a function, and that
131expression will be specific to the evaluation of function foo.
132The argument list to be applied will be available as T-arglist.
133.Tf "(foo printargs prfunc)"
134this tells
135.i trace
136to used prfunc to print the arguments to be
137applied to the function foo.
138prfunc should be a lambda of one argument.
139You might want to use this option if you wanted a print function which could
140handle circular lists.
141This option will work only if you do not specify your own
142.b traceenter
143function.
144Specifying the option
145.b lprint
146is just a simple way of changing the printargs
147function to the level printer.
148.Tf "(foo printres prfunc)"
149this tells
150.i trace
151to use prfunc to print the result of evaluating foo.
152prfunc should be a lambda of one argument.
153This option will work only if you do not specify your own
154.b traceexit
155function.
156Specifying the option
157.b lprint
158changes printres to the level printer.
159.sp 2v
160.pp
161You may specify more than one option for each function traced.
162For example:
163.sp 1v
164.ti .5i
165\fI(trace (foo if\ (eq 3 (arg 1)) break lprint) (bar evalin (print xyzzy)))\fP
166.sp 1v
167This tells
168.i trace
169to trace two more functions, foo and bar.
170Should foo be called with the first argument
171.i eq
172to 3, then the entering foo message will be printed with the level printer.
173Next it will enter a trace break loop, allowing you to evaluate any
174lisp expressions.
175When you exit the trace break loop, foo will be applied to its arguments
176and the resulting value will be printed, again using the level printer.
177Bar is also traced, and each time bar is entered, an entering bar message
178will be printed and then the value of xyzzy will be printed.
179Next bar will be applied to its arguments and the result will be printed.
180If you tell
181.i trace
182to trace a function which is already traced, it will first
183.i untrace
184it. Thus if you want to specify more than one trace option for
185a function, you must do it all at once.
186The following is
187.i not
188equivalent to the preceding call to
189.i trace
190for foo:
191.sp 1v
192\fI(trace (foo if (eq 3 (arg 1))) (foo break) (foo lprint))\fP
193.sp 1v.
194In this example, only the last option, lprint, will be in effect.
195.pp
196If the symbol $tracemute is given a non nil value, printing of the
197function name and arguments on entry and exit will be surpressed.
198This is particularly useful if the function you are tracing fails
199after many calls to it. In this case you would tell
200.i trace
201to
202trace the function, set $tracemute to t, and begin the computation.
203When an error occurs you can use
204.i tracedump
205to print out the current trace frames.
206.pp
207Generally the trace package has its own internal names for the the lisp
208functions it uses, so that you can feel free to trace system functions like
209.i cond
210and not worry about adverse interaction with the actions of the trace
211package.
212You can trace any type of function: lambda, nlambda, lexpr or macro whether
213compiled or interpreted and you can even trace array references (however
214you should not attempt to store in an array which has been traced).
215.pp
216When tracing compiled code keep in mind that many function calls are translated
217directly to machine language or other equivalent function calls.
218A full list of open coded functions is listed at the beginning of the
219liszt compiler source.
220.i Trace
221will do a \fI(sstatus\ translink\ nil)\fP to insure that the
222new traced definitions it defines are called instead of the old untraced ones.
223You may notice that compiled code will run slower after this is done.
224.Lf traceargs "s_func [x_level]"
225.Wh
226if x_level is missing it is assumed to be 1.
227.Re
228the arguments to the x_level\fIth\fP call to traced
229function s_func are returned.
230.Lf tracedump ""
231.Se
232the currently active trace frames are printed on the terminal.
233returns a list of functions untraced.
234.Lf untrace "[s_arg1 ...]"
235.Re
236a list of the functions which were untraced.
237.No
238if no arguments are given, all functions are untraced.
239.Se
240the old function definitions of all
241traced functions are restored
242except in the case where it appears that
243the current definition of a function was not created by trace.