3 use Carp
(); # old Carp doesn't export shortmess.
6 use vars
qw($pack $file $line $sub $level
10 *define_shortcut = *Sepia::define_shortcut;
13 ## Just leave it on -- with $DB::trace = 0, there doesn't seem
14 ## to be a performance penalty!
15 ## enter/exit | per-line | sub locations | eval filenames | anon subnames
16 $^P = 0x313; # 01 | 02 | 10 | 100 | 200
23 eval q{ require PadWalker };
27 *peek_my
= \
&PadWalker
::peek_my
;
40 for (my $i = 0; ; ++$i) {
41 my ($pack, $file, $line, $sub) = caller($i);
43 # XXX: 4 is the magic number...
44 print($i == $level+4 ?
"*" : ' ', " [$i]\t$sub ($file:$line)\n");
48 # return value from die
51 if ($Sepia::WANTARRAY
) {
52 @Sepia::REPL_RESULT
= $Sepia::REPL
{eval}->(@_);
54 $Sepia::REPL_RESULT
[0] = $Sepia::REPL
{eval}->(@_);
59 use vars
qw($DIE_TO @DIE_RETURN $DIE_LEVEL);
64 eval q{ use Scope::Upper ':all' };
66 print "xreturn requires Sub::Uplevel.\n";
69 *xreturn
= eval <<'EOS';
72 $exp = '""' unless defined $exp;
73 my $ctx = CALLER($level+4); # XXX: ok?
74 local $Sepia::WANTARRAY = want_at $ctx;
75 my @res = eval_in_env($exp, peek_my($level + 4));
76 print STDERR "unwind(@res)\n";
77 unwind @res, SUB UP $ctx;
86 print STDERR
"XRETURN(@_)\n";
87 xreturn
(shift); # XXX: doesn't return. Problem?
88 print STDERR
"XRETURN: XXX\n";
89 # ($DB::DIE_TO, $DB::DIE_RETURN[0]) = split ' ', $_[0], 2;
90 # $DB::DIE_RETURN[0] = $Sepia::REPL{eval}->($DB::DIE_RETURN[0]);
99 local $DIE_LEVEL = $DIE_LEVEL + 1;
100 ## Set up a dynamic catch target
106 if $DIE_LEVEL > 1 && defined $DIE_TO
107 && $DB::sub !~ /(?:^|::)\Q$DIE_TO\E$/;
109 wantarray ?
@DIE_RETURN : $DIE_RETURN[0]
126 for my $file (sort grep /^_</ && *{"::$_"}{HASH
}, keys %::) {
127 my ($name) = $file =~ /^_<(.*)/;
128 my @pts = keys %{"::$file"};
131 for (sort { $a <=> $b } @pts) {
132 print "\t$_\t${$file}{$_}\n"
137 # evaluate EXPR in environment ENV
140 my ($expr, $env) = @_;
141 local $Sepia::ENV
= $env;
144 next unless /^([\$\@%])(.+)/;
145 $str .= "local *$2 = \$Sepia::ENV->{'$_'}; ";
147 $str = "do { no strict; package $Sepia::PACKAGE; $str $expr }";
148 return $Sepia::WANTARRAY ?
eval $str : scalar eval $str;
154 my $sig = substr shift, 0, 1;
155 return $sig eq '$' ?
'Tie::StdScalar'
156 : $sig eq '@' ?
'Tie::StdArray'
157 : $sig eq '%' ?
'Tie::StdHash'
158 : die "Sorry, can't tie $sig\n";
161 ## XXX: this is a better approach (the local/tie business is vile),
162 ## but it segfaults and I'm not sure why.
165 my ($expr, $env, $fn) = @_;
166 local $Sepia::ENV
= $env;
167 my @vars = grep /^([\$\@%])(.+)/, keys %$env;
168 my $body = 'sub { my ('.join(',', @vars).');';
170 $body .= "Devel::LexAlias::lexalias(\$Sepia::ENV, '$_', \\$_);"
173 print STDERR
"---\n$body\n---\n";
178 # evaluate EXP LEV levels up the stack
180 # NOTE: We need to act like &repl_eval here and consider e.g. $WANTARRAY
183 # if ($Sepia::WANTARRAY) {
184 return eval_in_env
(shift, peek_my
(4+$level));
186 # return scalar eval_in_env(shift, peek_my(4+$level));
190 # inspect lexicals at level N, or current level
199 my $sub = (caller $i)[3];
201 my $h = peek_my
($i+1);
202 print "[$i] $sub:\n";
203 for (sort keys %$h) {
204 local @Sepia::res
= $h->{$_};
205 print "\t$_ = ", $Sepia::PRINTER
{$Sepia::PRINTER
}->(), "\n";
212 my $new = Sepia
::as_boolean
(shift, $DB::trace
);
213 print "debug ", $new ?
"ON" : "OFF";
214 if ($new == $DB::trace
) {
215 print " (unchanged)\n"
225 return \
%{$main::{"_<$file"}} if exists $main::{"_<$file"};
226 if ($file !~ /^\//) {
227 ($file) = grep /^_<.*\/\Q
$file\E
$/, keys %main::;
228 return \
%{$main::{$file}} if $file;
235 my ($file, $line, $cond) = @_;
236 my $h = breakpoint_file
$file;
238 $h->{$line} = $cond || 1;
239 return $cond ?
"$file\:$line if $cond" : "$file\:$line";
249 my ($f, $l, $cond) = $arg =~ /^(.+?):(\d+)\s*(.*)/;
250 $cond = 1 unless $cond =~ /\S/;
253 return unless defined $f && defined $l;
254 my $bp = breakpoint
($f, $l, $cond);
255 print "break $bp\n" if $bp;
260 # XXX: magic numberage.
261 ($pack, $file, $line, $sub) = caller($level + shift);
266 print "_<$file:$line>\n" if defined $file && defined $line;
271 my @lines = eval shift;
272 @lines = $line - 5 .. $line + 5 unless @lines;
273 printf '%-6d%s', $_, ${"::_<$file"}[$_-1] for @lines;
278 my ($f, $l) = split /:/, shift;
281 my $h = breakpoint_file
$f;
282 delete $h->{$l} if defined $h;
287 # XXX: doesn't handle recursion, but oh, well...
288 my $sub = (caller $level + 4)[3];
289 if (exists $DB::sub{$sub}) {
290 my ($file, $start, $end) = $DB::sub{$sub} =~ /(.*):(\d+)-(\d+)/;
291 print STDERR
"finish($sub): will stop at $file:$end\n";
292 # XXX: $end doesn't always work, since it may not have an
293 # executable statement on it.
294 breakpoint
($file, $end-1, 'finish');
297 print STDERR
"yikes: @{[keys %DB::sub]}\n";
304 die(bless [], __PACKAGE__
);
307 sub add_repl_commands
309 define_shortcut
'delete', \
&repl_delete
,
310 'Delete current breakpoint.';
311 define_shortcut
'debug', \
&repl_debug
,
312 'debug [0|1]', 'Enable or disable debugging.';
313 define_shortcut
'break', \
&repl_break
,
315 'Break at file F, line N (or at current position) if E is true.';
316 define_shortcut
'lsbreak', \
&repl_lsbreak
,
318 # define_shortcut 'dbsub', \&repl_dbsub, '(Un)install DB::sub.';
319 %Sepia::RK
= abbrev
keys %Sepia::REPL
;
322 sub add_debug_repl_commands
324 define_shortcut quit
=> \
&repl_toplevel
,
325 'quit', 'Quit the debugger, returning to the top level.';
326 define_shortcut toplevel
=> \
&repl_toplevel
,
327 'toplevel', 'Return to the top level.';
328 define_shortcut up
=> sub {
329 $level += shift || 1;
332 }, 'up [N]', 'Move up N stack frames.';
333 define_shortcut down
=> sub {
334 $level -= shift || 1;
335 $level = 0 if $level < 0;
338 }, 'down [N]', 'Move down N stack frames.';
339 define_shortcut
continue => sub {
345 define_shortcut
next => sub {
348 breakpoint
$file, $line + $n, 'next';
350 }, 'next [N]', 'Advance N lines, skipping subroutines.';
352 define_shortcut step
=> sub {
353 $DB::single
= shift || 1;
355 }, 'step [N]', 'Step N lines forward, entering subroutines.';
357 define_shortcut finish
=> \
&repl_finish
,
358 'finish', 'Finish the current subroutine.';
360 define_shortcut list
=> \
&repl_list
,
361 'list EXPR', 'List source lines of current file.';
362 define_shortcut backtrace
=> \
&repl_backtrace
, 'show backtrace';
363 define_shortcut inspect
=> \
&repl_inspect
,
364 'inspect [N]', 'inspect lexicals in frame N (or current)';
365 define_shortcut
return => \
&repl_return
, 'return EXPR', 'return EXPR';
366 # define_shortcut xreturn => \&repl_xreturn, 'xreturn EXPR',
367 # 'return EXPR from the current sub.';
368 define_shortcut
eval => \
&repl_upeval
,
369 'eval EXPR', 'evaluate EXPR in current frame'; # DANGER!
375 local %Sepia::REPL
= %Sepia::REPL
;
376 local %Sepia::REPL_DOC
= %Sepia::REPL_DOC
;
377 add_debug_repl_commands
;
378 map { define_shortcut @
$_ } @_;
379 local %Sepia::RK
= abbrev
keys %Sepia::REPL
;
380 # local $Sepia::REPL_LEVEL = $Sepia::REPL_LEVEL + 1;
381 local $Sepia::PS1
= "*$Sepia::REPL_LEVEL*> ";
387 return if $Sepia::ISEVAL
;
389 local ($pack, $file, $line, $sub) = caller($level);
390 ## Don't do anything if we're inside an eval request, even if in
392 return unless $DB::single
|| exists $main::{"_<$file"}{$line};
394 return unless --$DB::single
== 0;
396 my $cond = $main::{"_<$file"}{$line};
397 if ($cond eq 'next') {
398 delete $main::{"_<$file"}{$line};
399 } elsif ($cond eq 'finish') {
400 # remove temporary breakpoint and take one more step.
401 delete $main::{"_<$file"}{$line};
405 return unless $Sepia::REPL
{eval}->($cond);
411 my $MSG = "('\\C-c' to exit, ',h' for help)";
415 ## Protect us against people doing weird things.
416 if ($STOPDIE && !$SIG{__DIE__
}) {
419 local ($pack, $file, $line, $sub) = caller($level);
421 $tmp .= "\n" unless $tmp =~ /\n\z/;
422 print "$tmp\tin $sub\nDied $MSG\n";
423 my $trace = $DB::trace
;
426 [die => sub { local $STOPDIE=0; CORE
::die @dieargs },
428 [quit
=> sub { local $STOPDIE=0; CORE
::die @dieargs },
432 CORE
::die(Carp
::shortmess
@_);
439 ## Again, this is above our pay grade:
440 if ($STOPWARN && $SIG{__WARN__
} eq 'Sepia::sig_warn') {
442 my $trace = $DB::trace
;
445 local ($pack, $file, $line, $sub) = caller($level);
446 print "@_\n\tin $sub\nWarned $MSG\n";
448 [warn => sub { local $STOPWARN=0; CORE
::warn @dieargs },
449 'Continue warning.'],
450 [quit
=> sub { local $STOPWARN=0; CORE
::warn @dieargs },
451 'Continue warning.']);
454 ## Avoid showing up in location information.
455 CORE
::warn(Carp
::shortmess
@_);
463 my $trace = $DB::trace
;
466 local ($pack, $file, $line, $sub) = caller($level);
467 print "@_\n\tin $sub\nCaught signal $sig\n";
469 [die => sub { local $STOPDIE=0; CORE
::die "Caught signal $sig; exiting." },
471 [quit
=> sub { local $STOPWARN=0; CORE
::die "Caught signal $sig; exiting." },
475 Carp
::confess
"Caught signal $sig: continue at your own risk.";