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 perforamnce penalty!
22 eval { require PadWalker };
26 *peek_my = \&PadWalker::peek_my;
39 for (my $i = 0; ; ++$i) {
40 my ($pack, $file, $line, $sub) = caller($i);
42 # XXX: 4 is the magic number...
43 print($i == $level+4 ? "*" : ' ', " [$i]\t$sub ($file:$line)\n");
47 # return value from die
50 if ($Sepia::WANTARRAY) {
51 @Sepia::REPL_RESULT = $Sepia::REPL{eval}->(@_);
53 $Sepia::REPL_RESULT[0] = $Sepia::REPL{eval}->(@_);
58 use vars qw($DIE_TO @DIE_RETURN $DIE_LEVEL);
63 ($DB::DIE_TO, $DB::DIE_RETURN[0]) = split ' ', $_[0], 2;
64 $DB::DIE_RETURN[0] = $Sepia::REPL{eval}->($DB::DIE_RETURN[0]);
73 local $DIE_LEVEL = $DIE_LEVEL + 1;
74 ## Set up a dynamic catch target
80 if $DIE_LEVEL > 1 && defined $DIE_TO
81 && $DB::sub !~ /(?:^|::)\Q$DIE_TO\E$/;
83 wantarray ? @DIE_RETURN : $DIE_RETURN[0]
100 for my $file (sort grep /^_</ && defined %{"::$_"}, keys %::) {
101 my ($name) = $file =~ /^_<(.*)/;
102 my @pts = keys %{"::$file"};
105 for (sort { $a <=> $b } @pts) {
106 print "\t$_\t${$file}{$_}\n"
111 # evaluate EXPR in environment ENV
114 my ($expr, $env) = @_;
115 local $Sepia::ENV = $env;
118 next unless /^([\$\@%])(.+)/;
119 $str .= "local *$2 = \$Sepia::ENV->{'$_'}; ";
121 eval "do { no strict; package $Sepia::PACKAGE; $str $expr }";
126 my $sig = substr shift, 0, 1;
127 return $sig eq '$' ? 'Tie::StdScalar'
128 : $sig eq '@' ? 'Tie::StdArray'
129 : $sig eq '%' ? 'Tie::StdHash'
130 : die "Sorry, can't tie $sig\n";
133 ## XXX: this is a better approach (the local/tie business is vile),
134 ## but it segfaults and I'm not sure why.
137 my ($expr, $env, $fn) = @_;
138 local $Sepia::ENV = $env;
139 my @vars = grep /^([\$\@%])(.+)/, keys %$env;
140 my $body = 'sub { my ('.join(',', @vars).');';
142 $body .= "Devel::LexAlias::lexalias(\$Sepia::ENV, '$_', \\$_);"
145 print STDERR "---\n$body\n---\n";
150 # evaluate EXP LEV levels up the stack
153 eval_in_env(shift, peek_my(4+$level));
156 # inspect lexicals at level N, or current level
165 my $sub = (caller $i)[3];
167 my $h = peek_my($i+1);
168 print "[$i] $sub:\n";
169 for (sort keys %$h) {
170 local @Sepia::res = $h->{$_};
171 print "\t$_ = ", $Sepia::PRINTER{$Sepia::PRINTER}->(), "\n";
178 my $new = Sepia::as_boolean(shift, $DB::trace);
179 print "debug ", $new ? "ON" : "OFF";
180 if ($new == $DB::trace) {
181 print " (unchanged)\n"
191 return \%{$main::{"_<$file"}} if exists $main::{"_<$file"};
192 if ($file !~ /^\//) {
193 ($file) = grep /^_<.*\/\Q$file\E$/, keys %main::;
194 return \%{$main::{$file}} if $file;
201 my ($file, $line, $cond) = @_;
202 my $h = breakpoint_file $file;
204 $h->{$line} = $cond || 1;
205 return $cond ? "$file\:$line if $cond" : "$file\:$line";
215 my ($f, $l, $cond) = $arg =~ /^(.+?):(\d+)\s*(.*)/;
216 $cond = 1 unless $cond =~ /\S/;
219 return unless defined $f && defined $l;
220 my $bp = breakpoint($f, $l, $cond);
221 print "break $bp\n" if $bp;
226 # XXX: magic numberage.
227 ($pack, $file, $line, $sub) = caller($level + shift);
232 print "_<$file:$line>\n" if defined $file && defined $line;
237 my @lines = eval shift;
238 @lines = $line - 5 .. $line + 5 unless @lines;
239 printf '%-6d%s', $_, ${"::_<$file"}[$_-1] for @lines;
244 my ($f, $l) = split /:/, shift;
247 my $h = breakpoint_file $f;
248 delete $h->{$l} if defined $h;
251 my ($finish_file, $finish_line);
255 print STDERR "finish: ($file, $line)\n";
256 $finish_file = $file;
257 $finish_line = $line;
265 die(bless [], __PACKAGE__);
268 sub add_repl_commands
270 define_shortcut 'delete', \&repl_delete,
271 'Delete current breakpoint.';
272 define_shortcut 'debug', \&repl_debug,
273 'debug [0|1]', 'Enable or disable debugging.';
274 define_shortcut 'break', \&repl_break,
276 'Break at file F, line N (or at current position) if E is true.';
277 define_shortcut 'lsbreak', \&repl_lsbreak,
279 # define_shortcut 'dbsub', \&repl_dbsub, '(Un)install DB::sub.';
280 %Sepia::RK = abbrev keys %Sepia::REPL;
283 sub add_debug_repl_commands
285 define_shortcut quit => \&repl_toplevel,
286 'quit', 'Quit the debugger, returning to the top level.';
287 define_shortcut toplevel => \&repl_toplevel,
288 'toplevel', 'Return to the top level.';
289 define_shortcut up => sub {
290 $level += shift || 1;
293 }, 'up [N]', 'Move up N stack frames.';
294 define_shortcut down => sub {
295 $level -= shift || 1;
296 $level = 0 if $level < 0;
299 }, 'down [N]', 'Move down N stack frames.';
300 define_shortcut continue => sub {
306 define_shortcut next => sub {
309 breakpoint $file, $line + $n, 'next';
311 }, 'next [N]', 'Advance N lines, skipping subroutines.';
313 define_shortcut step => sub {
314 $DB::single = shift || 1;
316 }, 'step [N]', 'Step N lines forward, entering subroutines.';
318 # define_shortcut finish => \&repl_finish,
319 # 'finish', 'Finish the current subroutine.';
321 define_shortcut list => \&repl_list,
322 'list EXPR', 'List source lines of current file.';
323 define_shortcut backtrace => \&repl_backtrace, 'show backtrace';
324 define_shortcut inspect => \&repl_inspect,
325 'inspect [N]', 'inspect lexicals in frame N (or current)';
326 define_shortcut return => \&repl_return, 'return EXPR', 'return EXPR';
327 # define_shortcut xreturn => \&repl_xreturn, 'xreturn NAME EXPR',
328 # 'xreturn NAME EXPR';
329 define_shortcut eval => \&repl_upeval,
330 'eval EXPR', 'evaluate EXPR in current frame'; # DANGER!
336 local %Sepia::REPL = %Sepia::REPL;
337 local %Sepia::REPL_DOC = %Sepia::REPL_DOC;
338 add_debug_repl_commands;
339 map { define_shortcut @$_ } @_;
340 local %Sepia::RK = abbrev keys %Sepia::REPL;
341 # local $Sepia::REPL_LEVEL = $Sepia::REPL_LEVEL + 1;
342 local $Sepia::PS1 = "*$Sepia::REPL_LEVEL*> ";
348 return if $Sepia::ISEVAL;
350 local ($pack, $file, $line, $sub) = caller($level);
351 ## Don't do anything if we're inside an eval request, even if in
353 return unless $DB::single || exists $main::{"_<$file"}{$line};
354 if (defined $finish_file) {
355 print STDERR "finish = $finish_file:$finish_line\n",
356 "cur = $file:$line\n";
357 if ($file eq $finish_file
358 && abs($line - $finish_line) < 3) {
359 $finish_line = $line;
366 } elsif ($DB::single) {
367 return unless --$DB::single == 0;
369 my $cond = $main::{"_<$file"}{$line};
370 if ($cond eq 'next') {
371 delete $main::{"_<$file"}{$line};
373 return unless $Sepia::REPL{eval}->($cond);
379 my $MSG = "('\\C-c' to exit, ',h' for help)";
383 ## Protect us against people doing weird things.
384 if ($STOPDIE && !$SIG{__DIE__}) {
387 local ($pack, $file, $line, $sub) = caller($level);
389 $tmp .= "\n" unless $tmp =~ /\n\z/;
390 print "$tmp\tin $sub\nDied $MSG\n";
391 my $trace = $DB::trace;
394 [die => sub { local $STOPDIE=0; CORE::die @dieargs },
396 [quit => sub { local $STOPDIE=0; CORE::die @dieargs },
400 CORE::die(Carp::shortmess @_);
407 ## Again, this is above our pay grade:
408 if ($STOPWARN && $SIG{__WARN__} eq 'Sepia::sig_warn') {
410 my $trace = $DB::trace;
413 local ($pack, $file, $line, $sub) = caller($level);
414 print "@_\n\tin $sub\nWarned $MSG\n";
416 [warn => sub { local $STOPWARN=0; CORE::warn @dieargs },
417 'Continue warning.'],
418 [quit => sub { local $STOPWARN=0; CORE::warn @dieargs },
419 'Continue warning.']);
422 ## Avoid showing up in location information.
423 CORE::warn(Carp::shortmess @_);
431 my $trace = $DB::trace;
434 local ($pack, $file, $line, $sub) = caller($level);
435 print "@_\n\tin $sub\nCaught signal $sig\n";
437 [die => sub { local $STOPDIE=0; CORE::die "Caught signal $sig; exiting." },
439 [quit => sub { local $STOPWARN=0; CORE::die "Caught signal $sig; exiting." },
443 Carp::confess "Caught signal $sig: continue at your own risk.";