summaryrefslogtreecommitdiffstats
path: root/upstream/debian-bookworm/man1/perldebtut.1
diff options
context:
space:
mode:
Diffstat (limited to 'upstream/debian-bookworm/man1/perldebtut.1')
-rw-r--r--upstream/debian-bookworm/man1/perldebtut.1887
1 files changed, 887 insertions, 0 deletions
diff --git a/upstream/debian-bookworm/man1/perldebtut.1 b/upstream/debian-bookworm/man1/perldebtut.1
new file mode 100644
index 00000000..02c4f2c2
--- /dev/null
+++ b/upstream/debian-bookworm/man1/perldebtut.1
@@ -0,0 +1,887 @@
+.\" Automatically generated by Pod::Man 4.14 (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
+..
+.\" Set up some character translations and predefined strings. \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote. \*(C+ will
+.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+. ds -- \(*W-
+. ds PI pi
+. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+. ds L" ""
+. ds R" ""
+. ds C` ""
+. ds C' ""
+'br\}
+.el\{\
+. ds -- \|\(em\|
+. ds PI \(*p
+. ds L" ``
+. ds R" ''
+. 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 "PERLDEBTUT 1"
+.TH PERLDEBTUT 1 "2023-11-25" "perl v5.36.0" "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"
+perldebtut \- Perl debugging tutorial
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+A (very) lightweight introduction in the use of the perl debugger, and a
+pointer to existing, deeper sources of information on the subject of debugging
+perl programs.
+.PP
+There's an extraordinary number of people out there who don't appear to know
+anything about using the perl debugger, though they use the language every
+day.
+This is for them.
+.SH "use strict"
+.IX Header "use strict"
+First of all, there's a few things you can do to make your life a lot more
+straightforward when it comes to debugging perl programs, without using the
+debugger at all. To demonstrate, here's a simple script, named \*(L"hello\*(R", with
+a problem:
+.PP
+.Vb 1
+\& #!/usr/bin/perl
+\&
+\& $var1 = \*(AqHello World\*(Aq; # always wanted to do that :\-)
+\& $var2 = "$varl\en";
+\&
+\& print $var2;
+\& exit;
+.Ve
+.PP
+While this compiles and runs happily, it probably won't do what's expected,
+namely it doesn't print \*(L"Hello World\en\*(R" at all; It will on the other hand do
+exactly what it was told to do, computers being a bit that way inclined. That
+is, it will print out a newline character, and you'll get what looks like a
+blank line. It looks like there's 2 variables when (because of the typo)
+there's really 3:
+.PP
+.Vb 3
+\& $var1 = \*(AqHello World\*(Aq;
+\& $varl = undef;
+\& $var2 = "\en";
+.Ve
+.PP
+To catch this kind of problem, we can force each variable to be declared
+before use by pulling in the strict module, by putting 'use strict;' after the
+first line of the script.
+.PP
+Now when you run it, perl complains about the 3 undeclared variables and we
+get four error messages because one variable is referenced twice:
+.PP
+.Vb 5
+\& Global symbol "$var1" requires explicit package name at ./t1 line 4.
+\& Global symbol "$var2" requires explicit package name at ./t1 line 5.
+\& Global symbol "$varl" requires explicit package name at ./t1 line 5.
+\& Global symbol "$var2" requires explicit package name at ./t1 line 7.
+\& Execution of ./hello aborted due to compilation errors.
+.Ve
+.PP
+Luvverly! and to fix this we declare all variables explicitly and now our
+script looks like this:
+.PP
+.Vb 2
+\& #!/usr/bin/perl
+\& use strict;
+\&
+\& my $var1 = \*(AqHello World\*(Aq;
+\& my $varl = undef;
+\& my $var2 = "$varl\en";
+\&
+\& print $var2;
+\& exit;
+.Ve
+.PP
+We then do (always a good idea) a syntax check before we try to run it again:
+.PP
+.Vb 2
+\& > perl \-c hello
+\& hello syntax OK
+.Ve
+.PP
+And now when we run it, we get \*(L"\en\*(R" still, but at least we know why. Just
+getting this script to compile has exposed the '$varl' (with the letter 'l')
+variable, and simply changing \f(CW$varl\fR to \f(CW$var1\fR solves the problem.
+.SH "Looking at data and \-w and v"
+.IX Header "Looking at data and -w and v"
+Ok, but how about when you want to really see your data, what's in that
+dynamic variable, just before using it?
+.PP
+.Vb 2
+\& #!/usr/bin/perl
+\& use strict;
+\&
+\& my $key = \*(Aqwelcome\*(Aq;
+\& my %data = (
+\& \*(Aqthis\*(Aq => qw(that),
+\& \*(Aqtom\*(Aq => qw(and jerry),
+\& \*(Aqwelcome\*(Aq => q(Hello World),
+\& \*(Aqzip\*(Aq => q(welcome),
+\& );
+\& my @data = keys %data;
+\&
+\& print "$data{$key}\en";
+\& exit;
+.Ve
+.PP
+Looks \s-1OK,\s0 after it's been through the syntax check (perl \-c scriptname), we
+run it and all we get is a blank line again! Hmmmm.
+.PP
+One common debugging approach here, would be to liberally sprinkle a few print
+statements, to add a check just before we print out our data, and another just
+after:
+.PP
+.Vb 3
+\& print "All OK\en" if grep($key, keys %data);
+\& print "$data{$key}\en";
+\& print "done: \*(Aq$data{$key}\*(Aq\en";
+.Ve
+.PP
+And try again:
+.PP
+.Vb 2
+\& > perl data
+\& All OK
+\&
+\& done: \*(Aq\*(Aq
+.Ve
+.PP
+After much staring at the same piece of code and not seeing the wood for the
+trees for some time, we get a cup of coffee and try another approach. That
+is, we bring in the cavalry by giving perl the '\fB\-d\fR' switch on the command
+line:
+.PP
+.Vb 2
+\& > perl \-d data
+\& Default die handler restored.
+\&
+\& Loading DB routines from perl5db.pl version 1.07
+\& Editor support available.
+\&
+\& Enter h or \`h h\*(Aq for help, or \`man perldebug\*(Aq for more help.
+\&
+\& main::(./data:4): my $key = \*(Aqwelcome\*(Aq;
+.Ve
+.PP
+Now, what we've done here is to launch the built-in perl debugger on our
+script. It's stopped at the first line of executable code and is waiting for
+input.
+.PP
+Before we go any further, you'll want to know how to quit the debugger: use
+just the letter '\fBq\fR', not the words 'quit' or 'exit':
+.PP
+.Vb 2
+\& DB<1> q
+\& >
+.Ve
+.PP
+That's it, you're back on home turf again.
+.SH "help"
+.IX Header "help"
+Fire the debugger up again on your script and we'll look at the help menu.
+There's a couple of ways of calling help: a simple '\fBh\fR' will get the summary
+help list, '\fB|h\fR' (pipe-h) will pipe the help through your pager (which is
+(probably 'more' or 'less'), and finally, '\fBh h\fR' (h\-space-h) will give you
+the entire help screen. Here is the summary page:
+.PP
+D\fB1\fRh
+.PP
+.Vb 10
+\& List/search source lines: Control script execution:
+\& l [ln|sub] List source code T Stack trace
+\& \- or . List previous/current line s [expr] Single step
+\& [in expr]
+\& v [line] View around line n [expr] Next, steps over
+\& subs
+\& f filename View source in file <CR/Enter> Repeat last n or s
+\& /pattern/ ?patt? Search forw/backw r Return from
+\& subroutine
+\& M Show module versions c [ln|sub] Continue until
+\& position
+\& Debugger controls: L List break/watch/
+\& actions
+\& o [...] Set debugger options t [expr] Toggle trace
+\& [trace expr]
+\& <[<]|{[{]|>[>] [cmd] Do pre/post\-prompt b [ln|event|sub] [cnd] Set
+\& breakpoint
+\& ! [N|pat] Redo a previous command B ln|* Delete a/all
+\& breakpoints
+\& H [\-num] Display last num commands a [ln] cmd Do cmd before line
+\& = [a val] Define/list an alias A ln|* Delete a/all
+\& actions
+\& h [db_cmd] Get help on command w expr Add a watch
+\& expression
+\& h h Complete help page W expr|* Delete a/all watch
+\& exprs
+\& |[|]db_cmd Send output to pager ![!] syscmd Run cmd in a
+\& subprocess
+\& q or ^D Quit R Attempt a restart
+\& Data Examination: expr Execute perl code, also see: s,n,t expr
+\& x|m expr Evals expr in list context, dumps the result or lists
+\& methods.
+\& p expr Print expression (uses script\*(Aqs current package).
+\& S [[!]pat] List subroutine names [not] matching pattern
+\& V [Pk [Vars]] List Variables in Package. Vars can be ~pattern or
+\& !pattern.
+\& X [Vars] Same as "V current_package [Vars]".
+\& y [n [Vars]] List lexicals in higher scope <n>. Vars same as V.
+\& For more help, type h cmd_letter, or run man perldebug for all docs.
+.Ve
+.PP
+More confusing options than you can shake a big stick at! It's not as bad as
+it looks and it's very useful to know more about all of it, and fun too!
+.PP
+There's a couple of useful ones to know about straight away. You wouldn't
+think we're using any libraries at all at the moment, but '\fBM\fR' will show
+which modules are currently loaded, and their version number, while '\fBm\fR'
+will show the methods, and '\fBS\fR' shows all subroutines (by pattern) as
+shown below. '\fBV\fR' and '\fBX\fR' show variables in the program by package
+scope and can be constrained by pattern.
+.PP
+.Vb 5
+\& DB<2>S str
+\& dumpvar::stringify
+\& strict::bits
+\& strict::import
+\& strict::unimport
+.Ve
+.PP
+Using 'X' and cousins requires you not to use the type identifiers ($@%), just
+the 'name':
+.PP
+.Vb 2
+\& DM<3>X ~err
+\& FileHandle(stderr) => fileno(2)
+.Ve
+.PP
+Remember we're in our tiny program with a problem, we should have a look at
+where we are, and what our data looks like. First of all let's view some code
+at our present position (the first line of code in this case), via '\fBv\fR':
+.PP
+.Vb 11
+\& DB<4> v
+\& 1 #!/usr/bin/perl
+\& 2: use strict;
+\& 3
+\& 4==> my $key = \*(Aqwelcome\*(Aq;
+\& 5: my %data = (
+\& 6 \*(Aqthis\*(Aq => qw(that),
+\& 7 \*(Aqtom\*(Aq => qw(and jerry),
+\& 8 \*(Aqwelcome\*(Aq => q(Hello World),
+\& 9 \*(Aqzip\*(Aq => q(welcome),
+\& 10 );
+.Ve
+.PP
+At line number 4 is a helpful pointer, that tells you where you are now. To
+see more code, type 'v' again:
+.PP
+.Vb 9
+\& DB<4> v
+\& 8 \*(Aqwelcome\*(Aq => q(Hello World),
+\& 9 \*(Aqzip\*(Aq => q(welcome),
+\& 10 );
+\& 11: my @data = keys %data;
+\& 12: print "All OK\en" if grep($key, keys %data);
+\& 13: print "$data{$key}\en";
+\& 14: print "done: \*(Aq$data{$key}\*(Aq\en";
+\& 15: exit;
+.Ve
+.PP
+And if you wanted to list line 5 again, type 'l 5', (note the space):
+.PP
+.Vb 2
+\& DB<4> l 5
+\& 5: my %data = (
+.Ve
+.PP
+In this case, there's not much to see, but of course normally there's pages of
+stuff to wade through, and 'l' can be very useful. To reset your view to the
+line we're about to execute, type a lone period '.':
+.PP
+.Vb 2
+\& DB<5> .
+\& main::(./data_a:4): my $key = \*(Aqwelcome\*(Aq;
+.Ve
+.PP
+The line shown is the one that is about to be executed \fBnext\fR, it hasn't
+happened yet. So while we can print a variable with the letter '\fBp\fR', at
+this point all we'd get is an empty (undefined) value back. What we need to
+do is to step through the next executable statement with an '\fBs\fR':
+.PP
+.Vb 7
+\& DB<6> s
+\& main::(./data_a:5): my %data = (
+\& main::(./data_a:6): \*(Aqthis\*(Aq => qw(that),
+\& main::(./data_a:7): \*(Aqtom\*(Aq => qw(and jerry),
+\& main::(./data_a:8): \*(Aqwelcome\*(Aq => q(Hello World),
+\& main::(./data_a:9): \*(Aqzip\*(Aq => q(welcome),
+\& main::(./data_a:10): );
+.Ve
+.PP
+Now we can have a look at that first ($key) variable:
+.PP
+.Vb 2
+\& DB<7> p $key
+\& welcome
+.Ve
+.PP
+line 13 is where the action is, so let's continue down to there via the letter
+\&'\fBc\fR', which by the way, inserts a 'one\-time\-only' breakpoint at the given
+line or sub routine:
+.PP
+.Vb 3
+\& DB<8> c 13
+\& All OK
+\& main::(./data_a:13): print "$data{$key}\en";
+.Ve
+.PP
+We've gone past our check (where 'All \s-1OK\s0' was printed) and have stopped just
+before the meat of our task. We could try to print out a couple of variables
+to see what is happening:
+.PP
+.Vb 1
+\& DB<9> p $data{$key}
+.Ve
+.PP
+Not much in there, lets have a look at our hash:
+.PP
+.Vb 2
+\& DB<10> p %data
+\& Hello Worldziptomandwelcomejerrywelcomethisthat
+\&
+\& DB<11> p keys %data
+\& Hello Worldtomwelcomejerrythis
+.Ve
+.PP
+Well, this isn't very easy to read, and using the helpful manual (\fBh h\fR), the
+\&'\fBx\fR' command looks promising:
+.PP
+.Vb 11
+\& DB<12> x %data
+\& 0 \*(AqHello World\*(Aq
+\& 1 \*(Aqzip\*(Aq
+\& 2 \*(Aqtom\*(Aq
+\& 3 \*(Aqand\*(Aq
+\& 4 \*(Aqwelcome\*(Aq
+\& 5 undef
+\& 6 \*(Aqjerry\*(Aq
+\& 7 \*(Aqwelcome\*(Aq
+\& 8 \*(Aqthis\*(Aq
+\& 9 \*(Aqthat\*(Aq
+.Ve
+.PP
+That's not much help, a couple of welcomes in there, but no indication of
+which are keys, and which are values, it's just a listed array dump and, in
+this case, not particularly helpful. The trick here, is to use a \fBreference\fR
+to the data structure:
+.PP
+.Vb 7
+\& DB<13> x \e%data
+\& 0 HASH(0x8194bc4)
+\& \*(AqHello World\*(Aq => \*(Aqzip\*(Aq
+\& \*(Aqjerry\*(Aq => \*(Aqwelcome\*(Aq
+\& \*(Aqthis\*(Aq => \*(Aqthat\*(Aq
+\& \*(Aqtom\*(Aq => \*(Aqand\*(Aq
+\& \*(Aqwelcome\*(Aq => undef
+.Ve
+.PP
+The reference is truly dumped and we can finally see what we're dealing with.
+Our quoting was perfectly valid but wrong for our purposes, with 'and jerry'
+being treated as 2 separate words rather than a phrase, thus throwing the
+evenly paired hash structure out of alignment.
+.PP
+The '\fB\-w\fR' switch would have told us about this, had we used it at the start,
+and saved us a lot of trouble:
+.PP
+.Vb 2
+\& > perl \-w data
+\& Odd number of elements in hash assignment at ./data line 5.
+.Ve
+.PP
+We fix our quoting: 'tom' => q(and jerry), and run it again, this time we get
+our expected output:
+.PP
+.Vb 2
+\& > perl \-w data
+\& Hello World
+.Ve
+.PP
+While we're here, take a closer look at the '\fBx\fR' command, it's really useful
+and will merrily dump out nested references, complete objects, partial objects
+\&\- just about whatever you throw at it:
+.PP
+Let's make a quick object and x\-plode it, first we'll start the debugger:
+it wants some form of input from \s-1STDIN,\s0 so we give it something non-committal,
+a zero:
+.PP
+.Vb 2
+\& > perl \-de 0
+\& Default die handler restored.
+\&
+\& Loading DB routines from perl5db.pl version 1.07
+\& Editor support available.
+\&
+\& Enter h or \`h h\*(Aq for help, or \`man perldebug\*(Aq for more help.
+\&
+\& main::(\-e:1): 0
+.Ve
+.PP
+Now build an on-the-fly object over a couple of lines (note the backslash):
+.PP
+.Vb 2
+\& DB<1> $obj = bless({\*(Aqunique_id\*(Aq=>\*(Aq123\*(Aq, \*(Aqattr\*(Aq=> \e
+\& cont: {\*(Aqcol\*(Aq => \*(Aqblack\*(Aq, \*(Aqthings\*(Aq => [qw(this that etc)]}}, \*(AqMY_class\*(Aq)
+.Ve
+.PP
+And let's have a look at it:
+.PP
+.Vb 10
+\& DB<2> x $obj
+\& 0 MY_class=HASH(0x828ad98)
+\& \*(Aqattr\*(Aq => HASH(0x828ad68)
+\& \*(Aqcol\*(Aq => \*(Aqblack\*(Aq
+\& \*(Aqthings\*(Aq => ARRAY(0x828abb8)
+\& 0 \*(Aqthis\*(Aq
+\& 1 \*(Aqthat\*(Aq
+\& 2 \*(Aqetc\*(Aq
+\& \*(Aqunique_id\*(Aq => 123
+\& DB<3>
+.Ve
+.PP
+Useful, huh? You can eval nearly anything in there, and experiment with bits
+of code or regexes until the cows come home:
+.PP
+.Vb 1
+\& DB<3> @data = qw(this that the other atheism leather theory scythe)
+\&
+\& DB<4> p \*(Aqsaw \-> \*(Aq.($cnt += map { print "\et:\et$_\en" } grep(/the/, sort @data))
+\& atheism
+\& leather
+\& other
+\& scythe
+\& the
+\& theory
+\& saw \-> 6
+.Ve
+.PP
+If you want to see the command History, type an '\fBH\fR':
+.PP
+.Vb 7
+\& DB<5> H
+\& 4: p \*(Aqsaw \-> \*(Aq.($cnt += map { print "\et:\et$_\en" } grep(/the/, sort @data))
+\& 3: @data = qw(this that the other atheism leather theory scythe)
+\& 2: x $obj
+\& 1: $obj = bless({\*(Aqunique_id\*(Aq=>\*(Aq123\*(Aq, \*(Aqattr\*(Aq=>
+\& {\*(Aqcol\*(Aq => \*(Aqblack\*(Aq, \*(Aqthings\*(Aq => [qw(this that etc)]}}, \*(AqMY_class\*(Aq)
+\& DB<5>
+.Ve
+.PP
+And if you want to repeat any previous command, use the exclamation: '\fB!\fR':
+.PP
+.Vb 9
+\& DB<5> !4
+\& p \*(Aqsaw \-> \*(Aq.($cnt += map { print "$_\en" } grep(/the/, sort @data))
+\& atheism
+\& leather
+\& other
+\& scythe
+\& the
+\& theory
+\& saw \-> 12
+.Ve
+.PP
+For more on references see perlref and perlreftut
+.SH "Stepping through code"
+.IX Header "Stepping through code"
+Here's a simple program which converts between Celsius and Fahrenheit, it too
+has a problem:
+.PP
+.Vb 2
+\& #!/usr/bin/perl
+\& use v5.36;
+\&
+\& my $arg = $ARGV[0] || \*(Aq\-c20\*(Aq;
+\&
+\& if ($arg =~ /^\e\-(c|f)((\e\-|\e+)*\ed+(\e.\ed+)*)$/) {
+\& my ($deg, $num) = ($1, $2);
+\& my ($in, $out) = ($num, $num);
+\& if ($deg eq \*(Aqc\*(Aq) {
+\& $deg = \*(Aqf\*(Aq;
+\& $out = &c2f($num);
+\& } else {
+\& $deg = \*(Aqc\*(Aq;
+\& $out = &f2c($num);
+\& }
+\& $out = sprintf(\*(Aq%0.2f\*(Aq, $out);
+\& $out =~ s/^((\e\-|\e+)*\ed+)\e.0+$/$1/;
+\& print "$out $deg\en";
+\& } else {
+\& print "Usage: $0 \-[c|f] num\en";
+\& }
+\& exit;
+\&
+\& sub f2c {
+\& my $f = shift;
+\& my $c = 5 * $f \- 32 / 9;
+\& return $c;
+\& }
+\&
+\& sub c2f {
+\& my $c = shift;
+\& my $f = 9 * $c / 5 + 32;
+\& return $f;
+\& }
+.Ve
+.PP
+For some reason, the Fahrenheit to Celsius conversion fails to return the
+expected output. This is what it does:
+.PP
+.Vb 2
+\& > temp \-c0.72
+\& 33.30 f
+\&
+\& > temp \-f33.3
+\& 162.94 c
+.Ve
+.PP
+Not very consistent! We'll set a breakpoint in the code manually and run it
+under the debugger to see what's going on. A breakpoint is a flag, to which
+the debugger will run without interruption, when it reaches the breakpoint, it
+will stop execution and offer a prompt for further interaction. In normal
+use, these debugger commands are completely ignored, and they are safe \- if a
+little messy, to leave in production code.
+.PP
+.Vb 4
+\& my ($in, $out) = ($num, $num);
+\& $DB::single=2; # insert at line 9!
+\& if ($deg eq \*(Aqc\*(Aq)
+\& ...
+\&
+\& > perl \-d temp \-f33.3
+\& Default die handler restored.
+\&
+\& Loading DB routines from perl5db.pl version 1.07
+\& Editor support available.
+\&
+\& Enter h or \`h h\*(Aq for help, or \`man perldebug\*(Aq for more help.
+\&
+\& main::(temp:4): my $arg = $ARGV[0] || \*(Aq\-c100\*(Aq;
+.Ve
+.PP
+We'll simply continue down to our pre-set breakpoint with a '\fBc\fR':
+.PP
+.Vb 2
+\& DB<1> c
+\& main::(temp:10): if ($deg eq \*(Aqc\*(Aq) {
+.Ve
+.PP
+Followed by a view command to see where we are:
+.PP
+.Vb 11
+\& DB<1> v
+\& 7: my ($deg, $num) = ($1, $2);
+\& 8: my ($in, $out) = ($num, $num);
+\& 9: $DB::single=2;
+\& 10==> if ($deg eq \*(Aqc\*(Aq) {
+\& 11: $deg = \*(Aqf\*(Aq;
+\& 12: $out = &c2f($num);
+\& 13 } else {
+\& 14: $deg = \*(Aqc\*(Aq;
+\& 15: $out = &f2c($num);
+\& 16 }
+.Ve
+.PP
+And a print to show what values we're currently using:
+.PP
+.Vb 2
+\& DB<1> p $deg, $num
+\& f33.3
+.Ve
+.PP
+We can put another break point on any line beginning with a colon, we'll use
+line 17 as that's just as we come out of the subroutine, and we'd like to
+pause there later on:
+.PP
+.Vb 1
+\& DB<2> b 17
+.Ve
+.PP
+There's no feedback from this, but you can see what breakpoints are set by
+using the list 'L' command:
+.PP
+.Vb 4
+\& DB<3> L
+\& temp:
+\& 17: print "$out $deg\en";
+\& break if (1)
+.Ve
+.PP
+Note that to delete a breakpoint you use 'B'.
+.PP
+Now we'll continue down into our subroutine, this time rather than by line
+number, we'll use the subroutine name, followed by the now familiar 'v':
+.PP
+.Vb 2
+\& DB<3> c f2c
+\& main::f2c(temp:30): my $f = shift;
+\&
+\& DB<4> v
+\& 24: exit;
+\& 25
+\& 26 sub f2c {
+\& 27==> my $f = shift;
+\& 28: my $c = 5 * $f \- 32 / 9;
+\& 29: return $c;
+\& 30 }
+\& 31
+\& 32 sub c2f {
+\& 33: my $c = shift;
+.Ve
+.PP
+Note that if there was a subroutine call between us and line 29, and we wanted
+to \fBsingle-step\fR through it, we could use the '\fBs\fR' command, and to step
+over it we would use '\fBn\fR' which would execute the sub, but not descend into
+it for inspection. In this case though, we simply continue down to line 29:
+.PP
+.Vb 2
+\& DB<4> c 29
+\& main::f2c(temp:29): return $c;
+.Ve
+.PP
+And have a look at the return value:
+.PP
+.Vb 2
+\& DB<5> p $c
+\& 162.944444444444
+.Ve
+.PP
+This is not the right answer at all, but the sum looks correct. I wonder if
+it's anything to do with operator precedence? We'll try a couple of other
+possibilities with our sum:
+.PP
+.Vb 2
+\& DB<6> p (5 * $f \- 32 / 9)
+\& 162.944444444444
+\&
+\& DB<7> p 5 * $f \- (32 / 9)
+\& 162.944444444444
+\&
+\& DB<8> p (5 * $f) \- 32 / 9
+\& 162.944444444444
+\&
+\& DB<9> p 5 * ($f \- 32) / 9
+\& 0.722222222222221
+.Ve
+.PP
+:\-) that's more like it! Ok, now we can set our return variable and we'll
+return out of the sub with an 'r':
+.PP
+.Vb 1
+\& DB<10> $c = 5 * ($f \- 32) / 9
+\&
+\& DB<11> r
+\& scalar context return from main::f2c: 0.722222222222221
+.Ve
+.PP
+Looks good, let's just continue off the end of the script:
+.PP
+.Vb 5
+\& DB<12> c
+\& 0.72 c
+\& Debugged program terminated. Use q to quit or R to restart,
+\& use O inhibit_exit to avoid stopping after program termination,
+\& h q, h R or h O to get additional info.
+.Ve
+.PP
+A quick fix to the offending line (insert the missing parentheses) in the
+actual program and we're finished.
+.SH "Placeholder for a, w, t, T"
+.IX Header "Placeholder for a, w, t, T"
+Actions, watch variables, stack traces etc.: on the \s-1TODO\s0 list.
+.PP
+.Vb 1
+\& a
+\&
+\& w
+\&
+\& t
+\&
+\& T
+.Ve
+.SH "REGULAR EXPRESSIONS"
+.IX Header "REGULAR EXPRESSIONS"
+Ever wanted to know what a regex looked like? You'll need perl compiled with
+the \s-1DEBUGGING\s0 flag for this one:
+.PP
+.Vb 10
+\& > perl \-Dr \-e \*(Aq/^pe(a)*rl$/i\*(Aq
+\& Compiling REx \`^pe(a)*rl$\*(Aq
+\& size 17 first at 2
+\& rarest char
+\& at 0
+\& 1: BOL(2)
+\& 2: EXACTF <pe>(4)
+\& 4: CURLYN[1] {0,32767}(14)
+\& 6: NOTHING(8)
+\& 8: EXACTF <a>(0)
+\& 12: WHILEM(0)
+\& 13: NOTHING(14)
+\& 14: EXACTF <rl>(16)
+\& 16: EOL(17)
+\& 17: END(0)
+\& floating \`\*(Aq$ at 4..2147483647 (checking floating) stclass
+\& \`EXACTF <pe>\*(Aq anchored(BOL) minlen 4
+\& Omitting $\` $& $\*(Aq support.
+\&
+\& EXECUTING...
+\&
+\& Freeing REx: \`^pe(a)*rl$\*(Aq
+.Ve
+.PP
+Did you really want to know? :\-)
+For more gory details on getting regular expressions to work, have a look at
+perlre, perlretut, and to decode the mysterious labels (\s-1BOL\s0 and \s-1CURLYN,\s0
+etc. above), see perldebguts.
+.SH "OUTPUT TIPS"
+.IX Header "OUTPUT TIPS"
+To get all the output from your error log, and not miss any messages via
+helpful operating system buffering, insert a line like this, at the start of
+your script:
+.PP
+.Vb 1
+\& $|=1;
+.Ve
+.PP
+To watch the tail of a dynamically growing logfile, (from the command line):
+.PP
+.Vb 1
+\& tail \-f $error_log
+.Ve
+.PP
+Wrapping all die calls in a handler routine can be useful to see how, and from
+where, they're being called, perlvar has more information:
+.PP
+.Vb 1
+\& BEGIN { $SIG{_\|_DIE_\|_} = sub { require Carp; Carp::confess(@_) } }
+.Ve
+.PP
+Various useful techniques for the redirection of \s-1STDOUT\s0 and \s-1STDERR\s0 filehandles
+are explained in perlopentut and perlfaq8.
+.SH "CGI"
+.IX Header "CGI"
+Just a quick hint here for all those \s-1CGI\s0 programmers who can't figure out how
+on earth to get past that 'waiting for input' prompt, when running their \s-1CGI\s0
+script from the command-line, try something like this:
+.PP
+.Vb 1
+\& > perl \-d my_cgi.pl \-nodebug
+.Ve
+.PP
+Of course \s-1CGI\s0 and perlfaq9 will tell you more.
+.SH "GUIs"
+.IX Header "GUIs"
+The command line interface is tightly integrated with an \fBemacs\fR extension
+and there's a \fBvi\fR interface too.
+.PP
+You don't have to do this all on the command line, though, there are a few \s-1GUI\s0
+options out there. The nice thing about these is you can wave a mouse over a
+variable and a dump of its data will appear in an appropriate window, or in a
+popup balloon, no more tiresome typing of 'x \f(CW$varname\fR' :\-)
+.PP
+In particular have a hunt around for the following:
+.PP
+\&\fBptkdb\fR perlTK based wrapper for the built-in debugger
+.PP
+\&\fBddd\fR data display debugger
+.PP
+\&\fBPerlDevKit\fR and \fBPerlBuilder\fR are \s-1NT\s0 specific
+.PP
+\&\s-1NB.\s0 (more info on these and others would be appreciated).
+.SH "SUMMARY"
+.IX Header "SUMMARY"
+We've seen how to encourage good coding practices with \fBuse strict\fR and
+\&\fB\-w\fR. We can run the perl debugger \fBperl \-d scriptname\fR to inspect your
+data from within the perl debugger with the \fBp\fR and \fBx\fR commands. You can
+walk through your code, set breakpoints with \fBb\fR and step through that code
+with \fBs\fR or \fBn\fR, continue with \fBc\fR and return from a sub with \fBr\fR. Fairly
+intuitive stuff when you get down to it.
+.PP
+There is of course lots more to find out about, this has just scratched the
+surface. The best way to learn more is to use perldoc to find out more about
+the language, to read the on-line help (perldebug is probably the next
+place to go), and of course, experiment.
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+perldebug,
+perldebguts,
+perl5db.pl,
+perldiag,
+perlrun
+.SH "AUTHOR"
+.IX Header "AUTHOR"
+Richard Foley <richard.foley@rfi.net> Copyright (c) 2000
+.SH "CONTRIBUTORS"
+.IX Header "CONTRIBUTORS"
+Various people have made helpful suggestions and contributions, in particular:
+.PP
+Ronald J Kimball <rjk@linguist.dartmouth.edu>
+.PP
+Hugo van der Sanden <hv@crypt0.demon.co.uk>
+.PP
+Peter Scott <Peter@PSDT.com>