}
sub _DB__trim_command_and_return_first_component {
+ my ($obj) = @_;
+
$cmd =~ s/\A\s+//s; # trim annoying leading whitespace
$cmd =~ s/\s+\z//s; # trim annoying trailing whitespace
- $cmd =~ m{\A(\S*)};
- return $1;
+ my ($verb, $args) = $cmd =~ m{\A(\S*)\s*(.*)}s;
+
+ $obj->cmd_verb($verb);
+ $obj->cmd_args($args);
+
+ return;
}
sub _DB__handle_f_command {
- if (($file) = $cmd =~ /\Af\b\s*(.*)/) {
- $file =~ s/\s+$//;
+ my ($obj) = @_;
+ if ($file = $obj->cmd_args) {
# help for no arguments (old-style was return from sub).
if ( !$file ) {
print $OUT
my ($obj) = @_;
# . command.
- if ($cmd eq '.') {
+ if ($obj->_is_full('.')) {
$incr = -1; # stay at current line
# Reset everything to the old location.
my ($obj) = @_;
if (my ($match_level, $match_vars)
- = $cmd =~ /^y(?:\s+(\d*)\s*(.*))?$/) {
+ = $obj->cmd_args =~ /\A(?:(\d*)\s*(.*))?\z/) {
# See if we've got the necessary support.
if (!eval { require PadWalker; PadWalker->VERSION(0.08) }) {
my $Err = $@;
- DB::warn(
+ _db_warn(
$Err =~ /locate/
? "PadWalker module not found - please install\n"
: $Err
# Oops. Can't find it.
if (my $Err = $@) {
$Err =~ s/ at .*//;
- DB::warn($Err);
+ _db_warn($Err);
next CMD;
}
sub _DB__handle_c_command {
my ($obj) = @_;
- if (my ($new_i) = $cmd =~ m#\Ac\b\s*([\w:]*)\s*\z#) {
+ my $i = $obj->cmd_args;
- $obj->i_cmd($new_i);
+ if ($i =~ m#\A[\w:]*\z#) {
# Hey, show's over. The debugged program finished
# executing already.
next CMD if _DB__is_finished();
# Capture the place to put a one-time break.
- $subname = $obj->i_cmd;
+ $subname = $i;
# Probably not needed, since we finish an interactive
# sub-session anyway...
# to where the subroutine is defined; we call find_sub,
# break up the return value, and assign it in one
# operation.
- ( $file, $new_i ) = ( find_sub($subname) =~ /^(.*):(.*)$/ );
+ ( $file, $i ) = ( find_sub($subname) =~ /^(.*):(.*)$/ );
# Force the line number to be numeric.
- $obj->i_cmd($new_i + 0);
+ $i = $i + 0;
# If we got a line number, we found the sub.
- if ($obj->i_cmd) {
+ if ($i) {
# Switch all the debugger's internals around so
# we're actually working with that file.
# Scan forward to the first executable line
# after the 'sub whatever' line.
$max = $#dbline;
- my $ii = $obj->i_cmd;
- ++$ii while $dbline[$ii] == 0 && $ii < $max;
- $obj->i_cmd($ii);
+ my $_line_num = $i;
+ while ($dbline[$_line_num] == 0 && $_line_num< $max)
+ {
+ $_line_num++;
+ }
+ $i = $_line_num;
} ## end if ($i)
# We didn't find a sub by that name.
# On the gripping hand, we can't do anything unless the
# current value of $i points to a valid breakable line.
# Check that.
- if ($obj->i_cmd) {
+ if ($i) {
# Breakable?
- if ( $dbline[$obj->i_cmd] == 0 ) {
- print $OUT "Line " . $obj->i_cmd . " not breakable.\n";
+ if ( $dbline[$i] == 0 ) {
+ print $OUT "Line $i not breakable.\n";
next CMD;
}
# Yes. Set up the one-time-break sigil.
- $dbline{$obj->i_cmd} =~ s/($|\0)/;9$1/; # add one-time-only b.p.
- _enable_breakpoint_temp_enabled_status($filename, $obj->i_cmd);
+ $dbline{$i} =~ s/($|\0)/;9$1/; # add one-time-only b.p.
+ _enable_breakpoint_temp_enabled_status($filename, $i);
} ## end if ($i)
# Turn off stack tracing from here up.
- for my $i (0 .. $stack_depth) {
- $stack[ $i ] &= ~1;
+ for my $j (0 .. $stack_depth) {
+ $stack[ $j ] &= ~1;
}
last CMD;
}
sub _DB__handle_restart_and_rerun_commands {
my ($obj) = @_;
+ my $cmd_cmd = $obj->cmd_verb;
+ my $cmd_params = $obj->cmd_args;
# R - restart execution.
# rerun - controlled restart execution.
- if (my ($cmd_cmd, $cmd_params) =
- $cmd =~ /\A((?:R)|(?:rerun\s*(.*)))\z/) {
+ if ($cmd_cmd eq 'rerun' or $cmd_params eq '') {
my @args = ($cmd_cmd eq 'R' ? restart() : rerun($cmd_params));
# Close all non-system fds for a clean restart. A more
# Default pager is into a pipe. Redirect I/O.
open( SAVEOUT, ">&STDOUT" )
- || DB::warn("Can't save STDOUT");
+ || _db_warn("Can't save STDOUT");
open( STDOUT, ">&OUT" )
- || DB::warn("Can't redirect STDOUT");
+ || _db_warn("Can't redirect STDOUT");
} ## end if ($pager =~ /^\|/)
else {
# Not into a pipe. STDOUT is safe.
- open( SAVEOUT, ">&OUT" ) || &warn("Can't save DB::OUT");
+ open( SAVEOUT, ">&OUT" ) || _db_warn("Can't save DB::OUT");
}
# Fix up environment to record we have less if so.
unless ( $obj->piped(scalar ( open( OUT, $pager ) ) ) ) {
# Couldn't open pipe to pager.
- DB::warn("Can't pipe output to '$pager'");
+ _db_warn("Can't pipe output to '$pager'");
if ( $pager =~ /^\|/ ) {
# Redirect I/O back again.
open( OUT, ">&STDOUT" ) # XXX: lost message
- || DB::warn("Can't restore DB::OUT");
+ || _db_warn("Can't restore DB::OUT");
open( STDOUT, ">&SAVEOUT" )
- || DB::warn("Can't restore STDOUT");
+ || _db_warn("Can't restore STDOUT");
close(SAVEOUT);
} ## end if ($pager =~ /^\|/)
else {
# Redirect I/O. STDOUT already safe.
open( OUT, ">&STDOUT" ) # XXX: lost message
- || DB::warn("Can't restore DB::OUT");
+ || _db_warn("Can't restore DB::OUT");
}
next CMD;
} ## end unless ($piped = open(OUT,...
# Reopen filehandle for our output (if we can) and
# restore STDOUT (if we can).
- open( OUT, ">&STDOUT" ) || &warn("Can't restore DB::OUT");
+ open( OUT, ">&STDOUT" ) || _db_warn("Can't restore DB::OUT");
open( STDOUT, ">&SAVEOUT" )
- || &warn("Can't restore STDOUT");
+ || _db_warn("Can't restore STDOUT");
# Turn off pipe exception handler if necessary.
$SIG{PIPE} = "DEFAULT" if $SIG{PIPE} eq \&DB::catch;
else {
# Non-piped "pager". Just restore STDOUT.
- open( OUT, ">&SAVEOUT" ) || &warn("Can't restore DB::OUT");
+ open( OUT, ">&SAVEOUT" ) || _db_warn("Can't restore DB::OUT");
}
# Close filehandle pager was using, restore the normal one
(
'-' => { t => 'm', v => '_handle_dash_command', },
'.' => { t => 's', v => \&_DB__handle_dot_command, },
+ '=' => { t => 'm', v => '_handle_equal_sign_command', },
+ 'H' => { t => 'm', v => '_handle_H_command', },
'S' => { t => 'm', v => '_handle_S_command', },
'T' => { t => 'm', v => '_handle_T_command', },
+ 'W' => { t => 'm', v => '_handle_W_command', },
'c' => { t => 's', v => \&_DB__handle_c_command, },
'f' => { t => 's', v => \&_DB__handle_f_command, },
'm' => { t => 's', v => \&_DB__handle_m_command, },
'n' => { t => 'm', v => '_handle_n_command', },
+ 'p' => { t => 'm', v => '_handle_p_command', },
'q' => { t => 'm', v => '_handle_q_command', },
'r' => { t => 'm', v => '_handle_r_command', },
's' => { t => 'm', v => '_handle_s_command', },
+ 'save' => { t => 'm', v => '_handle_save_command', },
+ 'source' => { t => 'm', v => '_handle_source_command', },
't' => { t => 'm', v => '_handle_t_command', },
+ 'w' => { t => 'm', v => '_handle_w_command', },
'x' => { t => 'm', v => '_handle_x_command', },
'y' => { t => 's', v => \&_DB__handle_y_command, },
(map { $_ => { t => 'm', v => '_handle_V_command_and_X_command', }, }
('X', 'V')),
+ (map { $_ => { t => 'm', v => '_handle_enable_disable_commands', }, }
+ qw(enable disable)),
+ (map { $_ =>
+ { t => 's', v => \&_DB__handle_restart_and_rerun_commands, },
+ } qw(R rerun)),
+ (map { $_ => {t => 'm', v => '_handle_cmd_wrapper_commands' }, }
+ qw(a A b B e E h i l L M o O P v w W)),
);
sub DB {
$tid = eval { "[".threads->tid."]" };
}
- my $i;
+ my $cmd_verb;
+ my $cmd_args;
my $obj = DB::Obj->new(
{
after => \$after,
explicit_stop => \$explicit_stop,
infix => \$infix,
- i_cmd => \$i,
+ cmd_args => \$cmd_args,
+ cmd_verb => \$cmd_verb,
pat => \$pat,
piped => \$piped,
selected => \$selected,
# Preserve current values of $@, $!, $^E, $,, $/, $\, $^W.
# The code being debugged may have altered them.
- &save;
+ DB::save();
# Since DB::DB gets called after every line, we can use caller() to
# figure out where we last were executing. Sneaky, eh? This works because
# via direct user input. It allows us to 'redo PIPE' to
# re-execute command processing without reading a new command.
PIPE: {
- $i = _DB__trim_command_and_return_first_component();
+ _DB__trim_command_and_return_first_component($obj);
=head3 COMMAND ALIASES
=cut
# See if there's an alias for the command, and set it up if so.
- if ( $alias{$i} ) {
+ if ( $alias{$cmd_verb} ) {
# Squelch signal handling; we want to keep control here
# if something goes loco during the alias eval.
# scope! Otherwise, we can't see the special debugger
# variables, or get to the debugger's subs. (Well, we
# _could_, but why make it even more complicated?)
- eval "\$cmd =~ $alias{$i}";
+ eval "\$cmd =~ $alias{$cmd_verb}";
if ($@) {
local $\ = '';
- print $OUT "Couldn't evaluate '$i' alias: $@";
+ print $OUT "Couldn't evaluate '$cmd_verb' alias: $@";
next CMD;
}
- $i = _DB__trim_command_and_return_first_component();
- } ## end if ($alias{$i})
+ _DB__trim_command_and_return_first_component($obj);
+ } ## end if ($alias{$cmd_verb})
=head3 MAIN-LINE COMMANDS
=cut
- if (my $cmd_rec = $cmd_lookup{$i}) {
+ # All of these commands were remapped in perl 5.8.0;
+ # we send them off to the secondary dispatcher (see below).
+ $obj->_handle_special_char_cmd_wrapper_commands;
+ _DB__trim_command_and_return_first_component($obj);
+
+ if (my $cmd_rec = $cmd_lookup{$cmd_verb}) {
my $type = $cmd_rec->{t};
my $val = $cmd_rec->{v};
if ($type eq 'm') {
Turn tracing on or off. Inverts the appropriate bit in C<$trace> (q.v.).
If level is specified, set C<$trace_to_depth>.
-=cut
-
=head4 C<S> - list subroutines matching/not matching a pattern
Walks through C<%sub>, checking to see whether or not to print the name.
-=cut
-
=head4 C<X> - list variables in current package
Since the C<V> command actually processes this, just change this to the
Uses C<dumpvar.pl> to dump out the current values for selected variables.
-=cut
-
=head4 C<x> - evaluate and print an expression
Hands the expression off to C<DB::eval>, setting it up to print the value
via C<dumpvar.pl> instead of just printing it directly.
-=cut
-
=head4 C<m> - print methods
Just uses C<DB::methods> to determine what methods are available.
-=cut
-
=head4 C<f> - switch files
-=cut
+Switch to a different filename.
=head4 C<.> - return to last-executed line.
We set C<$incr> to -1 to indicate that the debugger shouldn't move ahead,
and then we look up the line in the magical C<%dbline> hash.
-=cut
-
=head4 C<-> - back one window
We change C<$start> to be one window back; if we go back past the first line,
them. At this point, we check for the new commands and call C<cmd_wrapper> to
deal with them instead of processing them in-line.
-=cut
-
- # All of these commands were remapped in perl 5.8.0;
- # we send them off to the secondary dispatcher (see below).
- $obj->_handle_cmd_wrapper_commands;
-
=head4 C<y> - List lexicals in higher scope
Uses C<PadWalker> to find the lexicals supplied as arguments in a scope
Just calls C<DB::cmd_w>.
-=cut
-
- $obj->_handle_w_command;
-
=head4 C<W> - watch-expression processing.
Just calls C<DB::cmd_W>.
-=cut
-
- $obj->_handle_W_command;
-
=head4 C</> - search forward for a string in the source
We take the argument and treat it as a pattern. If it turns out to be a
=head4 C<$sh$sh> - C<system()> command
-Calls the C<DB::system()> to handle the command. This keeps the C<STDIN> and
+Calls the C<_db_system()> to handle the command. This keeps the C<STDIN> and
C<STDOUT> from getting messed up.
=cut
=head4 C<$sh> - Invoke a shell
-Uses C<DB::system> to invoke a shell.
+Uses C<_db_system()> to invoke a shell.
=cut
=head4 C<$sh I<command>> - Force execution of a command in a shell
Like the above, but the command is passed to the shell. Again, we use
-C<DB::system> to avoid problems with C<STDIN> and C<STDOUT>.
+C<_db_system()> to avoid problems with C<STDIN> and C<STDOUT>.
=head4 C<H> - display commands in history
Prints the contents of C<@hist> (if any).
-=cut
-
- $obj->_handle_H_command;
-
=head4 C<man, doc, perldoc> - look up documentation
Just calls C<runman()> to print the appropriate document.
Builds a C<print EXPR> expression in the C<$cmd>; this will get executed at
the bottom of the loop.
-=cut
-
- $obj->_handle_p_command;
-
=head4 C<=> - define command alias
Manipulates C<%alias> to add or list command aliases.
-=cut
-
- # = - set up a command alias.
- $obj->_handle_equal_sign_command;
-
=head4 C<source> - read commands from a file.
Opens a lexical filehandle and stacks it on C<@cmdfhs>; C<DB::readline> will
pick it up.
-=cut
-
- $obj->_handle_source_command;
-
=head4 C<enable> C<disable> - enable or disable breakpoints
This enables or disables breakpoints.
-=cut
-
- $obj->_handle_enable_disable_commands;
-
=head4 C<save> - send current history to a file
Takes the complete history, (not the shrunken version you see with C<H>),
Note that all C<^(save|source)>'s are commented out with a view to minimise recursion.
-=cut
-
- # save source - write commands to a file for later use
- $obj->_handle_save_command;
-
=head4 C<R> - restart
Restart the debugger session.
Return to any given position in the B<true>-history list
-=cut
-
- # R - restart execution.
- # rerun - controlled restart execution.
- _DB__handle_restart_and_rerun_commands($obj);
-
=head4 C<|, ||> - pipe output through the pager.
For C<|>, we save C<OUT> (the debugger's output filehandle) and C<STDOUT>
{
no strict 'refs';
foreach my $slot_name (qw(
- after explicit_stop infix pat piped position prefix selected i_cmd
+ after explicit_stop infix pat piped position prefix selected cmd_verb
+ cmd_args
)) {
my $slot = $slot_name;
*{$slot} = sub {
return $DB::dbline[$line];
}
+sub _is_full {
+ my ($self, $letter) = @_;
+
+ return ($DB::cmd eq $letter);
+}
+
sub _DB__grab_control
{
my $self = shift;
}
sub _handle_t_command {
- if (my ($levels) = $DB::cmd =~ /\At(?:\s+(\d+))?\z/) {
+ my $self = shift;
+
+ my $levels = $self->cmd_args();
+
+ if ((!length($levels)) or ($levels !~ /\D/)) {
$trace ^= 1;
local $\ = '';
$DB::trace_to_depth = $levels ? $stack_depth + $levels : 1E9;
sub _handle_S_command {
+ my $self = shift;
+
if (my ($print_all_subs, $should_reverse, $Spatt)
- = $DB::cmd =~ /\AS(\s+(!)?(.+))?\z/) {
+ = $self->cmd_args =~ /\A((!)?(.+))?\z/) {
# $Spatt is the pattern (if any) to use.
# Reverse scan?
my $Srev = defined $should_reverse;
}
sub _handle_V_command_and_X_command {
+ my $self = shift;
$DB::cmd =~ s/^X\b/V $DB::package/;
# Bare V commands get the currently-being-debugged package
# added.
- if ($DB::cmd eq "V") {
+ if ($self->_is_full('V')) {
$DB::cmd = "V $DB::package";
}
# must detect sigpipe failures - not catching
# then will cause the debugger to die.
eval {
- &main::dumpvar(
+ main::dumpvar(
$packname,
defined $option{dumpDepth}
? $option{dumpDepth}
}
sub _handle_dash_command {
+ my $self = shift;
- if ($DB::cmd eq '-') {
+ if ($self->_is_full('-')) {
# back up by a window; go to 1 if back too far.
$start -= $incr + $window + 1;
# Generate and execute a "l +" command (handled below).
$DB::cmd = 'l ' . ($start) . '+';
+ redo CMD;
}
return;
}
sub _n_or_s {
my ($self, $letter, $new_val) = @_;
- if ($DB::cmd eq $letter) {
+ if ($self->_is_full($letter)) {
$self->_n_or_s_commands_generic($new_val);
}
- elsif ($DB::cmd =~ m#\A\Q$letter\E\b#) {
+ else {
$self->_n_or_s_and_arg_commands_generic($letter, $new_val);
}
sub _handle_r_command {
my $self = shift;
+
# r - return from the current subroutine.
- if ($DB::cmd eq 'r') {
+ if ($self->_is_full('r')) {
# Can't do anything if the program's over.
next CMD if DB::_DB__is_finished();
}
sub _handle_T_command {
- if ($DB::cmd eq 'T') {
+ my $self = shift;
+
+ if ($self->_is_full('T')) {
DB::print_trace( $OUT, 1 ); # skip DB
next CMD;
}
}
sub _handle_w_command {
- if (my ($arg) = $DB::cmd =~ /\Aw\b\s*(.*)/s) {
- DB::cmd_w( 'w', $arg );
- next CMD;
- }
+ my $self = shift;
+
+ DB::cmd_w( 'w', $self->cmd_args() );
+ next CMD;
return;
}
sub _handle_W_command {
- if (my ($arg) = $DB::cmd =~ /\AW\b\s*(.*)/s) {
+ my $self = shift;
+
+ if (my $arg = $self->cmd_args) {
DB::cmd_W( 'W', $arg );
next CMD;
}
# Y - index back from most recent (by 1 if bare minus)
# N - go to that particular command slot or the last
# thing if nothing following.
- my $new_i = $minus ? ( $#hist - ( $arg || 1 ) ) : ( $arg || $#hist );
- $self->i_cmd($new_i);
+ $self->cmd_verb(
+ scalar($minus ? ( $#hist - ( $arg || 1 ) ) : ( $arg || $#hist ))
+ );
# Pick out the command desired.
- $DB::cmd = $hist[$self->i_cmd];
+ $DB::cmd = $hist[$self->cmd_verb];
# Print the command to be executed and restart the loop
# with that command in the buffer.
# Toss off last entry if length is >1 (and it always is).
pop(@hist) if length($DB::cmd) > 1;
- my $i = $self->i_cmd;
+ my $i;
# Look backward through the history.
SEARCH_HIST:
last SEARCH_HIST if $hist[$i] =~ /$pat/;
}
- $self->i_cmd($i);
-
- if ( !$self->i_cmd ) {
+ if ( !$i ) {
# Never found it.
print $OUT "No such command!\n\n";
}
# Found it. Put it in the buffer, print it, and process it.
- $DB::cmd = $hist[$self->i_cmd];
+ $DB::cmd = $hist[$i];
print $OUT $DB::cmd, "\n";
redo CMD;
}
sub _handle_H_command {
my $self = shift;
- if ($DB::cmd =~ /\AH\b\s*\*/) {
+ if ($self->cmd_args =~ m#\A\*#) {
@hist = @truehist = ();
print $OUT "History cleansed\n";
next CMD;
}
- if (my ($num)
- = $DB::cmd =~ /\AH\b\s*(?:-(\d+))?/) {
+ if (my ($num) = $self->cmd_args =~ /\A(?:-(\d+))?/) {
# Anything other than negative numbers is ignored by
# the (incorrect) pattern, so this test does nothing.
unless $hist[$i] =~ /^.?$/;
}
- $self->i_cmd($i);
-
next CMD;
}
my $print_cmd = 'print {$DB::OUT} ';
# p - print (no args): print $_.
- if ($DB::cmd eq 'p') {
+ if ($self->_is_full('p')) {
$DB::cmd = $print_cmd . '$_';
}
-
- # p - print the given expression.
- $DB::cmd =~ s/\Ap\b/$print_cmd /;
+ else {
+ # p - print the given expression.
+ $DB::cmd =~ s/\Ap\b/$print_cmd /;
+ }
return;
}
my $self = shift;
# source - read commands from a file (or pipe!) and execute.
- if (my ($sourced_fn) = $DB::cmd =~ /\Asource\s+(.*\S)/) {
+ if (my $sourced_fn = $self->cmd_args) {
if ( open my $fh, $sourced_fn ) {
# Opened OK; stick it in the list of file handles.
else {
# Couldn't open it.
- DB::warn("Can't execute '$sourced_fn': $!\n");
+ DB::_db_warn("Can't execute '$sourced_fn': $!\n");
}
next CMD;
}
sub _handle_enable_disable_commands {
my $self = shift;
- if (my ($which_cmd, $position)
- = $DB::cmd =~ /\A(enable|disable)\s+(\S+)\s*\z/) {
+ my $which_cmd = $self->cmd_verb;
+ my $position = $self->cmd_args;
+ if ($position !~ /\s/) {
my ($fn, $line_num);
if ($position =~ m{\A\d+\z})
{
}
else
{
- DB::warn("Wrong spec for enable/disable argument.\n");
+ DB::_db_warn("Wrong spec for enable/disable argument.\n");
}
if (defined($fn)) {
);
}
else {
- DB::warn("No breakpoint set at ${fn}:${line_num}\n");
+ DB::_db_warn("No breakpoint set at ${fn}:${line_num}\n");
}
}
sub _handle_save_command {
my $self = shift;
- if (my ($new_fn) = $DB::cmd =~ /\Asave\s*(.*)\z/) {
+ if (my $new_fn = $self->cmd_args) {
my $filename = $new_fn || '.perl5dbrc'; # default?
if ( open my $fh, '>', $filename ) {
print "commands saved in $filename\n";
}
else {
- DB::warn("Can't save debugger commands in '$new_fn': $!\n");
+ DB::_db_warn("Can't save debugger commands in '$new_fn': $!\n");
}
next CMD;
}
if ($my_cmd =~ m#\G\z#cgms) {
# Run the user's shell. If none defined, run Bourne.
# We resume execution when the shell terminates.
- DB::system( $ENV{SHELL} || "/bin/sh" );
+ DB::_db_system( $ENV{SHELL} || "/bin/sh" );
next CMD;
}
elsif ($my_cmd =~ m#\G$sh\s*(.*)#cgms) {
# System it.
- DB::system($1);
+ DB::_db_system($1);
next CMD;
}
elsif ($my_cmd =~ m#\G\s*(.*)#cgms) {
- DB::system( $ENV{SHELL} || "/bin/sh", "-c", $1 );
+ DB::_db_system( $ENV{SHELL} || "/bin/sh", "-c", $1 );
next CMD;
}
}
sub _handle_q_command {
my $self = shift;
- if ($DB::cmd eq 'q') {
+ if ($self->_is_full('q')) {
$fall_off_end = 1;
DB::clean_ENV();
exit $?;
sub _handle_cmd_wrapper_commands {
my $self = shift;
+ DB::cmd_wrapper( $self->cmd_verb, $self->cmd_args, $line );
+ next CMD;
+}
+
+sub _handle_special_char_cmd_wrapper_commands {
+ my $self = shift;
+
# All of these commands were remapped in perl 5.8.0;
# we send them off to the secondary dispatcher (see below).
- if (my ($cmd_letter, $my_arg) = $DB::cmd =~ /\A([aAbBeEhilLMoOPvwW]\b|[<>\{]{1,2})\s*(.*)/so) {
+ if (my ($cmd_letter, $my_arg) = $DB::cmd =~ /\A([<>\{]{1,2})\s*(.*)/so) {
DB::cmd_wrapper( $cmd_letter, $my_arg, $line );
next CMD;
}
return;
}
+
package DB;
# The following code may be executed now:
# We need to fully qualify the name ("DB::sub") to make "use strict;"
# happy. -- Shlomi Fish
+
+sub _indent_print_line_info {
+ my ($offset, $str) = @_;
+
+ print_lineinfo( ' ' x ($stack_depth - $offset), $str);
+
+ return;
+}
+
+sub _print_frame_message {
+ my ($al) = @_;
+
+ if ($frame) {
+ if ($frame & 4) { # Extended frame entry message
+ _indent_print_line_info(-1, "in ");
+
+ # Why -1? But it works! :-(
+ # Because print_trace will call add 1 to it and then call
+ # dump_trace; this results in our skipping -1+1 = 0 stack frames
+ # in dump_trace.
+ #
+ # Now it's 0 because we extracted a function.
+ print_trace( $LINEINFO, 0, 1, 1, "$sub$al" );
+ }
+ else {
+ _indent_print_line_info(-1, "entering $sub$al\n" );
+ }
+ }
+
+ return;
+}
+
sub DB::sub {
# Do not use a regex in this subroutine -> results in corrupted memory
# See: [perl #66110]
$single |= 4 if $stack_depth == $deep;
# If frame messages are on ...
- (
- $frame & 4 # Extended frame entry message
- ? (
- print_lineinfo( ' ' x ( $stack_depth - 1 ), "in " ),
- # Why -1? But it works! :-(
- # Because print_trace will call add 1 to it and then call
- # dump_trace; this results in our skipping -1+1 = 0 stack frames
- # in dump_trace.
- print_trace( $LINEINFO, -1, 1, 1, "$sub$al" )
- )
- : print_lineinfo( ' ' x ( $stack_depth - 1 ), "entering $sub$al\n" )
+ _print_frame_message($al);
+ # standard frame entry message
- # standard frame entry message
- )
- if $frame;
+ my $print_exit_msg = sub {
+ # Check for exit trace messages...
+ if ($frame & 2)
+ {
+ if ($frame & 4) # Extended exit message
+ {
+ _indent_print_line_info(0, "out ");
+ print_trace( $LINEINFO, 0, 1, 1, "$sub$al" );
+ }
+ else
+ {
+ _indent_print_line_info(0, "exited $sub$al\n" );
+ }
+ }
+ return;
+ };
# Determine the sub's return type, and capture appropriately.
if (wantarray) {
# Pop the single-step value back off the stack.
$single |= $stack[ $stack_depth-- ];
- # Check for exit trace messages...
- (
- $frame & 4 # Extended exit message
- ? (
- print_lineinfo( ' ' x $stack_depth, "out " ),
- print_trace( $LINEINFO, -1, 1, 1, "$sub$al" )
- )
- : print_lineinfo( ' ' x $stack_depth, "exited $sub$al\n" )
-
- # Standard exit message
- )
- if $frame & 2;
+ $print_exit_msg->();
# Print the return info if we need to.
if ( $doret eq $stack_depth or $frame & 16 ) {
my $fh = ( $doret eq $stack_depth ? $OUT : $LINEINFO );
# Indent if we're printing because of $frame tracing.
- print $fh ' ' x $stack_depth if $frame & 16;
+ if ($frame & 16)
+ {
+ print {$fh} ' ' x $stack_depth;
+ }
# Print the return value.
- print $fh "list context return from $sub:\n";
+ print {$fh} "list context return from $sub:\n";
dumpit( $fh, \@ret );
# And don't print it again.
$single |= $stack[ $stack_depth-- ];
# If we're doing exit messages...
- (
- $frame & 4 # Extended messages
- ? (
- print_lineinfo( ' ' x $stack_depth, "out " ),
- print_trace( $LINEINFO, -1, 1, 1, "$sub$al" )
- )
- : print_lineinfo( ' ' x $stack_depth, "exited $sub$al\n" )
-
- # Standard messages
- )
- if $frame & 2;
+ $print_exit_msg->();
# If we are supposed to show the return value... same as before.
if ( $doret eq $stack_depth or $frame & 16 and defined wantarray ) {
$single |= 4 if $stack_depth == $deep;
# If frame messages are on ...
- (
- $frame & 4 # Extended frame entry message
- ? (
- print_lineinfo( ' ' x ( $stack_depth - 1 ), "in " ),
-
- # Why -1? But it works! :-(
- # Because print_trace will call add 1 to it and then call
- # dump_trace; this results in our skipping -1+1 = 0 stack frames
- # in dump_trace.
- print_trace( $LINEINFO, -1, 1, 1, "$sub$al" )
- )
- : print_lineinfo( ' ' x ( $stack_depth - 1 ), "entering $sub$al\n" )
-
- # standard frame entry message
- )
- if $frame;
+ _print_frame_message($al);
# Pop the single-step value back off the stack.
$single |= $stack[ $stack_depth-- ];
=cut
sub cmd_b_sub {
- my ( $subname, $cond ) = @_;
-
- # Add always-true condition if we have none.
- $cond = 1 unless @_ >= 2;
+ my $subname = shift;
+ my $cond = @_ ? shift : 1;
# If the subname isn't a code reference, qualify it so that
# break_subroutine() will work right.
- unless ( ref $subname eq 'CODE' ) {
+ if ( ref($subname) ne 'CODE' ) {
- # Not Perl4.
- $subname =~ s/\'/::/g;
+ # Not Perl 4.
+ $subname =~ s/'/::/g;
my $s = $subname;
# Put it in this package unless it's already qualified.
- $subname = "${package}::" . $subname
- unless $subname =~ /::/;
+ if ($subname !~ /::/)
+ {
+ $subname = $package . '::' . $subname;
+ };
# Requalify it into CORE::GLOBAL if qualifying it into this
# package resulted in its not being defined, but only do so
# if it really is in CORE::GLOBAL.
- $subname = "CORE::GLOBAL::$s"
- if not defined &$subname
- and $s !~ /::/
- and defined &{"CORE::GLOBAL::$s"};
+ my $core_name = "CORE::GLOBAL::$s";
+ if ((!defined(&$subname))
+ and ($s !~ /::/)
+ and (defined &{$core_name}))
+ {
+ $subname = $core_name;
+ }
# Put it in package 'main' if it has a leading ::.
- $subname = "main" . $subname if substr( $subname, 0, 2 ) eq "::";
-
- } ## end unless (ref $subname eq 'CODE')
+ if ($subname =~ /\A::/)
+ {
+ $subname = "main" . $subname;
+ }
+ } ## end if ( ref($subname) ne 'CODE' ) {
# Try to set the breakpoint.
if (not eval { break_subroutine( $subname, $cond ); 1 }) {
local $\ = '';
- print $OUT $@ and return;
+ print {$OUT} $@;
+ return;
}
return;
# If no argument, list everything. Pre-5.8.0 version always lists
# everything
my $arg = shift || 'abw';
- $arg = 'abw' unless $CommandSet eq '580'; # sigh...
+ if ($CommandSet ne '580')
+ {
+ $arg = 'abw';
+ }
# See what is wanted.
my $action_wanted = ( $arg =~ /a/ ) ? 1 : 0;
# Nonblank. Try to parse and process.
if ( $opt =~ /^(\S.*)/ ) {
- &parse_options($1);
+ parse_options($1);
}
# Blank. List the current option settings.
else {
for (@options) {
- &dump_option($_);
+ dump_option($_);
}
}
} ## end sub cmd_o
}
# If this is a subroutine, let postponed_sub() deal with it.
- return &postponed_sub unless ref \$_[0] eq 'GLOB';
+ if (ref(\$_[0]) ne 'GLOB') {
+ return postponed_sub(@_);
+ }
# Not a subroutine. Deal with the file.
local *dbline = shift;
my $v = shift;
my $maxdepth = shift || $option{dumpDepth};
$maxdepth = -1 unless defined $maxdepth; # -1 means infinite depth
- &main::dumpValue( $v, $maxdepth );
+ main::dumpValue( $v, $maxdepth );
} ## end if (defined &main::dumpValue)
# Oops, couldn't load dumpvar.pl.
while ( $action =~ s/\\$// ) {
# We have a backslash on the end. Read more.
- $action .= &gets;
+ $action .= gets();
} ## end while ($action =~ s/\\$//)
# Return the assembled action.
=cut
sub gets {
- &readline("cont: ");
+ return DB::readline("cont: ");
}
-=head2 C<DB::system()> - handle calls to<system()> without messing up the debugger
+=head2 C<_db_system()> - handle calls to<system()> without messing up the debugger
The C<system()> function assumes that it can just go ahead and use STDIN and
STDOUT, but under the debugger, we want it to use the debugger's input and
outout filehandles.
-C<DB::system()> socks away the program's STDIN and STDOUT, and then substitutes
+C<_db_system()> socks away the program's STDIN and STDOUT, and then substitutes
the debugger's IN and OUT filehandles for them. It does the C<system()> call,
and then puts everything back again.
=cut
-sub system {
+sub _db_system {
# We save, change, then restore STDIN and STDOUT to avoid fork() since
# some non-Unix systems can do system() but have problems with fork().
- open( SAVEIN, "<&STDIN" ) || DB::warn("Can't save STDIN");
- open( SAVEOUT, ">&STDOUT" ) || DB::warn("Can't save STDOUT");
- open( STDIN, "<&IN" ) || DB::warn("Can't redirect STDIN");
- open( STDOUT, ">&OUT" ) || DB::warn("Can't redirect STDOUT");
+ open( SAVEIN, "<&STDIN" ) || db_warn("Can't save STDIN");
+ open( SAVEOUT, ">&STDOUT" ) || db_warn("Can't save STDOUT");
+ open( STDIN, "<&IN" ) || db_warn("Can't redirect STDIN");
+ open( STDOUT, ">&OUT" ) || db_warn("Can't redirect STDOUT");
# XXX: using csh or tcsh destroys sigint retvals!
system(@_);
- open( STDIN, "<&SAVEIN" ) || DB::warn("Can't restore STDIN");
- open( STDOUT, ">&SAVEOUT" ) || DB::warn("Can't restore STDOUT");
+ open( STDIN, "<&SAVEIN" ) || db_warn("Can't restore STDIN");
+ open( STDOUT, ">&SAVEOUT" ) || db_warn("Can't restore STDOUT");
close(SAVEIN);
close(SAVEOUT);
# most of the $? crud was coping with broken cshisms
if ( $? >> 8 ) {
- DB::warn( "(Command exited ", ( $? >> 8 ), ")\n" );
+ db_warn( "(Command exited ", ( $? >> 8 ), ")\n" );
}
elsif ($?) {
- DB::warn(
+ db_warn(
"(Command died of SIG#",
( $? & 127 ),
( ( $? & 128 ) ? " -- core dumped" : "" ),
} ## end sub system
+*system = \&_db_system;
+
=head1 TTY MANAGEMENT
The subs here do some of the terminal management for multiple debuggers.
$term->MinLine(2);
- &load_hist();
+ load_hist();
if ( $term->Features->{setHistory} and "@hist" ne "?" ) {
$term->SetHistory(@hist);
# If we know how to get a new TTY, do it! $in will have
# the TTY name if get_fork_TTY works.
- my $in = &get_fork_TTY if defined &get_fork_TTY;
+ my $in = get_fork_TTY(@_) if defined &get_fork_TTY;
# It used to be that
$in = $fork_TTY if defined $fork_TTY; # Backward compatibility
=cut
-sub warn {
+sub _db_warn {
my ($msg) = join( "", @_ );
$msg .= ": $!\n" unless $msg =~ /\n$/;
local $\ = '';
print $OUT $msg;
} ## end sub warn
+*warn = \&_db_warn;
+
=head1 INITIALIZATION TTY SUPPORT
=head2 C<reset_IN_OUT>
# This term can't get a new tty now. Better luck later.
elsif ($term) {
- &warn("Too late to set IN/OUT filehandles, enabled on next 'R'!\n");
+ _db_warn("Too late to set IN/OUT filehandles, enabled on next 'R'!\n");
}
# Set the filehndles up as they were.
# Terminal doesn't support new TTY, or doesn't support readline.
# Can't do it now, try restarting.
- &warn("Too late to set TTY, enabled on next 'R'!\n") if $term and @_;
+ if ($term and @_) {
+ _db_warn("Too late to set TTY, enabled on next 'R'!\n");
+ }
# Useful if done through PERLDB_OPTS:
$console = $tty = shift if @_;
sub noTTY {
if ($term) {
- &warn("Too late to set noTTY, enabled on next 'R'!\n") if @_;
+ _db_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, enabled on next 'R'!\n") if @_;
+ _db_warn("Too late to set ReadLine, enabled on next 'R'!\n") if @_;
}
$rl = shift if @_;
$rl;
sub RemotePort {
if ($term) {
- &warn("Too late to set RemotePort, enabled on next 'R'!\n") if @_;
+ _db_warn("Too late to set RemotePort, enabled on next 'R'!\n") if @_;
}
$remoteport = shift if @_;
$remoteport;
sub NonStop {
if ($term) {
- &warn("Too late to set up NonStop mode, enabled on next 'R'!\n")
+ _db_warn("Too late to set up NonStop mode, enabled on next 'R'!\n")
if @_;
}
$runnonstop = shift if @_;
sub DollarCaretP {
if ($term) {
- &warn("Some flag changes could not take effect until next 'R'!\n")
+ _db_warn("Some flag changes could not take effect until next 'R'!\n")
if @_;
}
$^P = parse_DollarCaretP_flags(shift) if @_;
# If this is a pipe, the stream points to a slave editor.
$slave_editor = ( $stream =~ /^\|/ );
+ my $new_lineinfo_fh;
# Open it up and unbuffer it.
- open( LINEINFO, $stream ) || &warn("Cannot open '$stream' for write");
- $LINEINFO = \*LINEINFO;
+ open ($new_lineinfo_fh , $stream )
+ or _db_warn("Cannot open '$stream' for write");
+ $LINEINFO = $new_lineinfo_fh;
$LINEINFO->autoflush(1);
}
local $Carp::CarpLevel = 2; # mydie + confess
# Tell us all about it.
- &warn( Carp::longmess("Signal @_") );
+ _db_warn( Carp::longmess("Signal @_") );
}
# No Carp. Tell us about the signal as best we can.
# Use the debugger's own special way of printing warnings to print
# the stack trace message.
- &warn($mess);
+ _db_warn($mess);
} ## end sub dbwarn
=head2 C<dbdie>
local $doret = -2;
local $SIG{__DIE__} = '';
local $SIG{__WARN__} = '';
- my $i = 0;
- my $ineval = 0;
- my $sub;
if ( $dieLevel > 2 ) {
local $SIG{__WARN__} = \&dbwarn;
- &warn(@_); # Yell no matter what
+ _db_warn(@_); # Yell no matter what
return;
}
if ( $dieLevel < 2 ) {
=head2 C<runman> - run the appropriate command to show documentation
Accepts a man page name; runs the appropriate command to display it (set up
-during debugger initialization). Uses C<DB::system> to avoid mucking up the
+during debugger initialization). Uses C<_db_system()> to avoid mucking up the
program's STDIN and STDOUT.
=cut
sub runman {
my $page = shift;
unless ($page) {
- &system("$doccmd $doccmd");
+ _db_system("$doccmd $doccmd");
return;
}
# this way user can override, like with $doccmd="man -Mwhatever"
# or even just "man " to disable the path check.
- unless ( $doccmd eq 'man' ) {
- &system("$doccmd $page");
+ if ( $doccmd ne 'man' ) {
+ _db_system("$doccmd $page");
return;
}
my @temp = @truehist; # store
push(@DB::typeahead, @truehist); # saved
@truehist = @hist = (); # flush
- @args = &restart(); # setup
- &get_list("PERLDB_HIST"); # clean
- &set_list("PERLDB_HIST", @temp); # reset
+ @args = restart(); # setup
+ get_list("PERLDB_HIST"); # clean
+ set_list("PERLDB_HIST", @temp); # reset
}
return @args;
}
# Do not stop in at_exit() and destructors on exit:
if ($fall_off_end or $runnonstop) {
- &save_hist();
+ save_hist();
} else {
$DB::single = 1;
DB::fake::at_exit();
if ( $cmd =~ /^load\b\s*(.*)/ ) {
my $file = $1;
$file =~ s/\s+$//;
- &cmd_b_load($file);
+ cmd_b_load($file);
}
# b compile|postpone <some sub> [<condition>]
elsif ( $cmd =~ /^([':A-Za-z_][':\w]*(?:\[.*\])?)\s*(.*)/ ) {
my $subname = $1;
my $cond = length $2 ? $2 : '1';
- &cmd_b_sub( $subname, $cond );
+ cmd_b_sub( $subname, $cond );
}
# b <line> [<condition>].
elsif ( $cmd =~ /^(\d*)\s*(.*)/ ) {
my $i = $1 || $dbline;
my $cond = length $2 ? $2 : '1';
- &cmd_b_line( $i, $cond );
+ cmd_b_line( $i, $cond );
}
} ## end sub cmd_pre580_b
my $line = shift || '*';
my $dbline = shift;
- return &cmd_prepost( $cmd, $line, $dbline );
+ return cmd_prepost( $cmd, $line, $dbline );
} ## end sub cmd_pre590_prepost
=head2 C<cmd_prepost>