diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 19:43:11 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 19:43:11 +0000 |
commit | fc22b3d6507c6745911b9dfcc68f1e665ae13dbc (patch) | |
tree | ce1e3bce06471410239a6f41282e328770aa404a /upstream/mageia-cauldron/man3pm/Devel::Peek.3pm | |
parent | Initial commit. (diff) | |
download | manpages-l10n-fc22b3d6507c6745911b9dfcc68f1e665ae13dbc.tar.xz manpages-l10n-fc22b3d6507c6745911b9dfcc68f1e665ae13dbc.zip |
Adding upstream version 4.22.0.upstream/4.22.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'upstream/mageia-cauldron/man3pm/Devel::Peek.3pm')
-rw-r--r-- | upstream/mageia-cauldron/man3pm/Devel::Peek.3pm | 578 |
1 files changed, 578 insertions, 0 deletions
diff --git a/upstream/mageia-cauldron/man3pm/Devel::Peek.3pm b/upstream/mageia-cauldron/man3pm/Devel::Peek.3pm new file mode 100644 index 00000000..3ae34251 --- /dev/null +++ b/upstream/mageia-cauldron/man3pm/Devel::Peek.3pm @@ -0,0 +1,578 @@ +.\" -*- mode: troff; coding: utf-8 -*- +.\" Automatically generated by Pod::Man 5.01 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" \*(C` and \*(C' are quotes in nroff, nothing in troff, for use with C<>. +.ie n \{\ +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Devel::Peek 3pm" +.TH Devel::Peek 3pm 2023-11-28 "perl v5.38.2" "Perl Programmers Reference Guide" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH NAME +Devel::Peek \- A data debugging tool for the XS programmer +.SH SYNOPSIS +.IX Header "SYNOPSIS" +.Vb 7 +\& use Devel::Peek; +\& Dump( $a ); +\& Dump( $a, 5 ); +\& Dump( @a ); +\& Dump( %h ); +\& DumpArray( 5, $a, $b, ... ); +\& mstat "Point 5"; +\& +\& use Devel::Peek \*(Aq:opd=st\*(Aq; +.Ve +.SH DESCRIPTION +.IX Header "DESCRIPTION" +Devel::Peek contains functions which allows raw Perl datatypes to be +manipulated from a Perl script. This is used by those who do XS programming +to check that the data they are sending from C to Perl looks as they think +it should look. The trick, then, is to know what the raw datatype is +supposed to look like when it gets to Perl. This document offers some tips +and hints to describe good and bad raw data. +.PP +It is very possible that this document will fall far short of being useful +to the casual reader. The reader is expected to understand the material in +the first few sections of perlguts. +.PP +Devel::Peek supplies a \f(CWDump()\fR function which can dump a raw Perl +datatype, and \f(CWmstat("marker")\fR function to report on memory usage +(if perl is compiled with corresponding option). The function +\&\fBDeadCode()\fR provides statistics on the data "frozen" into inactive +\&\f(CW\*(C`CV\*(C'\fR. Devel::Peek also supplies \f(CWSvREFCNT()\fR which can query reference +counts on SVs. This document will take a passive, and safe, approach +to data debugging and for that it will describe only the \f(CWDump()\fR +function. +.PP +All output is to STDERR. +.PP +The \f(CWDump()\fR function takes one or two arguments: something to dump, and +an optional limit for recursion and array elements (default is 4). The +first argument is evaluated in rvalue scalar context, with exceptions for +\&\f(CW@array\fR and \f(CW%hash\fR, which dump the array or hash itself. So \f(CW\*(C`Dump @array\*(C'\fR +works, as does \f(CW\*(C`Dump $foo\*(C'\fR. And \f(CW\*(C`Dump pos\*(C'\fR will call \f(CW\*(C`pos\*(C'\fR in rvalue +context, whereas \f(CW\*(C`Dump ${\epos}\*(C'\fR will call it in lvalue context. +.PP +Function \f(CWDumpArray()\fR allows dumping of multiple values (useful when you +need to analyze returns of functions). +.PP +The global variable \f(CW$Devel::Peek::pv_limit\fR can be set to limit the +number of character printed in various string values. Setting it to 0 +means no limit. +.PP +If \f(CW\*(C`use Devel::Peek\*(C'\fR directive has a \f(CW\*(C`:opd=FLAGS\*(C'\fR argument, +this switches on debugging of opcode dispatch. \f(CW\*(C`FLAGS\*(C'\fR should be a +combination of \f(CW\*(C`s\*(C'\fR, \f(CW\*(C`t\*(C'\fR, and \f(CW\*(C`P\*(C'\fR (see +\&\fB\-D\fR flags in perlrun). +.PP +\&\f(CW\*(C`:opd\*(C'\fR is a shortcut for \f(CW\*(C`:opd=st\*(C'\fR. +.SS "Runtime debugging" +.IX Subsection "Runtime debugging" +\&\f(CWCvGV($cv)\fR return one of the globs associated to a subroutine reference \f(CW$cv\fR. +.PP +\&\fBdebug_flags()\fR returns a string representation of \f(CW$^D\fR (similar to +what is allowed for \fB\-D\fR flag). When called with a numeric argument, +sets $^D to the corresponding value. When called with an argument of +the form \f(CW"flags\-flags"\fR, set on/off bits of \f(CW$^D\fR corresponding to +letters before/after \f(CW\*(C`\-\*(C'\fR. (The returned value is for \f(CW$^D\fR before +the modification.) +.PP +\&\fBrunops_debug()\fR returns true if the current \fIopcode dispatcher\fR is the +debugging one. When called with an argument, switches to debugging or +non-debugging dispatcher depending on the argument (active for +newly-entered subs/etc only). (The returned value is for the dispatcher before the modification.) +.SS "Memory footprint debugging" +.IX Subsection "Memory footprint debugging" +When perl is compiled with support for memory footprint debugging +(default with Perl's \fBmalloc()\fR), Devel::Peek provides an access to this API. +.PP +Use \fBmstat()\fR function to emit a memory state statistic to the terminal. +For more information on the format of output of \fBmstat()\fR see +"Using \f(CW$ENV\fR{PERL_DEBUG_MSTATS}" in perldebguts. +.PP +Three additional functions allow access to this statistic from Perl. +First, use \f(CWmstats_fillhash(%hash)\fR to get the information contained +in the output of \fBmstat()\fR into \f(CW%hash\fR. The field of this hash are +.PP +.Vb 3 +\& minbucket nbuckets sbrk_good sbrk_slack sbrked_remains sbrks +\& start_slack topbucket topbucket_ev topbucket_odd total total_chain +\& total_sbrk totfree +.Ve +.PP +Two additional fields \f(CW\*(C`free\*(C'\fR, \f(CW\*(C`used\*(C'\fR contain array references which +provide per-bucket count of free and used chunks. Two other fields +\&\f(CW\*(C`mem_size\*(C'\fR, \f(CW\*(C`available_size\*(C'\fR contain array references which provide +the information about the allocated size and usable size of chunks in +each bucket. Again, see "Using \f(CW$ENV\fR{PERL_DEBUG_MSTATS}" in perldebguts +for details. +.PP +Keep in mind that only the first several "odd-numbered" buckets are +used, so the information on size of the "odd-numbered" buckets which are +not used is probably meaningless. +.PP +The information in +.PP +.Vb 1 +\& mem_size available_size minbucket nbuckets +.Ve +.PP +is the property of a particular build of perl, and does not depend on +the current process. If you do not provide the optional argument to +the functions \fBmstats_fillhash()\fR, \fBfill_mstats()\fR, \fBmstats2hash()\fR, then +the information in fields \f(CW\*(C`mem_size\*(C'\fR, \f(CW\*(C`available_size\*(C'\fR is not +updated. +.PP +\&\f(CWfill_mstats($buf)\fR is a much cheaper call (both speedwise and +memory-wise) which collects the statistic into \f(CW$buf\fR in +machine-readable form. At a later moment you may need to call +\&\f(CW\*(C`mstats2hash($buf, %hash)\*(C'\fR to use this information to fill \f(CW%hash\fR. +.PP +All three APIs \f(CWfill_mstats($buf)\fR, \f(CWmstats_fillhash(%hash)\fR, and +\&\f(CW\*(C`mstats2hash($buf, %hash)\*(C'\fR are designed to allocate no memory if used +\&\fIthe second time\fR on the same \f(CW$buf\fR and/or \f(CW%hash\fR. +.PP +So, if you want to collect memory info in a cycle, you may call +.PP +.Vb 3 +\& $#buf = 999; +\& fill_mstats($_) for @buf; +\& mstats_fillhash(%report, 1); # Static info too +\& +\& foreach (@buf) { +\& # Do something... +\& fill_mstats $_; # Collect statistic +\& } +\& foreach (@buf) { +\& mstats2hash($_, %report); # Preserve static info +\& # Do something with %report +\& } +.Ve +.SH EXAMPLES +.IX Header "EXAMPLES" +The following examples don't attempt to show everything as that would be a +monumental task, and, frankly, we don't want this manpage to be an internals +document for Perl. The examples do demonstrate some basics of the raw Perl +datatypes, and should suffice to get most determined people on their way. +There are no guidewires or safety nets, nor blazed trails, so be prepared to +travel alone from this point and on and, if at all possible, don't fall into +the quicksand (it's bad for business). +.PP +Oh, one final bit of advice: take perlguts with you. When you return we +expect to see it well-thumbed. +.SS "A simple scalar string" +.IX Subsection "A simple scalar string" +Let's begin by looking a simple scalar which is holding a string. +.PP +.Vb 3 +\& use Devel::Peek; +\& $a = 42; $a = "hello"; +\& Dump $a; +.Ve +.PP +The output: +.PP +.Vb 7 +\& SV = PVIV(0xbc288) at 0xbe9a8 +\& REFCNT = 1 +\& FLAGS = (POK,pPOK) +\& IV = 42 +\& PV = 0xb2048 "hello"\e0 +\& CUR = 5 +\& LEN = 8 +.Ve +.PP +This says \f(CW$a\fR is an SV, a scalar. The scalar type is a PVIV, which is +capable of holding an integer (IV) and/or a string (PV) value. The scalar's +head is allocated at address 0xbe9a8, while the body is at 0xbc288. +Its reference count is 1. It has the \f(CW\*(C`POK\*(C'\fR flag set, meaning its +current PV field is valid. Because POK is set we look at the PV item +to see what is in the scalar. The \e0 at the end indicate that this +PV is properly NUL-terminated. +Note that the IV field still contains its old numeric value, but because +FLAGS doesn't have IOK set, we must ignore the IV item. +CUR indicates the number of characters in the PV. LEN indicates the +number of bytes allocated for the PV (at least one more than CUR, because +LEN includes an extra byte for the end-of-string marker, then usually +rounded up to some efficient allocation unit). +.SS "A simple scalar number" +.IX Subsection "A simple scalar number" +If the scalar contains a number the raw SV will be leaner. +.PP +.Vb 3 +\& use Devel::Peek; +\& $a = 42; +\& Dump $a; +.Ve +.PP +The output: +.PP +.Vb 4 +\& SV = IV(0xbc818) at 0xbe9a8 +\& REFCNT = 1 +\& FLAGS = (IOK,pIOK) +\& IV = 42 +.Ve +.PP +This says \f(CW$a\fR is an SV, a scalar. The scalar is an IV, a number. Its +reference count is 1. It has the \f(CW\*(C`IOK\*(C'\fR flag set, meaning it is currently +being evaluated as a number. Because IOK is set we look at the IV item to +see what is in the scalar. +.SS "A simple scalar with an extra reference" +.IX Subsection "A simple scalar with an extra reference" +If the scalar from the previous example had an extra reference: +.PP +.Vb 4 +\& use Devel::Peek; +\& $a = 42; +\& $b = \e$a; +\& Dump $a; +.Ve +.PP +The output: +.PP +.Vb 4 +\& SV = IV(0xbe860) at 0xbe9a8 +\& REFCNT = 2 +\& FLAGS = (IOK,pIOK) +\& IV = 42 +.Ve +.PP +Notice that this example differs from the previous example only in its +reference count. Compare this to the next example, where we dump \f(CW$b\fR +instead of \f(CW$a\fR. +.SS "A reference to a simple scalar" +.IX Subsection "A reference to a simple scalar" +This shows what a reference looks like when it references a simple scalar. +.PP +.Vb 4 +\& use Devel::Peek; +\& $a = 42; +\& $b = \e$a; +\& Dump $b; +.Ve +.PP +The output: +.PP +.Vb 8 +\& SV = IV(0xf041c) at 0xbe9a0 +\& REFCNT = 1 +\& FLAGS = (ROK) +\& RV = 0xbab08 +\& SV = IV(0xbe860) at 0xbe9a8 +\& REFCNT = 2 +\& FLAGS = (IOK,pIOK) +\& IV = 42 +.Ve +.PP +Starting from the top, this says \f(CW$b\fR is an SV. The scalar is an IV, +which is capable of holding an integer or reference value. +It has the \f(CW\*(C`ROK\*(C'\fR flag set, meaning it is a reference (rather than an +integer or string). Notice that Dump +follows the reference and shows us what \f(CW$b\fR was referencing. We see the +same \f(CW$a\fR that we found in the previous example. +.PP +Note that the value of \f(CW\*(C`RV\*(C'\fR coincides with the numbers we see when we +stringify \f(CW$b\fR. The addresses inside \fBIV()\fR are addresses of +\&\f(CW\*(C`X***\*(C'\fR structures which hold the current state of an \f(CW\*(C`SV\*(C'\fR. This +address may change during lifetime of an SV. +.SS "A reference to an array" +.IX Subsection "A reference to an array" +This shows what a reference to an array looks like. +.PP +.Vb 3 +\& use Devel::Peek; +\& $a = [42]; +\& Dump $a; +.Ve +.PP +The output: +.PP +.Vb 10 +\& SV = IV(0xc85998) at 0xc859a8 +\& REFCNT = 1 +\& FLAGS = (ROK) +\& RV = 0xc70de8 +\& SV = PVAV(0xc71e10) at 0xc70de8 +\& REFCNT = 1 +\& FLAGS = () +\& ARRAY = 0xc7e820 +\& FILL = 0 +\& MAX = 0 +\& FLAGS = (REAL) +\& Elt No. 0 +\& SV = IV(0xc70f88) at 0xc70f98 +\& REFCNT = 1 +\& FLAGS = (IOK,pIOK) +\& IV = 42 +.Ve +.PP +This says \f(CW$a\fR is a reference (ROK), which points to +another SV which is a PVAV, an array. The array has one element, +element zero, which is another SV. The field \f(CW\*(C`FILL\*(C'\fR above indicates +the last element in the array, similar to \f(CW\*(C`$#$a\*(C'\fR. +.PP +If \f(CW$a\fR pointed to an array of two elements then we would see the +following. +.PP +.Vb 3 +\& use Devel::Peek \*(AqDump\*(Aq; +\& $a = [42,24]; +\& Dump $a; +.Ve +.PP +The output: +.PP +.Vb 10 +\& SV = IV(0x158c998) at 0x158c9a8 +\& REFCNT = 1 +\& FLAGS = (ROK) +\& RV = 0x1577de8 +\& SV = PVAV(0x1578e10) at 0x1577de8 +\& REFCNT = 1 +\& FLAGS = () +\& ARRAY = 0x1585820 +\& FILL = 1 +\& MAX = 1 +\& FLAGS = (REAL) +\& Elt No. 0 +\& SV = IV(0x1577f88) at 0x1577f98 +\& REFCNT = 1 +\& FLAGS = (IOK,pIOK) +\& IV = 42 +\& Elt No. 1 +\& SV = IV(0x158be88) at 0x158be98 +\& REFCNT = 1 +\& FLAGS = (IOK,pIOK) +\& IV = 24 +.Ve +.PP +Note that \f(CW\*(C`Dump\*(C'\fR will not report \fIall\fR the elements in the array, +only several first (depending on how deep it already went into the +report tree). +.SS "A reference to a hash" +.IX Subsection "A reference to a hash" +The following shows the raw form of a reference to a hash. +.PP +.Vb 3 +\& use Devel::Peek; +\& $a = {hello=>42}; +\& Dump $a; +.Ve +.PP +The output: +.PP +.Vb 10 +\& SV = IV(0x55cb50b50fb0) at 0x55cb50b50fc0 +\& REFCNT = 1 +\& FLAGS = (ROK) +\& RV = 0x55cb50b2b758 +\& SV = PVHV(0x55cb50b319c0) at 0x55cb50b2b758 +\& REFCNT = 1 +\& FLAGS = (SHAREKEYS) +\& ARRAY = 0x55cb50b941a0 (0:7, 1:1) +\& hash quality = 100.0% +\& KEYS = 1 +\& FILL = 1 +\& MAX = 7 +\& Elt "hello" HASH = 0x3128ece4 +\& SV = IV(0x55cb50b464f8) at 0x55cb50b46508 +\& REFCNT = 1 +\& FLAGS = (IOK,pIOK) +\& IV = 42 +.Ve +.PP +This shows \f(CW$a\fR is a reference pointing to an SV. That SV is a PVHV, a hash. +.PP +The "quality" of a hash is defined as the total number of comparisons needed +to access every element once, relative to the expected number needed for a +random hash. The value can go over 100%. +.PP +The total number of comparisons is equal to the sum of the squares of the +number of entries in each bucket. For a random hash of \f(CW\*(C`<n\*(C'\fR> keys into +\&\f(CW\*(C`<k\*(C'\fR> buckets, the expected value is: +.PP +.Vb 1 +\& n + n(n\-1)/2k +.Ve +.SS "Dumping a large array or hash" +.IX Subsection "Dumping a large array or hash" +The \f(CWDump()\fR function, by default, dumps up to 4 elements from a +toplevel array or hash. This number can be increased by supplying a +second argument to the function. +.PP +.Vb 3 +\& use Devel::Peek; +\& $a = [10,11,12,13,14]; +\& Dump $a; +.Ve +.PP +Notice that \f(CWDump()\fR prints only elements 10 through 13 in the above code. +The following code will print all of the elements. +.PP +.Vb 3 +\& use Devel::Peek \*(AqDump\*(Aq; +\& $a = [10,11,12,13,14]; +\& Dump $a, 5; +.Ve +.SS "A reference to an SV which holds a C pointer" +.IX Subsection "A reference to an SV which holds a C pointer" +This is what you really need to know as an XS programmer, of course. When +an XSUB returns a pointer to a C structure that pointer is stored in an SV +and a reference to that SV is placed on the XSUB stack. So the output from +an XSUB which uses something like the T_PTROBJ map might look something like +this: +.PP +.Vb 11 +\& SV = IV(0xf381c) at 0xc859a8 +\& REFCNT = 1 +\& FLAGS = (ROK) +\& RV = 0xb8ad8 +\& SV = PVMG(0xbb3c8) at 0xc859a0 +\& REFCNT = 1 +\& FLAGS = (OBJECT,IOK,pIOK) +\& IV = 729160 +\& NV = 0 +\& PV = 0 +\& STASH = 0xc1d10 "CookBookB::Opaque" +.Ve +.PP +This shows that we have an SV which is a reference, which points at another +SV. In this case that second SV is a PVMG, a blessed scalar. Because it is +blessed it has the \f(CW\*(C`OBJECT\*(C'\fR flag set. Note that an SV which holds a C +pointer also has the \f(CW\*(C`IOK\*(C'\fR flag set. The \f(CW\*(C`STASH\*(C'\fR is set to the package +name which this SV was blessed into. +.PP +The output from an XSUB which uses something like the T_PTRREF map, which +doesn't bless the object, might look something like this: +.PP +.Vb 10 +\& SV = IV(0xf381c) at 0xc859a8 +\& REFCNT = 1 +\& FLAGS = (ROK) +\& RV = 0xb8ad8 +\& SV = PVMG(0xbb3c8) at 0xc859a0 +\& REFCNT = 1 +\& FLAGS = (IOK,pIOK) +\& IV = 729160 +\& NV = 0 +\& PV = 0 +.Ve +.SS "A reference to a subroutine" +.IX Subsection "A reference to a subroutine" +Looks like this: +.PP +.Vb 10 +\& SV = IV(0x24d2dd8) at 0x24d2de8 +\& REFCNT = 1 +\& FLAGS = (TEMP,ROK) +\& RV = 0x24e79d8 +\& SV = PVCV(0x24e5798) at 0x24e79d8 +\& REFCNT = 2 +\& FLAGS = () +\& COMP_STASH = 0x22c9c50 "main" +\& START = 0x22eed60 ===> 0 +\& ROOT = 0x22ee490 +\& GVGV::GV = 0x22de9d8 "MY" :: "top_targets" +\& FILE = "(eval 5)" +\& DEPTH = 0 +\& FLAGS = 0x0 +\& OUTSIDE_SEQ = 93 +\& PADLIST = 0x22e9ed8 +\& PADNAME = 0x22e9ec0(0x22eed00) PAD = 0x22e9ea8(0x22eecd0) +\& OUTSIDE = 0x22c9fb0 (MAIN) +.Ve +.PP +This shows that +.IP \(bu 4 +the subroutine is not an XSUB (since \f(CW\*(C`START\*(C'\fR and \f(CW\*(C`ROOT\*(C'\fR are +non-zero, and \f(CW\*(C`XSUB\*(C'\fR is not listed, and is thus null); +.IP \(bu 4 +that it was compiled in the package \f(CW\*(C`main\*(C'\fR; +.IP \(bu 4 +under the name \f(CW\*(C`MY::top_targets\*(C'\fR; +.IP \(bu 4 +inside a 5th eval in the program; +.IP \(bu 4 +it is not currently executed (because \f(CW\*(C`DEPTH\*(C'\fR is 0); +.IP \(bu 4 +it has no prototype (\f(CW\*(C`PROTOTYPE\*(C'\fR field is missing). +.SH EXPORTS +.IX Header "EXPORTS" +\&\f(CW\*(C`Dump\*(C'\fR, \f(CW\*(C`mstat\*(C'\fR, \f(CW\*(C`DeadCode\*(C'\fR, \f(CW\*(C`DumpArray\*(C'\fR, \f(CW\*(C`DumpWithOP\*(C'\fR and +\&\f(CW\*(C`DumpProg\*(C'\fR, \f(CW\*(C`fill_mstats\*(C'\fR, \f(CW\*(C`mstats_fillhash\*(C'\fR, \f(CW\*(C`mstats2hash\*(C'\fR by +default. Additionally available \f(CW\*(C`SvREFCNT\*(C'\fR, \f(CW\*(C`SvREFCNT_inc\*(C'\fR and +\&\f(CW\*(C`SvREFCNT_dec\*(C'\fR. +.SH BUGS +.IX Header "BUGS" +Readers have been known to skip important parts of perlguts, causing much +frustration for all. +.SH AUTHOR +.IX Header "AUTHOR" +Ilya Zakharevich ilya@math.ohio\-state.edu +.PP +Copyright (c) 1995\-98 Ilya Zakharevich. All rights reserved. +This program is free software; you can redistribute it and/or +modify it under the same terms as Perl itself. +.PP +Author of this software makes no claim whatsoever about suitability, +reliability, edability, editability or usability of this product, and +should not be kept liable for any damage resulting from the use of +it. If you can use it, you are in luck, if not, I should not be kept +responsible. Keep a handy copy of your backup tape at hand. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +perlguts, and perlguts, again. |