-." @(#)ch11.n 34.1 1/29/81
-.Lc The\ Joseph\ Lister\ Trace\ Package 11
-.de Tf
-.sp 2v
-.ti -.5i
-\fB\\$1\fP -
-..
-.pp
-The Joseph Lister\*[\(dg\*] Trace package is an
-important tool for the interactive debugging of a Lisp
-program.
-.(f
-\*[\(dg\*]\fILister, Joseph\fP\ \ \ \
-1st Baron Lister of Lyme Regis,
-1827-1912; English surgeon: introduced antiseptic surgery.
-.)f
-It allows you to examine selected calls to a function or functions, and
-optionally to stop execution of the Lisp program to examine the values
-of variables.
-.pp
-The trace package is a set of Lisp programs located in the Lisp program
-library (usually in the file /usr/lib/lisp/trace.l).
-There are two user callable functions in the trace package:
-.i trace
-and
-.i untrace .
-The trace package will be loaded automatically when you first use the
-.i trace
-function.
-Both
-.i trace and
-.i untrace
-are nlambdas (their arguments are not evaluated).
-The form of a call to
-.i trace
-is
-.br
-.tl ''\fB(trace \fIarg1 arg2 ...\fB)\fR''
-where the
-.i argi
-have one of the following forms:
-.in .75i
-.Tf "foo"
-when foo is entered and exited, the trace information will be printed.
-.Tf "(foo break)"
-when foo is entered and exited the trace information will be printed.
-Also, just after the trace information for foo is printed upon entry,
-you will be put in a special break loop.
-The prompt is `T>' and you may type any Lisp expression, and see its
-value printed.
-The
-.i i th
-argument to the function just called can be accessed as (arg \fIi\fP).
-To leave the trace loop, just type ^D or (tracereturn)
-and execution will continue.
-Note that ^D will work only on UNIX systems.
-.Tf "(foo if expression)"
-when foo is entered and the expression evaluates to non-nil, then the
-trace information will be printed for both exit and entry.
-If expression evaluates to nil, then no trace information will be
-printed.
-.Tf "(foo ifnot expression)"
-when foo is entered and the expression evaluates to nil, then the
-trace information will be printed for both entry and exit.
-If both \fBif\fP and
-.b ifnot
-are specified, then the
-.b if
-expression must evaluate
-to non nil AND the
-.b ifnot
-expression must evaluate to nil for the trace
-information to be printed out.
-.Tf "(foo evalin expression)"
-when foo is entered and after the entry trace information is printed,
-expression will be evaluated.
-Exit trace information will be printed when foo exits.
-.Tf "(foo evalout expression)"
-when foo is entered, entry trace information will be printed.
-When foo exits, and before the exit trace information is printed,
-expression will be evaluated.
-.Tf "(foo evalinout expression)"
-this has the same effect as (trace (foo evalin expression evalout expression)).
-.Tf "(foo lprint)"
-this tells
-.i trace
-to use the level printer when printing the arguments to
-and the result of a call to foo.
-The level printer prints only the top levels of list structure.
-Any structure
-below three levels is printed as a &.
-This allows you to trace functions with massive arguments or results.
-.sp 2v
-.pp
-The following trace options permit one to have greater control over each
-action which takes place when a function is traced.
-These options are only meant to be used by people who need special hooks
-into the trace package.
-Most people should skip reading this section.
-.in .75i
-.Tf "(foo traceenter tefunc)"
-this tells
-.i trace
-that the function to be called when foo is entered is
-tefunc.
-tefunc should be a lambda of two arguments, the first argument will be
-bound to the name of the function being traced, foo in this case.
-The second argument will be bound to the list of arguments to which
-foo should be applied.
-The function tefunc should print some sort of "entering foo" message.
-It should not apply foo to the arguments, however.
-That is done later on.
-.Tf "(foo traceexit txfunc)"
-this tells
-.i trace
-that the function to be called when foo is exited is
-txfunc.
-txfunc should be a lambda of two arguments, the first argument will be
-bound to the name of the function being traced, foo in this case.
-The second argument will be bound to the result of the call to foo.
-The function txfunc should print some sort of "exiting foo" message.
-.Tf "(foo evfcn evfunc)"
-this tells
-.i trace
-that the form evfunc should be evaluated to get the value
-of foo applied to its arguments.
-This option is a bit different from the other special options since evfunc
-will usually be an expression, not just the name of a function, and that
-expression will be specific to the evaluation of function foo.
-The argument list to be applied will be available as T-arglist.
-.Tf "(foo printargs prfunc)"
-this tells
-.i trace
-to used prfunc to print the arguments to be
-applied to the function foo.
-prfunc should be a lambda of one argument.
-You might want to use this option if you wanted a print function which could
-handle circular lists.
-This option will work only if you do not specify your own
-.b traceenter
-function.
-Specifying the option
-.b lprint
-is just a simple way of changing the printargs
-function to the level printer.
-.Tf "(foo printres prfunc)"
-this tells
-.i trace
-to use prfunc to print the result of evaluating foo.
-prfunc should be a lambda of one argument.
-This option will work only if you do not specify your own
-.b traceexit
-function.
-Specifying the option
-.b lprint
-changes printres to the level printer.
-.sp 2v
-.pp
-You may specify more than one option for each function traced.
-For example:
-.sp 1v
-.ti .5i
-\fI(trace (foo if\ (eq 3 (arg 1)) break lprint) (bar evalin (print xyzzy)))\fP
-.sp 1v
-This tells
-.i trace
-to trace two more functions, foo and bar.
-Should foo be called with the first argument
-.i eq
-to 3, then the entering foo message will be printed with the level printer.
-Next it will enter a trace break loop, allowing you to evaluate any
-lisp expressions.
-When you exit the trace break loop, foo will be applied to its arguments
-and the resulting value will be printed, again using the level printer.
-Bar is also traced, and each time bar is entered, an entering bar message
-will be printed and then the value of xyzzy will be printed.
-Next bar will be applied to its arguments and the result will be printed.
-If you tell
-.i trace
-to trace a function which is already traced, it will first
-.i untrace
-it. Thus if you want to specify more than one trace option for
-a function, you must do it all at once.
-The following is
-.i not
-equivalent to the preceding call to
-.i trace
-for foo:
-.sp 1v
-\fI(trace (foo if (eq 3 (arg 1))) (foo break) (foo lprint))\fP
-.sp 1v.
-In this example, only the last option, lprint, will be in effect.
-.pp
-The function
-.i trace
-returns a list of functions is was able to trace.
-The function
-.i untrace
-untraces those functions its is argument list.
-If the argument list is empty then all functions being traced are untraced.
-.i Untrace
-returns a list of functions untraced.
-.pp
-Generally the trace package has its own internal names for the the lisp
-functions it uses, so that you can feel free to trace system functions like
-.i cond
-and not worry about adverse interaction with the actions of the trace
-package.
-You can trace any type of function: lambda, nlambda, lexpr or macro whether
-compiled or interpreted and you can even trace array references (however
-you should not attempt to store in an array which has been traced).
-.pp
-When tracing compiled code keep in mind that many function calls are translated
-directly to machine language or other equivalent function calls.
-A full list of open coded functions is listed at the beginning of the
-liszt compiler source.
-.i Trace
-will do a \fI(sstatus\ translink\ nil)\fP to insure that the
-new traced definitions it defines are called instead of the old untraced ones.
-You may notice that compiled code will run slower after this is done.