<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE TIP SYSTEM "http://www.tcl.tk/cgi-bin/tct/tip/tipxml.dtd">
<!-- Converted at Sun May 19 06:50:39 GMT 2013 -->
<!-- TIP AutoGenerator - written by Donal K. Fellows -->

<TIP number='62'>
<header><title>Add Support for Command Tracing</title><author address="mailto:HemangLavana@users.sourceforge.net">Hemang Lavana</author><author address="mailto:vince.darley@eurobios.com">Vince Darley</author><status type='project' state='final' tclversion="8.4" vote='after'>$Revision: 1.11 $</status><history></history><created day='18' month='sep' year='2001' /></header>
<abstract>This TIP proposes that the Tcl&apos;s trace command be extended to include the following features: 1. tracing of command execution for the specified tcl command, and 2. step-wise tracing of any command execution within a specified procedure.</abstract>
<body><section title="Rationale">
<para>One of the main strengths of Tcl is the ability to trace <emph style="italic">read</emph>, <emph style="italic">write</emph> or <emph style="italic">delete</emph> operations on variables. Moreover, Tcl8.4 has already added support for tracing <emph style="italic">rename</emph> or <emph style="italic">delete</emph> operations on Tcl commands. Addition of the proposed subcommand for tracing executions will further improve the capabilities of Tcl without any loss of performance (see <emph style="italic">Benchmark Results</emph> section below).</para>
<para>I can see several applications of this feature, including:</para>
<itemize><item.i><para> overloading/wrapping of Tcl commands, please see <url ref="http://mini.net/tcl/1494.html"/></para></item.i><item.i><para> aid developer in debugging Tcl scripts</para></item.i><item.i><para> profiler module in <emph style="italic">tcllib</emph> can benefit from this feature</para></item.i></itemize>
</section>
<section title="Specification">
<para>This TIP proposes an enhancement to the trace command with the following syntax:</para>
<verbatim><vline encoding='base64'>ICAgICAgICB0cmFjZSBhZGQgZXhlY3V0aW9uIG5hbWUgb3BzIGNvbW1hbmQ=</vline></verbatim>
<para>The type <emph style="italic">execution</emph> is used to arrange for <emph style="italic">command</emph> to be executed whenever the command <emph style="italic">name</emph> is invoked for execution. <emph style="italic">Name</emph> may refer to any of the tcl commands or procedures that have been previously defined. It is an error to create an <emph style="italic">execution</emph> trace on a non-existant command or a procedure.</para>
<para>The <emph style="italic">ops</emph> argument can accept <emph style="italic">enter</emph>, <emph style="italic">leave</emph>, <emph style="italic">enterstep</emph>, and <emph style="italic">leavestep</emph> as valid operations:</para>
<enumerate><item.e index='1'><para><emph style="italic">enter</emph> - Invoke <emph style="italic">command</emph> whenever the command <emph style="italic">name</emph> is executed, just before the actual execution takes place.</para></item.e><item.e index='2'><para><emph style="italic">leave</emph> - Invoke <emph style="italic">command</emph> whenever the command <emph style="italic">name</emph> is executed, just after the actual execution takes place.</para></item.e><item.e index='3'><para><emph style="italic">enterstep</emph> - Invoke <emph style="italic">command</emph> for every tcl command which is executed inside the procedure <emph style="italic">name</emph>, just before the actual execution takes place. Setting a <emph style="italic">enterstep</emph> trace on a <emph style="italic">command</emph> will not result in an error and is simply ignored.</para></item.e><item.e index='4'><para><emph style="italic">leavestep</emph> - Invoke <emph style="italic">command</emph> for every tcl command which is executed inside the procedure <emph style="italic">name</emph>, just after the actual execution takes place. Setting a <emph style="italic">leavestep</emph> trace on a <emph style="italic">command</emph> will not result in an error and is simply ignored.</para></item.e></enumerate>
<para>When the trace triggers, depending on the operations being traced, a number of arguments are appended to command so that the actual command is as follows:</para>
<para>For <emph style="italic">enter</emph> and <emph style="italic">enterstep</emph> operations:</para>
<verbatim><vline encoding='base64'>ICAgIGNvbW1hbmQgY29tbWFuZC1zdHJpbmcgb3A=</vline></verbatim>
<para><emph style="italic">command-string</emph> gives the complete current command being executed, including all arguments in their fully expanded form. <emph style="italic">Op</emph> indicates what operation is being performed on the variable, and is one of <emph style="italic">enter</emph> or <emph style="italic">enterstep</emph> here. The trace operation can be used to stop the command from executing, by deleting the command in question. Of course when the command is subsequently executed, an &apos;invalid command&apos; error will occur.</para>
<para>For <emph style="italic">leave</emph> and <emph style="italic">leavestep</emph> operations:</para>
<verbatim><vline encoding='base64'>ICAgY29tbWFuZCBjb21tYW5kLXN0cmluZyBjb2RlIHJlc3VsdCBvcA==</vline></verbatim>
<para><emph style="italic">command-string</emph> gives the complete current command being executed, including all arguments in their fully expanded form. <emph style="italic">code</emph> gives the result code of that execution, and <emph style="italic">result</emph> gives its result string. <emph style="italic">Op</emph> indicates what operation is being performed on the variable, and is one of <emph style="italic">leave</emph> or <emph style="italic">leavestep</emph> here.</para>
<para><emph style="italic">Command</emph> executes in the same context as the code that invoked the traced operation: thus the <emph style="italic">command</emph>, if invoked from a procedure, will have access to the same local variables as code in the procedure. This context may be different than the context in which the trace was created. If <emph style="italic">command</emph> invokes a procedure (which it normally does) then the procedure will have to use upvar or uplevel commands if it wishes to access the local variables of the code which invoked the trace operation. Note that if the value of a local variable is passed as an argument to the traced command <emph style="italic">name</emph> and is modified by the <emph style="italic">command</emph> procedure, the traced command <emph style="italic">name</emph> will still be invoked with the old value of the local variable. This is because the argument list to <emph style="italic">name</emph> is formed before the traced <emph style="italic">command</emph> is invoked. Please see the section on <emph style="italic">Future Scope</emph> below on how to modify the arguments passed to <emph style="italic">name</emph>.</para>
<para>While <emph style="italic">command</emph> is executing during an <emph style="italic">execution</emph> trace, traces on <emph style="italic">name</emph> are temporarily disabled. This allows the <emph style="italic">command</emph> to execute <emph style="italic">name</emph> in its body without invoking any other traces again. If an error occurs while executing the <emph style="italic">command</emph> body, then the command <emph style="italic">name</emph> as a whole will return that same error. Therefore, if <emph style="italic">catch</emph> command is used for invocation of the <emph style="italic">name</emph> command, it will also ignore errors resulting from such traces.</para>
<para>When multiple traces are set on <emph style="italic">name</emph>, then the sequence of trace command invocation is as follows:</para>
<enumerate><item.e index='1'><para> For <emph style="italic">enter</emph> and <emph style="italic">enterstep</emph> operations, the traced commands are invoked in the reverse order of how these traces were created.</para></item.e><item.e index='2'><para> For <emph style="italic">leave</emph> and <emph style="italic">leavestep</emph> operations, the traced commands are invoked in the same order as how these traces were created.</para></item.e></enumerate>
<para>For example, if we have two traces on proc foo:</para>
<verbatim><vline encoding='base64'>ICAgIHRyYWNlIGFkZCBleGVjdXRpb24gZm9vIHtlbnRlciBsZWF2ZX0ge2JhckF9</vline><vline encoding='base64'>ICAgIHRyYWNlIGFkZCBleGVjdXRpb24gZm9vIHtlbnRlciBsZWF2ZX0ge2JhckJ9</vline></verbatim>
<para>then the trace commands <emph style="italic">barA</emph> and <emph style="italic">barB</emph> will be invoked in the following sequence:</para>
<verbatim><vline encoding='base64'>ICAgIGJhckIge2ZvbyB4fSB7ZW50ZXJ9</vline><vline encoding='base64'>ICAgIGJhckEge2ZvbyB4fSB7ZW50ZXJ9</vline><vline encoding='base64'>ICAgICAgZm9vIHg=</vline><vline encoding='base64'>ICAgIGJhckEge2ZvbyB4fSAwIHt9IHtsZWF2ZX0=</vline><vline encoding='base64'>ICAgIGJhckIge2ZvbyB4fSAwIHt9IHtsZWF2ZX0=</vline></verbatim>
<para>The creation of many <emph style="italic">enterstep</emph> or <emph style="italic">leavestep</emph> traces can lead to unintuitive results, since the invoked commands from one trace can themselves lead to further command invocations for other traces. However, these unintuitive results are completely predictable and safe (and tested in the test suite). Nevertheless the user will probably only want to have one such trace active at a time.</para>
<para>Once created, the trace remains in effect either until the trace is removed with the <emph style="italic">trace remove execution</emph> command, until the <emph style="italic">name</emph> is deleted or until the interpreter is deleted. Note that renaming the command <emph style="italic">name</emph> will not remove the execution traces.</para>
<para>To implement <emph style="italic">enterstep</emph> and <emph style="italic">leavestep</emph> traces, it is necessary to invoke traces regardless of at what level the <emph style="italic">command</emph> is being traced. This means that the value for <emph style="italic">level</emph> argument to Tcl_CreateTrace and Tcl_CreateObjTrace APIs should also accept <emph style="italic">0</emph>. A value of <emph style="italic">0</emph> implies that commands at all levels will be traced. </para>
</section>
<section title="Examples">
<para>The following script defines a procedure <emph style="italic">foo</emph> and illustrates several cases as to how its execution can be traced.</para>
<verbatim><vline encoding='base64'>ICAgICMgRGVmaW5lIHRoZSBwcm9jIGZvbw==</vline><vline encoding='base64'>ICAgIHByb2MgZm9vIHt2YXJ9IHs=</vline><vline encoding='base64'>ICAgICAgICAgcmV0dXJuIFtzdHJpbmcgaW5kZXggJHZhciBbZXhwciB7JHZhcioyfV1d</vline><vline encoding='base64'>ICAgIH0=</vline><vline encoding='base64'>ICAgIA==</vline><vline encoding='base64'>ICAgICMgQ29tbWFuZCB0byBpbnZva2Ugb24gdHJhY2UgYWN0aXZhdGlvbg==</vline><vline encoding='base64'>ICAgIHByb2MgcHJpbnQge2FyZ3N9IHs=</vline><vline encoding='base64'>ICAgICAgICBwdXRzIHN0ZG91dCAiUFJJTlQ6ICRhcmdzIg==</vline><vline encoding='base64'>ICAgIH0=</vline><vline encoding='base64'>ICAgIA==</vline><vline encoding='base64'>ICAgIHByb2MgbWFpbiB7fSB7</vline><vline encoding='base64'>ICAgICAgICBwdXRzIHN0ZG91dCAiPT09PT09PT09PT09PT09PUNBU0UgMT09PT09PT09PT09PT09PT09PT09PT09PT0i</vline><vline encoding='base64'>ICAgICAgICBwdXRzIHN0ZG91dCAiVHJhY2UgcHJvYyBmb28gb25seSI=</vline><vline encoding='base64'>ICAgICAgICB0cmFjZSBhZGQgZXhlY3V0aW9uIGZvbyB7ZW50ZXIgbGVhdmV9IHtwcmludCBleGVjfQ==</vline><vline encoding='base64'>ICAgICAgICBmb28gNA==</vline><vline encoding='base64'>ICAgIA==</vline><vline encoding='base64'>ICAgICAgICBwdXRzIHN0ZG91dCAiPT09PT09PT09PT09PT09PUNBU0UgMj09PT09PT09PT09PT09PT09PT09PT09PT0i</vline><vline encoding='base64'>ICAgICAgICBwdXRzIHN0ZG91dCAiVHJhY2UgcHJvYyBmb28gYXMgd2VsbCBhcyBhbGwgY29tbWFuZHMgd2l0aGluIGl0Ig==</vline><vline encoding='base64'>ICAgICAgICB0cmFjZSBhZGQgZXhlY3V0aW9uIGZvbyB7ZW50ZXJzdGVwIGxlYXZlc3RlcH0ge3ByaW50IHN0ZXB9</vline><vline encoding='base64'>ICAgICAgICBmb28gNA==</vline><vline encoding='base64'>ICAgIA==</vline><vline encoding='base64'>ICAgICAgICAjIFJlbW92ZSBhbGwgdHJhY2Vz</vline><vline encoding='base64'>ICAgICAgICB0cmFjZSByZW1vdmUgZXhlY3V0aW9uIGZvbyB7ZW50ZXIgbGVhdmV9IHtwcmludCBleGVjfQ==</vline><vline encoding='base64'>ICAgICAgICB0cmFjZSByZW1vdmUgZXhlY3V0aW9uIGZvbyB7ZW50ZXJzdGVwIGxlYXZlc3RlcH0ge3ByaW50IHN0ZXB9</vline><vline encoding='base64'>ICAgIA==</vline><vline encoding='base64'>ICAgICAgICBwdXRzIHN0ZG91dCAiPT09PT09PT09PT09PT09PUNBU0UgMz09PT09PT09PT09PT09PT09PT09PT09PT0i</vline><vline encoding='base64'>ICAgICAgICBwdXRzIHN0ZG91dCAiQWRkIGEgdHJhY2Ugb24gc3RyaW5nIGNvbW1hbmQi</vline><vline encoding='base64'>ICAgICAgICB0cmFjZSBhZGQgZXhlY3V0aW9uIHN0cmluZyB7ZW50ZXIgbGVhdmV9IHtwcmludCBleGVjfQ==</vline><vline encoding='base64'>ICAgICAgICBmb28gNA==</vline><vline encoding='base64'>ICAgICAgICB0cmFjZSByZW1vdmUgZXhlY3V0aW9uIHN0cmluZyB7ZW50ZXIgbGVhdmV9IHtwcmludCBleGVjfQ==</vline><vline encoding='base64'>ICAgIH0=</vline><vline encoding='base64'>ICAgIG1haW4=</vline></verbatim>
<para>The expected output of running the above script would be:</para>
<verbatim><vline encoding='base64'>ICAgID09PT09PT09PT09PT09PT09PT1DQVNFIDE9PT09PT09PT09PT09PT09PT09PT09PT0=</vline><vline encoding='base64'>ICAgIFRyYWNlIHByb2MgZm9vIG9ubHk=</vline><vline encoding='base64'>ICAgIFBSSU5UOiBleGVjIHtmb28gNH0gZW50ZXI=</vline><vline encoding='base64'>ICAgIFBSSU5UOiBleGVjIHtmb28gNH0gMCB7fSBsZWF2ZQ==</vline><vline encoding='base64'>ICAgID09PT09PT09PT09PT09PT09PT1DQVNFIDI9PT09PT09PT09PT09PT09PT09PT09PQ==</vline><vline encoding='base64'>ICAgIFRyYWNlIHByb2MgZm9vIGFzIHdlbGwgYXMgYWxsIGNvbW1hbmRzIHdpdGhpbiBpdA==</vline><vline encoding='base64'>ICAgIFBSSU5UOiBleGVjIHtmb28gNH0gZW50ZXI=</vline><vline encoding='base64'>ICAgIFBSSU5UOiBzdGVwIHtleHByIHskdmFyKjJ9fSBlbnRlcnN0ZXA=</vline><vline encoding='base64'>ICAgIFBSSU5UOiBzdGVwIHtleHByIHskdmFyKjJ9fSAwIDggbGVhdmVzdGVw</vline><vline encoding='base64'>ICAgIFBSSU5UOiBzdGVwIHtzdHJpbmcgaW5kZXggNCA4fSBlbnRlcnN0ZXA=</vline><vline encoding='base64'>ICAgIFBSSU5UOiBzdGVwIHtzdHJpbmcgaW5kZXggNCA4fSAwIHt9IGxlYXZlc3RlcA==</vline><vline encoding='base64'>ICAgIFBSSU5UOiBzdGVwIHtyZXR1cm4ge319IGVudGVyc3RlcA==</vline><vline encoding='base64'>ICAgIFBSSU5UOiBzdGVwIHtyZXR1cm4ge319IDIge30gbGVhdmVzdGVw</vline><vline encoding='base64'>ICAgIFBSSU5UOiBleGVjIHtmb28gNH0gMCB7fSBsZWF2ZQ==</vline><vline encoding='base64'>ICAgID09PT09PT09PT09PT09PT09PT1DQVNFIDM9PT09PT09PT09PT09PT09PT09PT09PQ==</vline><vline encoding='base64'>ICAgIEFkZCBhIHRyYWNlIG9uIHN0cmluZyBjb21tYW5k</vline><vline encoding='base64'>ICAgIFBSSU5UOiBleGVjIHtzdHJpbmcgaW5kZXggNCA4fSBlbnRlcg==</vline><vline encoding='base64'>ICAgIFBSSU5UOiBleGVjIHtzdHJpbmcgaW5kZXggNCA4fSAwIHt9IGxlYXZl</vline></verbatim>
<para>Case 1 specifies a enter and leave trace on proc foo. Here the proc foo is fully byte-code-compiled.</para>
<para>Case 2 additionally invokes a enterstep and leavestep trace on proc foo. This means that it will trace each command that is inovked within the proc foo. Here the proc foo is *not* byte-code-compiled. This is implemented by setting the DONT_COMPILE_CMDS_INLINE flag.</para>
<para>Case 3 specifies a trace on string command only. Here all commands within proc foo, except string command, is byte-code-compiled. This is implemented by modifying compilation engine to check for CMD_HAS_EXEC_TRACES flag before generating any byte-code.</para>
</section>
<section title="Reference Implementation">
<para>This proposal was originally implemented by Vince Darley. Please see Feature Request #462580: <url ref="http://sf.net/tracker/?func=detail&amp;aid=462580&amp;group_id=10894&amp;atid=360894"/></para>
<para>The original patch from Vince Darley has been modified in the following respects:</para>
<enumerate><item.e index='1'><para> For <emph style="italic">enter</emph> and <emph style="italic">enterstep</emph> operations, the original patch passed arguments to the <emph style="italic">command</emph> in its unexpanded form. This behavior has been changed to pass the arguments in its fully expanded form since it should be more useful for debugging scripts.</para></item.e><item.e index='2'><para> The original patch could not trace Tcl commands that were invoked inside a procedure because tracing is currently not possible for compiled commands. Therefore, the patch was modified such that Tcl commands are no longer internally compiled if a trace has been set on a command.</para></item.e><item.e index='3'><para> For multiple traces on same command, the original patch invoked the traces in the same order as they were created. This behavior was changed so that for <emph style="italic">enter</emph> and <emph style="italic">enterstep</emph> operations, the traces are invoked in the reverse order of its creation. For <emph style="italic">leave</emph> and <emph style="italic">leavestep</emph>, the traces are still invoked in the original order.</para></item.e><item.e index='4'><para> The original patch was created on 2000-Sept-14. It was updated to work with the current CVS head.</para></item.e></enumerate>
<para>The latest patch for this tip 62 is available at:</para>
<para> <url ref="http://www.employees.org/~hlavana/tcl/"/></para>
<para>The main changes for the patch are described in brief next.</para>
<para>Two new flags have been defined in tcl.h:</para>
<verbatim><vline encoding='base64'>ICAjZGVmaW5lIFRDTF9UUkFDRV9FTlRFUl9FWEVDICAgICAgICAgIDE=</vline><vline encoding='base64'>ICAjZGVmaW5lIFRDTF9UUkFDRV9MRUFWRV9FWEVDICAgICAgICAgIDI=</vline></verbatim>
<para>These flag values are passed to Tcl_CreateObjTrace and used by command execution traces. More internal flags for slots 4, 8, 15, 16, 32 are defined in tclCmdMZ.c file: TCL_TRACE_ENTER_DURING_EXEC, TCL_TRACE_LEAVE_DURING_EXEC, TCL_TRACE_ANY_EXEC, TCL_TRACE_EXEC_IN_PROGRESS and TCL_TRACE_EXEC_DIRECT.</para>
<para>A new function TclTraceExecutionObjCmd function implements the <emph style="italic">trace {add|remove|list} execution ...</emph> subcommands. A new function TclCheckExecutionTraces is defined to check for traces added by the execution subcommand. A new function TclCheckInterpTraces is defined to check for global traces added by the Tcl_CreateObjTrace command. The TclEvalObjvInternal has been modified to call the above two functions before as well as after the original command is executed. A new function TraceExecutionProc is invoked, when necessary, to execute the actual trace command in the interpreter.</para>
<para>A new structure ActiveInterpTrace has been defined for internal use so that it behaves reasonably when traces are deleted while active. In tclVar.c file, the function CallTraces has been renamed to CallVarTraces and iPtr-&gt;activeTracePtr has been renamed to iPtr-&gt;activeTraceVarPtr.</para>
<para>An additional check for (tracePtr-&gt;level == 0) has been added in Tcl_EvalObjv and TclExecuteByteCode functions, so as to enable command tracing at all levels.</para>
</section>
<section title="Benchmark Results">
<para>The benchmark results corresponds to <emph style="italic">Version 1.1</emph> of the reference implementation.</para>
<para>One potential objection to this TIP could be that it may affect the performance of the Tcl-core. Therefore, I have run the <emph style="italic">runbench.tcl</emph> script from the tclbench module for comparison on a Sun Ultra5, Solaris2.6 machine. The results have been posted at <url ref="http://sf.net/tracker/?func=detail&amp;aid=462580&amp;group_id=10894&amp;atid=360894"/></para>
<para>These results show that there is hardly any performance hit, if any, by addition of this feature. Of course when you activate a trace on a command, then you will see a performance hit, but since primary uses of traces will be in profiling and debugging, that isn&apos;t an issue.</para>
</section>
<section title="Future Scope">
<para>This proposal does not allow for the trace invocation <emph style="italic">command</emph> to do the following:</para>
<enumerate><item.e index='1'><para>modify the number of arguments passed to <emph style="italic">name</emph></para></item.e><item.e index='2'><para>modify the value of arguments passed to <emph style="italic">name</emph></para></item.e><item.e index='3'><para>modify the result value and result code returned by <emph style="italic">name</emph></para></item.e><item.e index='4'><para>skip invocation of <emph style="italic">name</emph> altogether if desired.</para></item.e></enumerate>
<para>Consider the example of adding a sub-command &quot;string reverse ...&quot; as shown on <url ref="http://mini.net/tcl/1570.html."/> Instead of using the rename command, it should be possible to use the trace command to do the same, as follows:</para>
<verbatim><vline encoding='base64'>ICAgIHRyYWNlIGFkZCBleGVjdXRpb24gc3RyaW5nIHtlbnRlcn0gezo6bXlsaWI6OnN0cmluZ3h9</vline><vline encoding='base64'>ICAgIHByb2MgOjpteWxpYjo6c3RyaW5neCB7c3ViY21kIGFyZ3N9IHs=</vline><vline encoding='base64'>ICAgICAgICBzd2l0Y2ggLWV4YWN0IC0tICRzdWJjbWQgew==</vline><vline encoding='base64'>ICAgICAgICAgICAgInJldmVyc2UiIHs=</vline><vline encoding='base64'>ICAgICAgICAgICAgICAgICMgSG1tIC4uLiB0aGlzIGlzIG15IHN1YmNvbW1hbmQsIHByb2Nlc3MgaXQgaGVyZQ==</vline><vline encoding='base64'>ICAgICAgICAgICAgICAgIHNldCByZXR1cm5WYWx1ZSBbY29kZV90b19yZXZlcnNlX3N0cmluZ192YWx1ZV0=</vline><vline encoding='base64'></vline><vline encoding='base64'>ICAgICAgICAgICAgICAgICMgV2UgbmVlZCBhIG1lY2hhbnNpbSB0byByZXR1cm4gaW1tZWRpYXRlbHkgaGVyZQ==</vline><vline encoding='base64'>ICAgICAgICAgICAgICAgICMgd2l0aCB0aGUgcHJvY2Vzc2VkIHJlc3VsdHMgYW5kIGFuIGFwcHJvcHJpYXRl</vline><vline encoding='base64'>ICAgICAgICAgICAgICAgICMgY29kZSB2YWx1ZSBhbmQgbm90IGludm9rZSB0aGUgb3JpZ2luYWwgc3RyaW5nIGNvbW1hbmQu</vline><vline encoding='base64'>ICAgICAgICAgICAgfQ==</vline><vline encoding='base64'>ICAgICAgICAgICAgZGVmYXVsdCB7</vline><vline encoding='base64'>ICAgICAgICAgICAgICAgICMgVGhpcyBpcyBwcm9iYWJseSBhIHZhaWxkIHN1YmNvbW1hbmQsIHNvIGRvIG5vdGhpbmc=</vline><vline encoding='base64'>ICAgICAgICAgICAgICAgICMgYW5kIGxldCB0aGUgb3JpZ2luYWwgc3RyaW5nIGNvbW1hbmQgaGFuZGxlIGl0</vline><vline encoding='base64'>ICAgICAgICAgICAgfQ==</vline><vline encoding='base64'>ICAgICAgICB9</vline><vline encoding='base64'>ICAgIH0=</vline></verbatim>
</section>
<section title="Copyright">
<para>This document has been placed in the public domain.</para>
</section>
</body></TIP>
