I would like to be able to (reasonably) arbitrarily set my execution point in the Perl debugger. E.g., moving imm开发者_JS百科ediately prior to an if from the body of the if and setting a variable.
Rummaging around the perldebug(and perldebguts and the perl debugger POD) page suggests that this kind of functionality is either not supported or not documented.
A cumbersome workaround would be to add labels and conditional goto
statements throughout your code. But depending on how badly you want to emulate this feature, it might be worth it.
POINT1: $GOTO=""; # $GOTO is our fake variable that we only set from the debugger
($a,$b,$c)=(1,2,3);
POINT2: $GOTO="";
if ($a < $b) {
goto $GOTO if $GOTO;
if ($a > $c) {
goto $GOTO if $GOTO;
print "foo\n";
} else {
goto $GOTO if $GOTO;
print "bar\n";
}
goto $GOTO if $GOTO;
} else {
goto $GOTO if $GOTO;
print "nothing\n";
goto $GOTO if $GOTO;
}
Sample debugging session:
$ perl -d debuggoto.pl
Loading DB routines from perl5db.pl version 1.28
Editor support available.
Enter h or `h h' for help, or `man perldebug' for more help.
main::(debuggoto.pl:1): POINT1: $GOTO=""; # $GOTO is our fake variable that we only set from the debugger
DB<1> n
main::(debuggoto.pl:2): ($a,$b,$c)=(1,2,3);
DB<1>
main::(debuggoto.pl:3): POINT2: $GOTO="";
DB<1>
main::(debuggoto.pl:4): if ($a < $b) {
DB<1>
main::(debuggoto.pl:5): goto $GOTO if $GOTO;
DB<1>
main::(debuggoto.pl:6): if ($a > $c) {
DB<1>
main::(debuggoto.pl:10): goto $GOTO if $GOTO;
DB<1>
main::(debuggoto.pl:11): print "bar\n";
DB<1>
bar
main::(debuggoto.pl:13): goto $GOTO if $GOTO;
DB<1> $GOTO="POINT2"
DB<2> n
main::(debuggoto.pl:3): POINT2: $GOTO="";
DB<2> $c=0
DB<3> n
main::(debuggoto.pl:4): if ($a < $b) {
DB<3>
main::(debuggoto.pl:5): goto $GOTO if $GOTO;
DB<3>
main::(debuggoto.pl:6): if ($a > $c) {
DB<3>
main::(debuggoto.pl:7): goto $GOTO if $GOTO;
DB<3>
main::(debuggoto.pl:8): print "foo\n";
DB<3>
foo
main::(debuggoto.pl:13): goto $GOTO if $GOTO;
DB<3>
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.
DB<3>
Use `q' to quit or `R' to restart. `h q' for details.
DB<3>
I wonder if it would be possible to build a debugger that uses this idea.
I am still not sure what exactly this would achieve, but I bet a custom runloop that skips ops you don't care about until you start caring again might solve your problem.
A good runloop to cargo-cult is Runops::Switch. Remove the switch statement and write a function that skips ops until you are on the one you want to run; then just call into the normal runloop to actually run that op.
Relevant code: http://cpansearch.perl.org/src/RGARCIA/Runops-Switch-0.04/Switch.xs
This is all handwaving, I have never written a runloop before. The goto idea in another post is also good, but this involves writing less code.
Breakpoints can only be set on the first line of a statement.
This can't be done with the existing debugger.
精彩评论