diff options
Diffstat (limited to 'upstream/debian-bookworm/man1/perldebtut.1')
-rw-r--r-- | upstream/debian-bookworm/man1/perldebtut.1 | 887 |
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> |