# Debugger for Perl 5.00x; perl5db.pl patch level:
-$VERSION = 0.9904;
-$header = "perl5db.pl patch level $VERSION";
+$VERSION = 1.00;
+$header = "perl5db.pl version $VERSION";
# Enhanced by ilya@math.ohio-state.edu (Ilya Zakharevich)
# Latest version available: ftp://ftp.math.ohio-state.edu/pub/users/ilya/perl
$dumpvar::quoteHighBit,
$dumpvar::printUndef,
$dumpvar::globPrint,
- $readline::Tk_toloop,
$dumpvar::usageOnly,
@ARGS,
$Carp::CarpLevel,
compactDump veryCompact quote HighBit undefPrint
globPrint PrintRet UsageOnly frame AutoTrace
TTY noTTY ReadLine NonStop LineInfo maxTraceLen
- recallCommand ShellBang pager tkRunning
+ recallCommand ShellBang pager tkRunning ornaments
signalLevel warnLevel dieLevel inhibit_exit);
%optionVars = (
HighBit => \$dumpvar::quoteHighBit,
undefPrint => \$dumpvar::printUndef,
globPrint => \$dumpvar::globPrint,
- tkRunning => \$readline::Tk_toloop,
UsageOnly => \$dumpvar::usageOnly,
frame => \$frame,
AutoTrace => \$trace,
signalLevel => \&signalLevel,
warnLevel => \&warnLevel,
dieLevel => \&dieLevel,
+ tkRunning => \&tkRunning,
+ ornaments => \&ornaments,
);
%optionRequire = (
%postponed = get_list("PERLDB_POSTPONE");
my @had_breakpoints= get_list("PERLDB_VISITED");
for (0 .. $#had_breakpoints) {
- %{$postponed_file{$had_breakpoints[$_]}} = get_list("PERLDB_FILE_$_");
+ my %pf = get_list("PERLDB_FILE_$_");
+ $postponed_file{$had_breakpoints[$_]} = \%pf if %pf;
}
my %opt = get_list("PERLDB_OPT");
my ($opt,$val);
}
@INC = get_list("PERLDB_INC");
@ini_INC = @INC;
+ $pretype = [get_list("PERLDB_PRETYPE")];
+ $pre = [get_list("PERLDB_PRE")];
+ $post = [get_list("PERLDB_POST")];
+ @typeahead = get_list("PERLDB_TYPEAHEAD", @typeahead);
}
if ($notty) {
if (-e "/dev/tty") {
$console = "/dev/tty";
- } elsif (-e "con") {
+ } elsif (-e "con" or $^O eq 'MSWin32') {
$console = "con";
} else {
$console = "sys\$command";
&afterinit();
}
+$I_m_init = 1;
+
############################################################ Subroutines
sub DB {
$evalarg = $action, &eval if $action;
if ($single || $was_signal) {
local $level = $level + 1;
- map {$evalarg = $_, &eval} @$pre;
+ foreach $evalarg (@$pre) {
+ &eval;
+ }
print $OUT $#stack . " levels deep in subroutine calls!\n"
if $single & 4;
$start = $line;
print $OUT "Postponed breakpoints in files:\n";
my ($file, $line);
for $file (keys %postponed_file) {
- my %db = %{$postponed_file{$file}};
- next unless keys %db;
+ my $db = $postponed_file{$file};
print $OUT " $file:\n";
- for $line (sort {$a <=> $b} keys %db) {
+ for $line (sort {$a <=> $b} keys %$db) {
print $OUT " $line:\n";
- my ($stop,$action) = split(/\0/, $db{$line});
+ my ($stop,$action) = split(/\0/, $$db{$line});
print $OUT " break if (", $stop, ")\n"
if $stop;
print $OUT " action: ", $action, "\n"
for (0 .. $#had_breakpoints) {
my $file = $had_breakpoints[$_];
*dbline = $main::{'_<' . $file};
- next unless %dbline or %{$postponed_file{$file}};
+ next unless %dbline or $postponed_file{$file};
(push @hard, $file), next
if $file =~ /^\(eval \d+\)$/;
my @add;
@add = %{$postponed_file{$file}}
- if %{$postponed_file{$file}};
+ if $postponed_file{$file};
set_list("PERLDB_FILE_$_", %dbline, @add);
}
for (@hard) { # Yes, really-really...
}
}
set_list("PERLDB_POSTPONE", %postponed);
+ set_list("PERLDB_PRETYPE", @$pretype);
+ set_list("PERLDB_PRE", @$pre);
+ set_list("PERLDB_POST", @$post);
+ set_list("PERLDB_TYPEAHEAD", @typeahead);
$ENV{PERLDB_RESTART} = 1;
#print "$^X, '-d', @flags, @script, ($emacs ? '-emacs' : ()), @ARGS";
exec $^X, '-d', @flags, @script, ($emacs ? '-emacs' : ()), @ARGS;
}
} # CMD:
$exiting = 1 unless defined $cmd;
- map {$evalarg = $_; &eval} @$post;
+ foreach $evalarg (@$post) {
+ &eval;
+ }
} # if ($single || $signal)
($@, $!, $,, $/, $\, $^W) = @saved;
();
sub sub {
my ($al, $ret, @ret) = "";
- if ($sub =~ /(.*)::AUTOLOAD$/) {
- $al = " for $ {$1 . '::AUTOLOAD'}";
+ if (length($sub) > 10 && substr($sub, -10, 10) eq '::AUTOLOAD') {
+ $al = " for $$sub";
}
push(@stack, $single);
$single &= 1;
$signal = 1, print $OUT "'$filename' loaded...\n"
if $break_on_load{$filename};
print $LINEINFO ' ' x $#stack, "Package $filename.\n" if $frame;
- return unless %{$postponed_file{$filename}};
+ return unless $postponed_file{$filename};
$had_breakpoints{$filename}++;
#%dbline = %{$postponed_file{$filename}}; # Cannot be done: unsufficient magic
my $key;
for $key (keys %{$postponed_file{$filename}}) {
$dbline{$key} = $ {$postponed_file{$filename}}{$key};
}
- undef %{$postponed_file{$filename}};
+ delete $postponed_file{$filename};
}
sub dumpit {
} else {
$term = new Term::ReadLine 'perldb', $IN, $OUT;
- $readline::rl_basic_word_break_characters .= "[:"
- if defined $readline::rl_basic_word_break_characters
- and index($readline::rl_basic_word_break_characters, ":") == -1;
- $readline::rl_special_prefixes =
- $readline::rl_special_prefixes = '$@&%';
- $readline::rl_completer_word_break_characters =
- $readline::rl_completer_word_break_characters . '$@&%';
- $readline::rl_completion_function =
- $readline::rl_completion_function = \&db_complete;
+ $rl_attribs = $term->Attribs;
+ $rl_attribs->{basic_word_break_characters} .= '-:+/*,[])}'
+ if defined $rl_attribs->{basic_word_break_characters}
+ and index($rl_attribs->{basic_word_break_characters}, ":") == -1;
+ $rl_attribs->{special_prefixes} = '$@&%';
+ $rl_attribs->{completer_word_break_characters} .= '$@&%';
+ $rl_attribs->{completion_function} = \&db_complete;
}
$LINEINFO = $OUT unless defined $LINEINFO;
$lineinfo = $console unless defined $lineinfo;
if ($term->Features->{setHistory} and "@hist" ne "?") {
$term->SetHistory(@hist);
}
+ ornaments($ornaments) if defined $ornaments;
}
sub readline {
sub TTY {
if ($term) {
- &warn("Too late to set TTY!\n") if @_;
- } else {
- $tty = shift if @_;
- }
+ &warn("Too late to set TTY, enabled on next `R'!\n") if @_;
+ }
+ $tty = shift if @_;
$tty or $console;
}
sub noTTY {
if ($term) {
- &warn("Too late to set noTTY!\n") if @_;
- } else {
- $notty = shift if @_;
+ &warn("Too late to set noTTY, enabled on next `R'!\n") if @_;
}
+ $notty = shift if @_;
$notty;
}
sub ReadLine {
if ($term) {
- &warn("Too late to set ReadLine!\n") if @_;
- } else {
- $rl = shift if @_;
+ &warn("Too late to set ReadLine, enabled on next `R'!\n") if @_;
}
+ $rl = shift if @_;
$rl;
}
+sub tkRunning {
+ if ($ {$term->Features}{tkRunning}) {
+ return $term->tkRunning(@_);
+ } else {
+ print $OUT "tkRunning not supported by current ReadLine package.\n";
+ 0;
+ }
+}
+
sub NonStop {
if ($term) {
- &warn("Too late to set up NonStop mode!\n") if @_;
- } else {
- $runnonstop = shift if @_;
+ &warn("Too late to set up NonStop mode, enabled on next `R'!\n") if @_;
}
+ $runnonstop = shift if @_;
$runnonstop;
}
$psh;
}
+sub ornaments {
+ if (defined $term) {
+ local ($warnLevel,$dieLevel) = (0, 1);
+ return '' unless $term->Features->{ornaments};
+ eval { $term->ornaments(@_) } || '';
+ } else {
+ $ornaments = shift;
+ }
+}
+
sub recallCommand {
if (@_) {
$rc = quotemeta shift;
frame affects printing messages on entry and exit from subroutines.
AutoTrace affects printing messages on every possible breaking point.
maxTraceLen gives maximal length of evals/args listed in stack trace.
+ ornaments affects screen appearance of the command line.
During startup options are initialized from \$ENV{PERLDB_OPTS}.
You can put additional initialization options TTY, noTTY,
- ReadLine, and NonStop there.
+ ReadLine, and NonStop there (or use `R' after you set them).
< command Define Perl command to run before each prompt.
<< command Add to the list of Perl commands to run before each prompt.
> command Define Perl command to run after each prompt.
local $doret = -2;
$SIG{'ABRT'} = 'DEFAULT';
kill 'ABRT', $$ if $panic++;
- print $DB::OUT "Got $_[0]!\n"; # in the case cannot continue
- local $SIG{__WARN__} = '';
- require Carp;
- local $Carp::CarpLevel = 2; # mydie + confess
- &warn(Carp::longmess("Signal @_"));
+ if (defined &Carp::longmess) {
+ local $SIG{__WARN__} = '';
+ local $Carp::CarpLevel = 2; # mydie + confess
+ &warn(Carp::longmess("Signal @_"));
+ }
+ else {
+ print $DB::OUT "Got signal @_\n";
+ }
kill 'ABRT', $$;
}
$SIG{__DIE__} = \&DB::dbdie; # if $dieLevel < 2;
#$SIG{__DIE__} = \&DB::diehard if $dieLevel >= 2;
print $OUT "Stack dump during die enabled",
- ( $dieLevel == 1 ? " outside of evals" : ""), ".\n";
+ ( $dieLevel == 1 ? " outside of evals" : ""), ".\n"
+ if $I_m_init;
print $OUT "Dump printed too.\n" if $dieLevel > 2;
} else {
$SIG{__DIE__} = $prevdie;
$out = "=$val ";
}
# Default to value if one completion, to question if many
- $readline::rl_completer_terminator_character
- = $readline::rl_completer_terminator_character
- = (@out == 1 ? $out : '? ');
+ $rl_attribs->{completer_terminator_character} = (@out == 1 ? $out : '? ');
return sort @out;
}
- return &readline::rl_filename_list($text); # filenames
+ return $term->filename_list($text); # filenames
}
-sub end_report { print $OUT "Use `q' to quit and `R' to restart. `h q' for details.\n" }
+sub end_report {
+ print $OUT "Use `q' to quit or `R' to restart. `h q' for details.\n"
+}
END {
$finished = $inhibit_exit; # So that some keys may be disabled.
package DB::fake;
sub at_exit {
- "Debuggee terminated. Use `q' to quit and `R' to restart.";
+ "Debugged program terminated. Use `q' to quit or `R' to restart.";
}
package DB; # Do not trace this 1; below!