This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Re: dumpvar.pl bug
[perl5.git] / lib / perl5db.pl
index aab1a68..158510d 100644 (file)
@@ -1,16 +1,53 @@
 package DB;
 
 # Debugger for Perl 5.00x; perl5db.pl patch level:
+$VERSION = 1.17;
+$header  = "perl5db.pl version $VERSION";
 
-$VERSION = 1.14;
-$header = "perl5db.pl version $VERSION";
+# It is crucial that there is no lexicals in scope of `eval ""' down below
+sub eval {
+    # 'my' would make it visible from user code
+    #    but so does local! --tchrist  [... into @DB::res, not @res. IZ]
+    local @res;
+    {
+       local $otrace = $trace;
+       local $osingle = $single;
+       local $od = $^D;
+       { ($evalarg) = $evalarg =~ /(.*)/s; }
+       @res = eval "$usercontext $evalarg;\n"; # '\n' for nice recursive debug
+       $trace = $otrace;
+       $single = $osingle;
+       $^D = $od;
+    }
+    my $at = $@;
+    local $saved[0];           # Preserve the old value of $@
+    eval { &DB::save };
+    if ($at) {
+       local $\ = '';
+       print $OUT $at;
+    } elsif ($onetimeDump) {
+      if ($onetimeDump eq 'dump')  {
+        local $option{dumpDepth} = $onetimedumpDepth 
+          if defined $onetimedumpDepth;
+       dumpit($OUT, \@res);
+      } elsif ($onetimeDump eq 'methods') {
+       methods($res[0]) ;
+      }
+    }
+    @res;
+}
 
+# After this point it is safe to introduce lexicals
+# However, one should not overdo it: leave as much control from outside as possible
 #
 # This file is automatically included if you do perl -d.
 # It's probably not useful to include this yourself.
 #
+# Before venturing further into these twisty passages, it is 
+# wise to read the perldebguts man page or risk the ire of dragons.
+#
 # Perl supplies the values for %sub.  It effectively inserts
-# a &DB'DB(); in front of every place that can have a
+# a &DB::DB(); in front of every place that can have a
 # breakpoint. Instead of a subroutine call it calls &DB::sub with
 # $DB::sub being the called subroutine. It also inserts a BEGIN
 # {require 'perl5db.pl'} before the first line.
@@ -25,14 +62,15 @@ $header = "perl5db.pl version $VERSION";
 # if caller() is called from the package DB, it provides some
 # additional data.
 #
-# The array @{$main::{'_<'.$filename}} is the line-by-line contents of
-# $filename.
+# The array @{$main::{'_<'.$filename}} (herein called @dbline) is the
+# line-by-line contents of $filename.
 #
-# The hash %{'_<'.$filename} contains breakpoints and action (it is
-# keyed by line number), and individual entries are settable (as
-# opposed to the whole hash). Only true/false is important to the
-# interpreter, though the values used by perl5db.pl have the form
-# "$break_condition\0$action". Values are magical in numeric context.
+# The hash %{'_<'.$filename} (herein called %dbline) contains
+# breakpoints and action (it is keyed by line number), and individual
+# entries are settable (as opposed to the whole hash). Only true/false
+# is important to the interpreter, though the values used by
+# perl5db.pl have the form "$break_condition\0$action". Values are
+# magical in numeric context.
 #
 # The scalar ${'_<'.$filename} contains $filename.
 #
@@ -202,7 +240,7 @@ $header = "perl5db.pl version $VERSION";
 #       I<CreateTTY>       bits control attempts to create a new TTY on events:
 #                          1: on fork()   2: debugger is started inside debugger
 #                          4: on startup
-#   c) Code to auto-create a new TTY window on OS/2 (currently one one
+#   c) Code to auto-create a new TTY window on OS/2 (currently one
 #      extra window per session - need named pipes to have more...);
 #   d) Simplified interface for custom createTTY functions (with a backward
 #      compatibility hack); now returns the TTY name to use; return of ''
@@ -218,7 +256,7 @@ $header = "perl5db.pl version $VERSION";
 #      cmd_b_line($lineno [, $cond])        # b lineno [cond]
 #      cmd_b_sub($sub [, $cond])            # b sub [cond]
 #      cmd_stop()                           # Control-C
-#      cmd_d($lineno)                       # d lineno
+#      cmd_d($lineno)                       # d lineno (B)
 #      The cmd_*() API returns FALSE on failure; in this case it outputs
 #      the error message to the debugging output.
 #   j) Low-level debugger API
@@ -254,6 +292,31 @@ $header = "perl5db.pl version $VERSION";
 #   + Fixed warnings generated by "p 42" (Print expression)
 # Changes: 1.13: Jun 19, 2001 Scott.L.Miller@compaq.com
 #   + Added windowSize option 
+# Changes: 1.14: Oct  9, 2001 multiple
+#   + Clean up after itself on VMS (Charles Lane in 12385)
+#   + Adding "@ file" syntax (Peter Scott in 12014)
+#   + Debug reloading selfloaded stuff (Ilya Zakharevich in 11457)
+#   + $^S and other debugger fixes (Ilya Zakharevich in 11120)
+#   + Forgot a my() declaration (Ilya Zakharevich in 11085)
+# Changes: 1.15: Nov  6, 2001 Michael G Schwern <schwern@pobox.com>
+#   + Updated 1.14 change log
+#   + Added *dbline explainatory comments
+#   + Mentioning perldebguts man page
+# Changes: 1.16: Feb 15, 2002 Mark-Jason Dominus <mjd@plover.com>
+#      + $onetimeDump improvements
+# Changes: 1.17: Feb 20, 2002 Richard Foley <richard.foley@rfi.net>
+#   Moved some code to cmd_[.]()'s for clarity and ease of handling,
+#   rationalised the following commands and added cmd_wrapper() to 
+#   enable switching between old and frighteningly consistent new 
+#   behaviours for diehards: 'o CommandSet=pre580' (sigh...)
+#     a(add),       A(del)            # action expr   (added del by line)
+#   + b(add),       B(del)            # break  [line] (was b,D)
+#   + w(add),       W(del)            # watch  expr   (was W,W) added del by expr
+#   + h(summary), h h(long)           # help (hh)     (was h h,h)
+#   + m(methods),   M(modules)        # ...           (was m,v)
+#   + o(option)                       # lc            (was O)
+#   + v(view code), V(view Variables) # ...           (was w,V)
+# 
 ####################################################################
 
 # Needed for the statement after exec():
@@ -284,7 +347,8 @@ $trace = $signal = $single = 0;     # Uninitialized warning suppression
                                 # (local $^W cannot help - other packages!).
 $inhibit_exit = $option{PrintRet} = 1;
 
-@options     = qw(hashDepth arrayDepth DumpDBFiles DumpPackages DumpReused
+@options     = qw(hashDepth arrayDepth CommandSet dumpDepth
+                  DumpDBFiles DumpPackages DumpReused
                  compactDump veryCompact quote HighBit undefPrint
                  globPrint PrintRet UsageOnly frame AutoTrace
                  TTY noTTY ReadLine NonStop LineInfo maxTraceLen
@@ -296,6 +360,7 @@ $inhibit_exit = $option{PrintRet} = 1;
 %optionVars    = (
                 hashDepth      => \$dumpvar::hashDepth,
                 arrayDepth     => \$dumpvar::arrayDepth,
+                CommandSet => \$CommandSet,
                 DumpDBFiles    => \$dumpvar::dumpDBFiles,
                 DumpPackages   => \$dumpvar::dumpPackages,
                 DumpReused     => \$dumpvar::dumpReused,
@@ -349,17 +414,18 @@ $pre              = []    unless defined $pre;
 $post          = []    unless defined $post;
 $pretype       = []    unless defined $pretype;
 $CreateTTY     = 3     unless defined $CreateTTY;
+$CommandSet = '580'    unless defined $CommandSet;
 
 warnLevel($warnLevel);
 dieLevel($dieLevel);
 signalLevel($signalLevel);
 
-&pager(
-    (defined($ENV{PAGER}) 
-       ? $ENV{PAGER}
-       : ($^O eq 'os2' 
-          ? 'cmd /c more' 
-          : 'more'))) unless defined $pager;
+pager(
+      defined $ENV{PAGER}              ? $ENV{PAGER} :
+      eval { require Config } && 
+        defined $Config::Config{pager} ? $Config::Config{pager}
+                                       : 'more'
+     ) unless defined $pager;
 setman();
 &recallCommand("!") unless defined $prc;
 &shellBang("!") unless defined $psh;
@@ -527,24 +593,21 @@ if ($notty) {
                                );
     if (!$OUT) { die "Unable to connect to remote host: $remoteport\n"; }
     $IN = $OUT;
-  } elsif ($CreateTTY & 4) {
-    create_IN_OUT(4);
   } else {
-    if (defined $console) {
+    create_IN_OUT(4) if $CreateTTY & 4;
+    if ($console) {
       my ($i, $o) = split /,/, $console;
       $o = $i unless defined $o;
       open(IN,"+<$i") || open(IN,"<$i") || open(IN,"<&STDIN");
       open(OUT,"+>$o") || open(OUT,">$o") || open(OUT,">&STDERR")
         || open(OUT,">&STDOUT");       # so we don't dongle stdout
-    } else {
+    } elsif (not defined $console) {
       open(IN,"<&STDIN");
       open(OUT,">&STDERR") || open(OUT,">&STDOUT"); # so we don't dongle stdout
       $console = 'STDIN/OUT';
     }
     # so open("|more") can read from STDOUT and so we don't dingle stdin
-    $IN = \*IN;
-
-    $OUT = \*OUT;
+    $IN = \*IN, $OUT = \*OUT if $console or not defined $console;
   }
   my $previous = select($OUT);
   $| = 1;                      # for DB::OUT
@@ -555,6 +618,8 @@ if ($notty) {
 
   $header =~ s/.Header: ([^,]+),v(\s+\S+\s+\S+).*$/$1$2/;
   unless ($runnonstop) {
+    local $\ = '';
+    local $, = '';
     if ($term_pid eq '-1') {
       print $OUT "\nDaughter DB session started...\n";
     } else {
@@ -602,31 +667,39 @@ sub DB {
     $usercontext = '($@, $!, $^E, $,, $/, $\, $^W) = @saved;' .
       "package $package;";     # this won't let them modify, alas
     local(*dbline) = $main::{'_<' . $filename};
+
+    # we need to check for pseudofiles on Mac OS (these are files
+    # not attached to a filename, but instead stored in Dev:Pseudo)
+    if ($^O eq 'MacOS' && $#dbline < 0) {
+       $filename_ini = $filename = 'Dev:Pseudo';
+       *dbline = $main::{'_<' . $filename};
+    }
+
     $max = $#dbline;
     if ($dbline{$line} && (($stop,$action) = split(/\0/,$dbline{$line}))) {
-       if ($stop eq '1') {
-           $signal |= 1;
-       } elsif ($stop) {
-           $evalarg = "\$DB::signal |= 1 if do {$stop}"; &eval;
-           $dbline{$line} =~ s/;9($|\0)/$1/;
-       }
+               if ($stop eq '1') {
+                       $signal |= 1;
+               } elsif ($stop) {
+                       $evalarg = "\$DB::signal |= 1 if do {$stop}"; &eval;
+                       $dbline{$line} =~ s/;9($|\0)/$1/;
+               }
     }
     my $was_signal = $signal;
     if ($trace & 2) {
       for (my $n = 0; $n <= $#to_watch; $n++) {
-       $evalarg = $to_watch[$n];
-       local $onetimeDump;     # Do not output results
-       my ($val) = &eval;      # Fix context (&eval is doing array)?
-       $val = ( (defined $val) ? "'$val'" : 'undef' );
-       if ($val ne $old_watch[$n]) {
-         $signal = 1;
-         print $OUT <<EOP;
+               $evalarg = $to_watch[$n];
+               local $onetimeDump;     # Do not output results
+               my ($val) = &eval;      # Fix context (&eval is doing array)?
+               $val = ( (defined $val) ? "'$val'" : 'undef' );
+               if ($val ne $old_watch[$n]) {
+                 $signal = 1;
+                 print $OUT <<EOP;
 Watchpoint $n:\t$to_watch[$n] changed:
-    old value:\t$old_watch[$n]
-    new value:\t$val
+       old value:\t$old_watch[$n]
+       new value:\t$val
 EOP
-         $old_watch[$n] = $val;
-       }
+                 $old_watch[$n] = $val;
+               }
       }
     }
     if ($trace & 4) {          # User-installed watch
@@ -656,48 +729,47 @@ EOP
            $after = ($dbline[$line] =~ /\n$/ ? '' : "\n");
            if (length($prefix) > 30) {
                $position = "$prefix$line):\n$line:\t$dbline[$line]$after";
-               $prefix = "";
-               $infix = ":\t";
+                       $prefix = "";
+                       $infix = ":\t";
            } else {
-               $infix = "):\t";
-               $position = "$prefix$line$infix$dbline[$line]$after";
+                       $infix = "):\t";
+                       $position = "$prefix$line$infix$dbline[$line]$after";
            }
            if ($frame) {
-               print_lineinfo(' ' x $stack_depth, "$line:\t$dbline[$line]$after");
+                       print_lineinfo(' ' x $stack_depth, "$line:\t$dbline[$line]$after");
            } else {
-               print_lineinfo($position);
+                       print_lineinfo($position);
            }
            for ($i = $line + 1; $i <= $max && $dbline[$i] == 0; ++$i) { #{ vi
-               last if $dbline[$i] =~ /^\s*[\;\}\#\n]/;
-               last if $signal;
-               $after = ($dbline[$i] =~ /\n$/ ? '' : "\n");
-               $incr_pos = "$prefix$i$infix$dbline[$i]$after";
-               $position .= $incr_pos;
-               if ($frame) {
-                   print_lineinfo(' ' x $stack_depth, "$i:\t$dbline[$i]$after");
-               } else {
-                   print_lineinfo($incr_pos);
-               }
+                       last if $dbline[$i] =~ /^\s*[\;\}\#\n]/;
+                       last if $signal;
+                       $after = ($dbline[$i] =~ /\n$/ ? '' : "\n");
+                       $incr_pos = "$prefix$i$infix$dbline[$i]$after";
+                       $position .= $incr_pos;
+                       if ($frame) {
+                               print_lineinfo(' ' x $stack_depth, "$i:\t$dbline[$i]$after");
+                       } else {
+                               print_lineinfo($incr_pos);
+                       }
            }
        }
     }
     $evalarg = $action, &eval if $action;
     if ($single || $was_signal) {
-       local $level = $level + 1;
-       foreach $evalarg (@$pre) {
-         &eval;
-       }
-       print $OUT $stack_depth . " levels deep in subroutine calls!\n"
-         if $single & 4;
-       $start = $line;
-       $incr = -1;             # for backward motion.
-       @typeahead = (@$pretype, @typeahead);
-      CMD:
+         local $level = $level + 1;
+         foreach $evalarg (@$pre) {
+           &eval;
+         }
+         print $OUT $stack_depth . " levels deep in subroutine calls!\n"
+              if $single & 4;
+               $start = $line;
+               $incr = -1;             # for backward motion.
+               @typeahead = (@$pretype, @typeahead);
+    CMD:
        while (($term || &setterm),
               ($term_pid == $$ or resetterm(1)),
               defined ($cmd=&readline("$pidprompt  DB" . ('<' x $level) .
-                                      ($#hist+1) . ('>' x $level) .
-                                      " "))) 
+                                      ($#hist+1) . ('>' x $level) . " "))) 
         {
                $single = 0;
                $signal = 0;
@@ -712,51 +784,37 @@ EOP
                    $cmd =~ s/\s+$//s;   # trim annoying trailing whitespace
                    ($i) = split(/\s+/,$cmd);
                    if ($alias{$i}) { 
-                       # squelch the sigmangler
-                       local $SIG{__DIE__};
-                       local $SIG{__WARN__};
-                       eval "\$cmd =~ $alias{$i}";
-                       if ($@) {
-                           print $OUT "Couldn't evaluate `$i' alias: $@";
-                           next CMD;
-                       } 
+                                       # squelch the sigmangler
+                                       local $SIG{__DIE__};
+                                       local $SIG{__WARN__};
+                                       eval "\$cmd =~ $alias{$i}";
+                                       if ($@) {
+                                                local $\ = '';
+                                               print $OUT "Couldn't evaluate `$i' alias: $@";
+                                               next CMD;
+                                       } 
                    }
-                   $cmd =~ /^q$/ && ($fall_off_end = 1) && clean_ENV() && exit $?;
-                   $cmd =~ /^h$/ && do {
-                       print_help($help);
-                       next CMD; };
-                   $cmd =~ /^h\s+h$/ && do {
-                       print_help($summary);
-                       next CMD; };
-                   # support long commands; otherwise bogus errors
-                   # happen when you ask for h on <CR> for example
-                   $cmd =~ /^h\s+(\S.*)$/ && do {      
-                       my $asked = $1;                 # for proper errmsg
-                       my $qasked = quotemeta($asked); # for searching
-                       # XXX: finds CR but not <CR>
-                       if ($help =~ /^<?(?:[IB]<)$qasked/m) {
-                         while ($help =~ /^(<?(?:[IB]<)$qasked([\s\S]*?)\n)(?!\s)/mg) {
-                           print_help($1);
-                         }
-                       } else {
-                           print_help("B<$asked> is not a debugger command.\n");
-                       }
-                       next CMD; };
+                    $cmd =~ /^q$/ && do {
+                        $fall_off_end = 1;
+                        clean_ENV();
+                        exit $?;
+                    };
                    $cmd =~ /^t$/ && do {
                        $trace ^= 1;
+                       local $\ = '';
                        print $OUT "Trace = " .
                            (($trace & 1) ? "on" : "off" ) . "\n";
                        next CMD; };
                    $cmd =~ /^S(\s+(!)?(.+))?$/ && do {
                        $Srev = defined $2; $Spatt = $3; $Snocheck = ! defined $1;
+                       local $\ = '';
+                       local $, = '';
                        foreach $subname (sort(keys %sub)) {
                            if ($Snocheck or $Srev^($subname =~ /$Spatt/)) {
                                print $OUT $subname,"\n";
                            }
                        }
                        next CMD; };
-                   $cmd =~ /^v$/ && do {
-                       list_versions(); next CMD};
                    $cmd =~ s/^X\b/V $package/;
                    $cmd =~ /^V$/ && do {
                        $cmd = "V $package"; };
@@ -769,7 +827,10 @@ EOP
                            local $frame = 0;
                            local $doret = -2;
                            # must detect sigpipe failures
-                           eval { &main::dumpvar($packname,@vars) };
+                           eval { &main::dumpvar($packname,
+                                                 defined $option{dumpDepth}
+                                                  ? $option{dumpDepth} : -1,
+                                                 @vars) };
                            if ($@) {
                                die unless $@ =~ /dumpvar print failed/;
                            } 
@@ -779,7 +840,12 @@ EOP
                        select ($savout);
                        next CMD; };
                    $cmd =~ s/^x\b/ / && do { # So that will be evaled
-                       $onetimeDump = 'dump'; };
+                       $onetimeDump = 'dump'; 
+                        # handle special  "x 3 blah" syntax
+                        if ($cmd =~ s/^\s*(\d+)(?=\s)/ /) {
+                          $onetimedumpDepth = $1;
+                        }
+                      };
                    $cmd =~ s/^m\s+([\w:]+)\s*$/ / && do {
                        methods($1); next CMD};
                    $cmd =~ s/^m\b/ / && do { # So this will be evaled
@@ -788,7 +854,7 @@ EOP
                        $file = $1;
                        $file =~ s/\s+$//;
                        if (!$file) {
-                           print $OUT "The old f command is now the r command.\n";
+                           print $OUT "The old f command is now the r command.\n"; # hint
                            print $OUT "The new f command switches filenames.\n";
                            next CMD;
                        }
@@ -813,43 +879,6 @@ EOP
                            next CMD;
                          }
                      };
-                   $cmd =~ s/^l\s+-\s*$/-/;
-                   $cmd =~ /^([lb])\b\s*(\$.*)/s && do {
-                       $evalarg = $2;
-                       my ($s) = &eval;
-                       print($OUT "Error: $@\n"), next CMD if $@;
-                       $s = CvGV_name($s);
-                       print($OUT "Interpreted as: $1 $s\n");
-                       $cmd = "$1 $s";
-                   };
-                   $cmd =~ /^l\b\s*([\':A-Za-z_][\':\w]*(\[.*\])?)/s && do {
-                       my $s = $subname = $1;
-                       $subname =~ s/\'/::/;
-                       $subname = $package."::".$subname 
-                         unless $subname =~ /::/;
-                       $subname = "CORE::GLOBAL::$s"
-                         if not defined &$subname and $s !~ /::/
-                            and defined &{"CORE::GLOBAL::$s"};
-                       $subname = "main".$subname if substr($subname,0,2) eq "::";
-                       @pieces = split(/:/,find_sub($subname) || $sub{$subname});
-                       $subrange = pop @pieces;
-                       $file = join(':', @pieces);
-                       if ($file ne $filename) {
-                           print $OUT "Switching to file '$file'.\n"
-                               unless $slave_editor;
-                           *dbline = $main::{'_<' . $file};
-                           $max = $#dbline;
-                           $filename = $file;
-                       }
-                       if ($subrange) {
-                           if (eval($subrange) < -$window) {
-                               $subrange =~ s/-.*/+/;
-                           }
-                           $cmd = "l $subrange";
-                       } else {
-                           print $OUT "Subroutine $subname not found.\n";
-                           next CMD;
-                       } };
                    $cmd =~ /^\.$/ && do {
                        $incr = -1;             # for backward motion.
                        $start = $line;
@@ -858,201 +887,18 @@ EOP
                        $max = $#dbline;
                        print_lineinfo($position);
                        next CMD };
-                   $cmd =~ /^w\b\s*(\d*)$/ && do {
-                       $incr = $window - 1;
-                       $start = $1 if $1;
-                       $start -= $preview;
-                       #print $OUT 'l ' . $start . '-' . ($start + $incr);
-                       $cmd = 'l ' . $start . '-' . ($start + $incr); };
                    $cmd =~ /^-$/ && do {
                        $start -= $incr + $window + 1;
                        $start = 1 if $start <= 0;
                        $incr = $window - 1;
                        $cmd = 'l ' . ($start) . '+'; };
-                   $cmd =~ /^l$/ && do {
-                       $incr = $window - 1;
-                       $cmd = 'l ' . $start . '-' . ($start + $incr); };
-                   $cmd =~ /^l\b\s*(\d*)\+(\d*)$/ && do {
-                       $start = $1 if $1;
-                       $incr = $2;
-                       $incr = $window - 1 unless $incr;
-                       $cmd = 'l ' . $start . '-' . ($start + $incr); };
-                   $cmd =~ /^l\b\s*((-?[\d\$\.]+)([-,]([\d\$\.]+))?)?/ && do {
-                       $end = (!defined $2) ? $max : ($4 ? $4 : $2);
-                       $end = $max if $end > $max;
-                       $i = $2;
-                       $i = $line if $i eq '.';
-                       $i = 1 if $i < 1;
-                       $incr = $end - $i;
-                       if ($slave_editor) {
-                           print $OUT "\032\032$filename:$i:0\n";
-                           $i = $end;
-                       } else {
-                           for (; $i <= $end; $i++) {
-                               my ($stop,$action);
-                               ($stop,$action) = split(/\0/, $dbline{$i}) if
-                                   $dbline{$i};
-                               $arrow = ($i==$line 
-                                         and $filename eq $filename_ini) 
-                                 ?  '==>' 
-                                   : ($dbline[$i]+0 ? ':' : ' ') ;
-                               $arrow .= 'b' if $stop;
-                               $arrow .= 'a' if $action;
-                               print $OUT "$i$arrow\t", $dbline[$i];
-                               $i++, last if $signal;
-                           }
-                           print $OUT "\n" unless $dbline[$i-1] =~ /\n$/;
-                       }
-                       $start = $i; # remember in case they want more
-                       $start = $max if $start > $max;
-                       next CMD; };
-                   $cmd =~ /^D$/ && do {
-                     print $OUT "Deleting all breakpoints...\n";
-                     my $file;
-                     for $file (keys %had_breakpoints) {
-                       local *dbline = $main::{'_<' . $file};
-                       my $max = $#dbline;
-                       my $was;
-                       
-                       for ($i = 1; $i <= $max ; $i++) {
-                           if (defined $dbline{$i}) {
-                               $dbline{$i} =~ s/^[^\0]+//;
-                               if ($dbline{$i} =~ s/^\0?$//) {
-                                   delete $dbline{$i};
-                               }
-                           }
-                       }
-                       
-                       if (not $had_breakpoints{$file} &= ~1) {
-                           delete $had_breakpoints{$file};
-                       }
-                     }
-                     undef %postponed;
-                     undef %postponed_file;
-                     undef %break_on_load;
-                     next CMD; };
-                   $cmd =~ /^L$/ && do {
-                     my $file;
-                     for $file (keys %had_breakpoints) {
-                       local *dbline = $main::{'_<' . $file};
-                       my $max = $#dbline;
-                       my $was;
-                       
-                       for ($i = 1; $i <= $max; $i++) {
-                           if (defined $dbline{$i}) {
-                               print $OUT "$file:\n" unless $was++;
-                               print $OUT " $i:\t", $dbline[$i];
-                               ($stop,$action) = split(/\0/, $dbline{$i});
-                               print $OUT "   break if (", $stop, ")\n"
-                                 if $stop;
-                               print $OUT "   action:  ", $action, "\n"
-                                 if $action;
-                               last if $signal;
-                           }
-                       }
-                     }
-                     if (%postponed) {
-                       print $OUT "Postponed breakpoints in subroutines:\n";
-                       my $subname;
-                       for $subname (keys %postponed) {
-                         print $OUT " $subname\t$postponed{$subname}\n";
-                         last if $signal;
-                       }
-                     }
-                     my @have = map { # Combined keys
-                       keys %{$postponed_file{$_}}
-                     } keys %postponed_file;
-                     if (@have) {
-                       print $OUT "Postponed breakpoints in files:\n";
-                       my ($file, $line);
-                       for $file (keys %postponed_file) {
-                         my $db = $postponed_file{$file};
-                         print $OUT " $file:\n";
-                         for $line (sort {$a <=> $b} keys %$db) {
-                               print $OUT "  $line:\n";
-                               my ($stop,$action) = split(/\0/, $$db{$line});
-                               print $OUT "    break if (", $stop, ")\n"
-                                 if $stop;
-                               print $OUT "    action:  ", $action, "\n"
-                                 if $action;
-                               last if $signal;
-                         }
-                         last if $signal;
-                       }
-                     }
-                     if (%break_on_load) {
-                       print $OUT "Breakpoints on load:\n";
-                       my $file;
-                       for $file (keys %break_on_load) {
-                         print $OUT " $file\n";
-                         last if $signal;
-                       }
-                     }
-                     if ($trace & 2) {
-                       print $OUT "Watch-expressions:\n";
-                       my $expr;
-                       for $expr (@to_watch) {
-                         print $OUT " $expr\n";
-                         last if $signal;
-                       }
-                     }
-                     next CMD; };
-                   $cmd =~ /^b\b\s*load\b\s*(.*)/ && do {
-                       my $file = $1; $file =~ s/\s+$//;
-                       cmd_b_load($file);
-                       next CMD; };
-                   $cmd =~ /^b\b\s*(postpone|compile)\b\s*([':A-Za-z_][':\w]*)\s*(.*)/ && do {
-                       my $cond = length $3 ? $3 : '1';
-                       my ($subname, $break) = ($2, $1 eq 'postpone');
-                       $subname =~ s/\'/::/g;
-                       $subname = "${'package'}::" . $subname
-                         unless $subname =~ /::/;
-                       $subname = "main".$subname if substr($subname,0,2) eq "::";
-                       $postponed{$subname} = $break 
-                         ? "break +0 if $cond" : "compile";
-                       next CMD; };
-                   $cmd =~ /^b\b\s*([':A-Za-z_][':\w]*(?:\[.*\])?)\s*(.*)/ && do {
-                       $subname = $1;
-                       $cond = length $2 ? $2 : '1';
-                       cmd_b_sub($subname, $cond);
-                       next CMD; };
-                   $cmd =~ /^b\b\s*(\d*)\s*(.*)/ && do {
-                       $i = $1 || $line;
-                       $cond = length $2 ? $2 : '1';
-                       cmd_b_line($i, $cond);
-                       next CMD; };
-                   $cmd =~ /^d\b\s*(\d*)/ && do {
-                       cmd_d($1 || $line);
-                       next CMD; };
-                   $cmd =~ /^A$/ && do {
-                     print $OUT "Deleting all actions...\n";
-                     my $file;
-                     for $file (keys %had_breakpoints) {
-                       local *dbline = $main::{'_<' . $file};
-                       my $max = $#dbline;
-                       my $was;
-                       
-                       for ($i = 1; $i <= $max ; $i++) {
-                           if (defined $dbline{$i}) {
-                               $dbline{$i} =~ s/\0[^\0]*//;
-                               delete $dbline{$i} if $dbline{$i} eq '';
-                           }
-                       }
-                       
-                       unless ($had_breakpoints{$file} &= ~2) {
-                           delete $had_breakpoints{$file};
-                       }
-                     }
-                     next CMD; };
-                   $cmd =~ /^O\s*$/ && do {
-                       for (@options) {
-                           &dump_option($_);
-                       }
-                       next CMD; };
-                   $cmd =~ /^O\s*(\S.*)/ && do {
-                       parse_options($1);
-                       next CMD; };
-                   $cmd =~ /^\<\<\s*(.*)/ && do { # \<\< for CPerl sake: not HERE
+                       # rjsf ->
+                 $cmd =~ /^([aAbBDhlLMoOvwW])\b\s*(.*)/s && do { 
+                               &cmd_wrapper($1, $2, $line); 
+                               next CMD; 
+                       };
+                       # <- rjsf
+                 $cmd =~ /^\<\<\s*(.*)/ && do { # \<\< for CPerl sake: not HERE
                        push @$pre, action($1);
                        next CMD; };
                    $cmd =~ /^>>\s*(.*)/ && do {
@@ -1130,22 +976,7 @@ EOP
                        } 
                        $pretype = [$1];
                        next CMD; };
-                   $cmd =~ /^a\b\s*(\d*)\s*(.*)/ && do {
-                       $i = $1 || $line; $j = $2;
-                       if (length $j) {
-                           if ($dbline[$i] == 0) {
-                               print $OUT "Line $i may not have an action.\n";
-                           } else {
-                               $had_breakpoints{$filename} |= 2;
-                               $dbline{$i} =~ s/\0[^\0]*//;
-                               $dbline{$i} .= "\0" . action($j);
-                           }
-                       } else {
-                           $dbline{$i} =~ s/\0[^\0]*//;
-                           delete $dbline{$i} if $dbline{$i} eq '';
-                       }
-                       next CMD; };
-                   $cmd =~ /^n$/ && do {
+           $cmd =~ /^n$/ && do {
                        end_report(), next CMD if $finished and $level <= 1;
                        $single = 2;
                        $laststep = $cmd;
@@ -1162,7 +993,7 @@ EOP
                        #  sub-session anyway...
                        # local $filename = $filename;
                        # local *dbline = *dbline;      # XXX Would this work?!
-                       if ($i =~ /\D/) { # subroutine name
+                       if ($subname =~ /\D/) { # subroutine name
                            $subname = $package."::".$subname 
                                unless $subname =~ /::/;
                            ($file,$i) = (find_sub($subname) =~ /^(.*):(.*)$/);
@@ -1203,6 +1034,7 @@ EOP
                        for (@ini_INC) {
                          push @flags, '-I', $_;
                        }
+                       push @flags, '-T' if ${^TAINT};
                        # Arrange for setting the old INC:
                        set_list("PERLDB_INC", @ini_INC);
                        if ($0 eq '-e') {
@@ -1280,18 +1112,8 @@ EOP
                    $cmd =~ /^T$/ && do {
                        print_trace($OUT, 1); # skip DB
                        next CMD; };
-                   $cmd =~ /^W\s*$/ && do {
-                       $trace &= ~2;
-                       @to_watch = @old_watch = ();
-                       next CMD; };
-                   $cmd =~ /^W\b\s*(.*)/s && do {
-                       push @to_watch, $1;
-                       $evalarg = $1;
-                       my ($val) = &eval;
-                       $val = (defined $val) ? "'$val'" : 'undef' ;
-                       push @old_watch, $val;
-                       $trace |= 2;
-                       next CMD; };
+                   $cmd =~ /^w\b\s*(.*)/s && do { &cmd_w($1); next CMD; };
+                   $cmd =~ /^W\b\s*(.*)/s && do { &cmd_W($1); next CMD; };
                    $cmd =~ /^\/(.*)$/ && do {
                        $inpat = $1;
                        $inpat =~ s:([^\\])/$:$1:;
@@ -1403,8 +1225,7 @@ EOP
                        my @keys;
                        if (length $cmd == 0) {
                            @keys = sort keys %alias;
-                       } 
-                        elsif (my($k,$v) = ($cmd =~ /^(\S+)\s+(\S.*)/)) {
+                       } elsif (my($k,$v) = ($cmd =~ /^(\S+)\s+(\S.*)/)) {
                            # can't use $_ or kill //g state
                            for my $x ($k, $v) { $x =~ s/\a/\\a/g }
                            $alias{$k} = "s\a$k\a$v\a";
@@ -1417,8 +1238,7 @@ EOP
                                next CMD;
                            } 
                            @keys = ($k);
-                       } 
-                       else {
+                       } else {
                            @keys = ($cmd);
                        } 
                        for my $k (@keys) {
@@ -1436,8 +1256,7 @@ EOP
                    $cmd =~ /^\@\s*(.*\S)/ && do {
                      if (open my $fh, $1) {
                        push @cmdfhs, $fh;
-                     }
-                     else {
+                     } else {
                        &warn("Can't execute `$1': $!\n");
                      }
                      next CMD; };
@@ -1479,6 +1298,7 @@ EOP
            $evalarg = "\$^D = \$^D | \$DB::db_stop;\n$cmd"; &eval;
            if ($onetimeDump) {
                $onetimeDump = undef;
+                $onetimedumpDepth = undef;
            } elsif ($term_pid == $$) {
                print $OUT "\n";
            }
@@ -1516,7 +1336,7 @@ EOP
                $piped= "";
            }
        }                       # CMD:
-       $fall_off_end = 1 unless defined $cmd; # Emulate `q' on EOF
+    $fall_off_end = 1 unless defined $cmd; # Emulate `q' on EOF
        foreach $evalarg (@$post) {
          &eval;
        }
@@ -1551,6 +1371,7 @@ sub sub {
             print_trace($LINEINFO, -1, 1, 1, "$sub$al") )
         : print_lineinfo(' ' x $stack_depth, "exited $sub$al\n")) if $frame & 2;
        if ($doret eq $stack_depth or $frame & 16) {
+           local $\ = '';
             my $fh = ($doret eq $stack_depth ? $OUT : $LINEINFO);
            print $fh ' ' x $stack_depth if $frame & 16;
            print $fh "list context return from $sub:\n"; 
@@ -1570,6 +1391,7 @@ sub sub {
              print_trace($LINEINFO, -1, 1, 1, "$sub$al") )
         : print_lineinfo(' ' x $stack_depth, "exited $sub$al\n")) if $frame & 2;
        if ($doret eq $stack_depth or $frame & 16 and defined wantarray) {
+           local $\ = '';
             my $fh = ($doret eq $stack_depth ? $OUT : $LINEINFO);
            print $fh (' ' x $stack_depth) if $frame & 16;
            print $fh (defined wantarray 
@@ -1588,6 +1410,126 @@ sub sub {
 ### returns FALSE on error.
 ### User-interface functions cmd_* output error message.
 
+### Note all cmd_[a-zA-Z]'s require $line, $dblineno as first arguments
+
+my %set = ( # 
+       'pre580'        => {
+               'a'     => 'pre580_a', 
+               'A'     => 'pre580_null',
+               'b'     => 'pre580_b', 
+               'B'     => 'pre580_null',
+               'd'     => 'pre580_null',
+               'D'     => 'pre580_D',
+               'h'     => 'pre580_h',
+               'M'     => 'pre580_null',
+               'O'     => 'o',
+               'o'     => 'pre580_null',
+               'v'     => 'M',
+               'w'     => 'v',
+               'W'     => 'pre580_W',
+       },
+);
+
+sub cmd_wrapper {
+       my $cmd      = shift;
+       my $line     = shift;
+       my $dblineno = shift;
+
+       # with this level of indirection we can wrap 
+       # to old (pre580) or other command sets easily
+       # 
+       my $call = 'cmd_'.(
+               $set{$CommandSet}{$cmd} || $cmd
+       );
+       # print "rjsf: cmd_wrapper($cmd): $CommandSet($set{$CommandSet}{$cmd}) => call($call)\n";
+
+       return &$call($line, $dblineno);
+}
+
+sub cmd_a {
+       my $line   = shift || ''; # [.|line] expr
+       my $dbline = shift; $line =~ s/^(\.|(?:[^\d]))/$dbline/;
+       if ($line =~ /^\s*(\d*)\s*(\S.+)/) {
+               my ($lineno, $expr) = ($1, $2);
+               if (length $expr) {
+                       if ($dbline[$lineno] == 0) {
+                               print $OUT "Line $lineno($dbline[$lineno]) does not have an action?\n";
+                       } else {
+                               $had_breakpoints{$filename} |= 2;
+                               $dbline{$lineno} =~ s/\0[^\0]*//;
+                               $dbline{$lineno} .= "\0" . action($expr);
+                       }
+               }
+       } else {
+               print $OUT "Adding an action requires an optional lineno and an expression\n"; # hint
+       }
+}
+
+sub cmd_A {
+       my $line   = shift || '';
+       my $dbline = shift; $line =~ s/^\./$dbline/;
+       if ($line eq '*') {
+               eval { &delete_action(); 1 } or print $OUT $@ and return;
+       } elsif ($line =~ /^(\S.*)/) {
+               eval { &delete_action($1); 1 } or print $OUT $@ and return;
+       } else {
+               print $OUT "Deleting an action requires a line number, or '*' for all\n"; # hint
+       }
+}
+
+sub delete_action {
+  my $i = shift;
+  if (defined($i)) {
+               die "Line $i has no action .\n" if $dbline[$i] == 0;
+               $dbline{$i} =~ s/\0[^\0]*//; # \^a
+               delete $dbline{$i} if $dbline{$i} eq '';
+       } else {
+               print $OUT "Deleting all actions...\n";
+               for my $file (keys %had_breakpoints) {
+                       local *dbline = $main::{'_<' . $file};
+                       my $max = $#dbline;
+                       my $was;
+                       for ($i = 1; $i <= $max ; $i++) {
+                                       if (defined $dbline{$i}) {
+                                                       $dbline{$i} =~ s/\0[^\0]*//;
+                                                       delete $dbline{$i} if $dbline{$i} eq '';
+                                       }
+                               unless ($had_breakpoints{$file} &= ~2) {
+                                               delete $had_breakpoints{$file};
+                               }
+                       }
+               }
+       }
+}
+
+sub cmd_b {
+       my $line   = shift; # [.|line] [cond]
+       my $dbline = shift; $line =~ s/^\./$dbline/;
+       if ($line =~ /^\s*$/) {
+               &cmd_b_line($dbline, 1);
+       } elsif ($line =~ /^load\b\s*(.*)/) {
+               my $file = $1; $file =~ s/\s+$//;
+               &cmd_b_load($file);
+       } elsif ($line =~ /^(postpone|compile)\b\s*([':A-Za-z_][':\w]*)\s*(.*)/) {
+               my $cond = length $3 ? $3 : '1';
+               my ($subname, $break) = ($2, $1 eq 'postpone');
+               $subname =~ s/\'/::/g;
+               $subname = "${'package'}::" . $subname unless $subname =~ /::/;
+               $subname = "main".$subname if substr($subname,0,2) eq "::";
+               $postponed{$subname} = $break ? "break +0 if $cond" : "compile";
+       } elsif ($line =~ /^([':A-Za-z_][':\w]*(?:\[.*\])?)\s*(.*)/) { 
+               $subname = $1;
+               $cond = length $2 ? $2 : '1';
+               &cmd_b_sub($subname, $cond);
+       } elsif ($line =~ /^(\d*)\s*(.*)/) { 
+               $line = $1 || $dbline;
+               $cond = length $2 ? $2 : '1';
+               &cmd_b_line($line, $cond);
+       } else {
+               print "confused by line($line)?\n";
+       }
+}
+
 sub break_on_load {
   my $file = shift;
   $break_on_load{$file} = 1;
@@ -1608,6 +1550,8 @@ sub cmd_b_load {
   }
   break_on_load($_) for @files;
   @files = report_break_on_load;
+  local $\ = '';
+  local $" = ' ';
   print $OUT "Will stop on load of `@files'.\n";
 }
 
@@ -1648,7 +1592,10 @@ sub break_on_line {
 }
 
 sub cmd_b_line {
-  eval { break_on_line(@_); 1 } or print $OUT $@ and return;
+  eval { break_on_line(@_); 1 } or do {
+    local $\ = '';
+    print $OUT $@ and return;
+  };
 }
 
 sub break_on_filename_line {
@@ -1693,23 +1640,295 @@ sub cmd_b_sub {
       if not defined &$subname and $s !~ /::/ and defined &{"CORE::GLOBAL::$s"};
     $subname = "main".$subname if substr($subname,0,2) eq "::";
   }
-  eval { break_subroutine($subname,$cond); 1 } or print $OUT $@ and return;
+  eval { break_subroutine($subname,$cond); 1 } or do {
+    local $\ = '';
+    print $OUT $@ and return;
+  }
 }
 
-sub cmd_stop {                 # As on ^C, but not signal-safy.
-  $signal = 1;
+sub cmd_B {
+       my $line   = ($_[0] =~ /^\./) ? $dbline : shift || ''; 
+       my $dbline = shift; $line =~ s/^\./$dbline/;
+       if ($line eq '*') {
+               eval { &delete_breakpoint(); 1 } or print $OUT $@ and return;
+       } elsif ($line =~ /^(\S.*)/) {
+               eval { &delete_breakpoint($line || $dbline); 1 } or do {
+                    local $\ = '';
+                    print $OUT $@ and return;
+                };
+       } else {
+               print $OUT "Deleting a breakpoint requires a line number, or '*' for all\n"; # hint
+       }
 }
 
 sub delete_breakpoint {
   my $i = shift;
-  die "Line $i not breakable.\n" if $dbline[$i] == 0;
-  $dbline{$i} =~ s/^[^\0]*//;
-  delete $dbline{$i} if $dbline{$i} eq '';
+  if (defined($i)) {
+         die "Line $i not breakable.\n" if $dbline[$i] == 0;
+         $dbline{$i} =~ s/^[^\0]*//;
+         delete $dbline{$i} if $dbline{$i} eq '';
+  } else {
+                 print $OUT "Deleting all breakpoints...\n";
+                 for my $file (keys %had_breakpoints) {
+                                       local *dbline = $main::{'_<' . $file};
+                                       my $max = $#dbline;
+                                       my $was;
+                                       for ($i = 1; $i <= $max ; $i++) {
+                                                       if (defined $dbline{$i}) {
+                                               $dbline{$i} =~ s/^[^\0]+//;
+                                               if ($dbline{$i} =~ s/^\0?$//) {
+                                                               delete $dbline{$i};
+                                               }
+                                                       }
+                                       }
+                                       if (not $had_breakpoints{$file} &= ~1) {
+                                                       delete $had_breakpoints{$file};
+                                       }
+                 }
+                 undef %postponed;
+                 undef %postponed_file;
+                 undef %break_on_load;
+       }
 }
 
-sub cmd_d {
-  my $i = shift;
-  eval { delete_breakpoint $i; 1 } or print $OUT $@ and return;
+sub cmd_stop {                 # As on ^C, but not signal-safy.
+  $signal = 1;
+}
+
+sub cmd_h {
+       my $line   = shift || '';
+       if ($line  =~ /^h\s*/) {
+               print_help($help);
+       } elsif ($line =~ /^(\S.*)$/) { 
+                       # support long commands; otherwise bogus errors
+                       # happen when you ask for h on <CR> for example
+                       my $asked = $1;                 # for proper errmsg
+                       my $qasked = quotemeta($asked); # for searching
+                       # XXX: finds CR but not <CR>
+                       if ($help =~ /^<?(?:[IB]<)$qasked/m) {
+                         while ($help =~ /^(<?(?:[IB]<)$qasked([\s\S]*?)\n)(?!\s)/mg) {
+                           print_help($1);
+                         }
+                       } else {
+                           print_help("B<$asked> is not a debugger command.\n");
+                       }
+       } else {
+                       print_help($summary);
+       }
+}
+
+sub cmd_l {
+       my $line = shift;
+       $line =~ s/^-\s*$/-/;
+       if ($line =~ /^(\$.*)/s) {
+               $evalarg = $2;
+               my ($s) = &eval;
+               print($OUT "Error: $@\n"), next CMD if $@;
+               $s = CvGV_name($s);
+               print($OUT "Interpreted as: $1 $s\n");
+               $line = "$1 $s";
+               &cmd_l($s);
+       } elsif ($line =~ /^([\':A-Za-z_][\':\w]*(\[.*\])?)/s) { 
+               my $s = $subname = $1;
+               $subname =~ s/\'/::/;
+               $subname = $package."::".$subname 
+               unless $subname =~ /::/;
+               $subname = "CORE::GLOBAL::$s"
+               if not defined &$subname and $s !~ /::/
+                        and defined &{"CORE::GLOBAL::$s"};
+               $subname = "main".$subname if substr($subname,0,2) eq "::";
+               @pieces = split(/:/,find_sub($subname) || $sub{$subname});
+               $subrange = pop @pieces;
+               $file = join(':', @pieces);
+               if ($file ne $filename) {
+                       print $OUT "Switching to file '$file'.\n"
+               unless $slave_editor;
+                       *dbline = $main::{'_<' . $file};
+                       $max = $#dbline;
+                       $filename = $file;
+               }
+               if ($subrange) {
+                       if (eval($subrange) < -$window) {
+               $subrange =~ s/-.*/+/;
+                       }
+                       $line = $subrange;
+                       &cmd_l($subrange);
+               } else {
+                       print $OUT "Subroutine $subname not found.\n";
+               }
+       } elsif ($line =~ /^\s*$/) {
+               $incr = $window - 1;
+               $line = $start . '-' . ($start + $incr); 
+               &cmd_l($line);
+       } elsif ($line =~ /^(\d*)\+(\d*)$/) { 
+               $start = $1 if $1;
+               $incr = $2;
+               $incr = $window - 1 unless $incr;
+               $line = $start . '-' . ($start + $incr); 
+               &cmd_l($line);  
+       } elsif ($line =~ /^((-?[\d\$\.]+)([-,]([\d\$\.]+))?)?/) { 
+               $end = (!defined $2) ? $max : ($4 ? $4 : $2);
+               $end = $max if $end > $max;
+               $i = $2;
+               $i = $line if $i eq '.';
+               $i = 1 if $i < 1;
+               $incr = $end - $i;
+               if ($slave_editor) {
+                       print $OUT "\032\032$filename:$i:0\n";
+                       $i = $end;
+               } else {
+                       for (; $i <= $end; $i++) {
+                               my ($stop,$action);
+                               ($stop,$action) = split(/\0/, $dbline{$i}) if
+                                               $dbline{$i};
+                                                       $arrow = ($i==$line 
+                                               and $filename eq $filename_ini) 
+                                       ?  '==>' 
+                                               : ($dbline[$i]+0 ? ':' : ' ') ;
+                               $arrow .= 'b' if $stop;
+                               $arrow .= 'a' if $action;
+                               print $OUT "$i$arrow\t", $dbline[$i];
+                               $i++, last if $signal;
+                       }
+                       print $OUT "\n" unless $dbline[$i-1] =~ /\n$/;
+               }
+               $start = $i; # remember in case they want more
+               $start = $max if $start > $max;
+       }
+}
+
+sub cmd_L {
+       my $arg    = shift || 'abw'; $arg = 'abw' unless $CommandSet eq '580'; # sigh...
+       my $action_wanted = ($arg =~ /a/) ? 1 : 0;
+       my $break_wanted  = ($arg =~ /b/) ? 1 : 0;
+       my $watch_wanted  = ($arg =~ /w/) ? 1 : 0;
+
+       if ($break_wanted or $action_wanted) {
+               for my $file (keys %had_breakpoints) {
+                       local *dbline = $main::{'_<' . $file};
+                       my $max = $#dbline;
+                       my $was;
+                       for ($i = 1; $i <= $max; $i++) {
+                               if (defined $dbline{$i}) {
+                                       print $OUT "$file:\n" unless $was++;
+                                       print $OUT " $i:\t", $dbline[$i];
+                                       ($stop,$action) = split(/\0/, $dbline{$i});
+                                       print $OUT "   break if (", $stop, ")\n"
+                                               if $stop and $break_wanted;
+                                       print $OUT "   action:  ", $action, "\n"
+                                               if $action and $action_wanted;
+                                       last if $signal;
+                               }
+                       }
+               }
+       }
+       if (%postponed and $break_wanted) {
+               print $OUT "Postponed breakpoints in subroutines:\n";
+               my $subname;
+               for $subname (keys %postponed) {
+                 print $OUT " $subname\t$postponed{$subname}\n";
+                 last if $signal;
+               }
+       }
+       my @have = map { # Combined keys
+                       keys %{$postponed_file{$_}}
+       } keys %postponed_file;
+       if (@have and ($break_wanted or $action_wanted)) {
+               print $OUT "Postponed breakpoints in files:\n";
+               my ($file, $line);
+               for $file (keys %postponed_file) {
+                 my $db = $postponed_file{$file};
+                 print $OUT " $file:\n";
+                 for $line (sort {$a <=> $b} keys %$db) {
+                       print $OUT "  $line:\n";
+                       my ($stop,$action) = split(/\0/, $$db{$line});
+                       print $OUT "    break if (", $stop, ")\n"
+                         if $stop and $break_wanted;
+                       print $OUT "    action:  ", $action, "\n"
+                         if $action and $action_wanted;
+                       last if $signal;
+                 }
+                 last if $signal;
+               }
+       }
+  if (%break_on_load and $break_wanted) {
+               print $OUT "Breakpoints on load:\n";
+               my $file;
+               for $file (keys %break_on_load) {
+                 print $OUT " $file\n";
+                 last if $signal;
+               }
+  }
+  if ($watch_wanted) {
+       if ($trace & 2) {
+               print $OUT "Watch-expressions:\n" if @to_watch;
+               for my $expr (@to_watch) {
+                       print $OUT " $expr\n";
+                       last if $signal;
+               }
+       }
+  }
+}
+
+sub cmd_M {
+       &list_modules();
+}
+
+sub cmd_o {
+       my $opt      = shift || ''; # opt[=val]
+       if ($opt =~ /^(\S.*)/) {
+               &parse_options($1);
+       } else {
+               for (@options) {
+                       &dump_option($_);
+               }
+       }
+}
+
+sub cmd_v {
+       my $line = shift;
+
+       if ($line =~ /^(\d*)$/) {
+               $incr = $window - 1;
+               $start = $1 if $1;
+               $start -= $preview;
+               $line = $start . '-' . ($start + $incr);
+               &cmd_l($line);
+       }
+}
+
+sub cmd_w {
+       my $expr     = shift || '';
+       if ($expr =~ /^(\S.*)/) {
+               push @to_watch, $expr;
+               $evalarg = $expr;
+               my ($val) = &eval;
+               $val = (defined $val) ? "'$val'" : 'undef' ;
+               push @old_watch, $val;
+               $trace |= 2;
+       } else {
+               print $OUT "Adding a watch-expression requires an expression\n"; # hint
+       }
+}
+
+sub cmd_W {
+       my $expr     = shift || '';
+       if ($expr eq '*') {
+               $trace &= ~2;
+               print $OUT "Deleting all watch expressions ...\n";
+               @to_watch = @old_watch = ();
+       } elsif ($expr =~ /^(\S.*)/) {
+               my $i_cnt = 0;
+               foreach (@to_watch) {
+                       my $val = $to_watch[$i_cnt];
+                       if ($val eq $expr) { # =~ m/^\Q$i$/) {
+                               splice(@to_watch, $i_cnt, 1);
+                       }
+                       $i_cnt++;
+               }
+       } else {
+               print $OUT "Deleting a watch-expression requires an expression, or '*' for all\n"; # hint
+       }
 }
 
 ### END of the API section
@@ -1721,37 +1940,13 @@ sub save {
 
 sub print_lineinfo {
   resetterm(1) if $LINEINFO eq $OUT and $term_pid != $$;
+  local $\ = '';
+  local $, = '';
   print $LINEINFO @_;
 }
 
 # The following takes its argument via $evalarg to preserve current @_
 
-sub eval {
-    # 'my' would make it visible from user code
-    #    but so does local! --tchrist  [... into @DB::res, not @res. IZ]
-    local @res;
-    {
-       local $otrace = $trace;
-       local $osingle = $single;
-       local $od = $^D;
-       { ($evalarg) = $evalarg =~ /(.*)/s; }
-       @res = eval "$usercontext $evalarg;\n"; # '\n' for nice recursive debug
-       $trace = $otrace;
-       $single = $osingle;
-       $^D = $od;
-    }
-    my $at = $@;
-    local $saved[0];           # Preserve the old value of $@
-    eval { &DB::save };
-    if ($at) {
-       print $OUT $at;
-    } elsif ($onetimeDump) {
-       dumpit($OUT, \@res) if $onetimeDump eq 'dump';
-       methods($res[0])    if $onetimeDump eq 'methods';
-    }
-    @res;
-}
-
 sub postponed_sub {
   my $subname = shift;
   if ($postponed{$subname} =~ s/^break\s([+-]?\d+)\s+if\s//) {
@@ -1767,6 +1962,7 @@ sub postponed_sub {
       ++$i until $dbline[$i] != 0 or $i >= $max;
       $dbline{$i} = delete $postponed{$subname};
     } else {
+      local $\ = '';
       print $OUT "Subroutine $subname not found.\n";
     }
     return;
@@ -1786,6 +1982,7 @@ sub postponed {
   local *dbline = shift;
   my $filename = $dbline;
   $filename =~ s/^_<//;
+  local $\ = '';
   $signal = 1, print $OUT "'$filename' loaded...\n"
     if $break_on_load{$filename};
   print_lineinfo(' ' x $stack_depth, "Package $filename.\n") if $frame;
@@ -1810,8 +2007,15 @@ sub dumpit {
        do 'dumpvar.pl';
     }
     if (defined &main::dumpValue) {
-       &main::dumpValue(shift);
+        local $\ = '';
+        local $, = '';
+        local $" = ' ';
+        my $v = shift;
+        my $maxdepth = shift || $option{dumpDepth};
+        $maxdepth = -1 unless defined $maxdepth;   # -1 means infinite depth
+       &main::dumpValue($v, $maxdepth);
     } else {
+        local $\ = '';
        print $OUT "dumpvar.pl not available.\n";
     }
     $single = $osingle;
@@ -1822,6 +2026,7 @@ sub dumpit {
 # Tied method do not create a context, so may get wrong message:
 
 sub print_trace {
+  local $\ = '';
   my $fh = shift;
   resetterm(1) if $fh eq $LINEINFO and $LINEINFO eq $OUT and $term_pid != $$;
   my @sub = dump_trace($_[0] + 1, $_[1]);
@@ -2017,24 +2222,27 @@ sub xterm_get_fork_TTY {
   return $tty;
 }
 
-# This one resets $IN, $OUT itself
+# This example function resets $IN, $OUT itself
 sub os2_get_fork_TTY {
-  $^F = 40;            # XXXX Fixme!
+  local $^F = 40;                      # XXXX Fixme!
+  local $\ = '';
   my ($in1, $out1, $in2, $out2);
   # Having -d in PERL5OPT would lead to a disaster...
   local $ENV{PERL5OPT} = $ENV{PERL5OPT}    if $ENV{PERL5OPT};
   $ENV{PERL5OPT} =~ s/(?:^|(?<=\s))-d\b//  if $ENV{PERL5OPT};
   $ENV{PERL5OPT} =~ s/(?:^|(?<=\s))-d\B/-/ if $ENV{PERL5OPT};
-  print $OUT "Making PERL5OPT->`$ENV{PERL5OPT}'.\n" if $ENV{PERL5OPT};
+  print $OUT "Making kid PERL5OPT->`$ENV{PERL5OPT}'.\n" if $ENV{PERL5OPT};
   (my $name = $0) =~ s,^.*[/\\],,s;
-  if ( pipe $in1, $out1 and pipe $in2, $out2 and
+  my @args;
+  if ( pipe $in1, $out1 and pipe $in2, $out2
        # system P_SESSION will fail if there is another process
        # in the same session with a "dependent" asynchronous child session.
-       (($kpid = CORE::system 4, $^X, '-we', <<'ES', fileno $in1, fileno $out2, "Daughter Perl debugger $pids $name") >= 0 or warn "system P_SESSION: $!, $^E" and 0) # P_SESSION
-use Term::ReadKey;
+       and @args = ($rl, fileno $in1, fileno $out2,
+                   "Daughter Perl debugger $pids $name") and
+       (($kpid = CORE::system 4, $^X, '-we', <<'ES', @args) >= 0 # P_SESSION
 use OS2::Process;
 
-my $in = shift;                # Read from here and pass through
+my ($rl, $in) = (shift, shift);                # Read from $in and pass through
 set_title pop;
 system P_NOWAIT, $^X, '-we', <<EOS or die "Cannot start a grandkid";
   open IN, '<&=$in' or die "open <&=$in: \$!";
@@ -2044,11 +2252,13 @@ EOS
 my $out = shift;
 open OUT, ">&=$out" or die "Cannot open &=$out for writing: $!";
 select OUT;    $| = 1;
-ReadMode 4;            # Nodelay on kbd.  Pipe is automatically nodelay...
-print while sysread STDIN, $_, 1<<16;
+require Term::ReadKey if $rl;
+Term::ReadKey::ReadMode(4) if $rl; # Nodelay on kbd.  Pipe is automatically nodelay...
+print while sysread STDIN, $_, 1<<($rl ? 16 : 0);
 ES
+        or warn "system P_SESSION: $!, $^E" and 0)
        and close $in1 and close $out2 ) {
-      $pidprompt = '';         # Shown anyway in titlebar
+      $pidprompt = '';                 # Shown anyway in titlebar
       reset_IN_OUT($in2, $out1);
       $tty = '*reset*';
       return '';                       # Indicate that reset_IN_OUT is called
@@ -2083,6 +2293,8 @@ EOP
 EOP
     } elsif ($in ne '') {
       TTY($in);
+    } else {
+      $console = '';           # Indicate no need to open-from-the-console 
     }
     undef $fork_TTY;
 }
@@ -2106,6 +2318,7 @@ sub readline {
   if (@typeahead) {
     my $left = @typeahead;
     my $got = shift @typeahead;
+    local $\ = '';
     print $OUT "auto(-$left)", shift, $got, "\n";
     $term->AddHistory($got) 
       if length($got) > 1 and defined $term->Features->{addHistory};
@@ -2159,10 +2372,11 @@ sub option_val {
 
 sub parse_options {
     local($_)= @_;
+    local $\ = '';
     # too dangerous to let intuitive usage overwrite important things
     # defaultion should never be the default
     my %opt_needs_val = map { ( $_ => 1 ) } qw{
-        arrayDepth hashDepth LineInfo maxTraceLen ornaments windowSize
+        dumpDepth arrayDepth hashDepth LineInfo maxTraceLen ornaments windowSize
         pager quote ReadLine recallCommand RemotePort ShellBang TTY
     };
     while (length) {
@@ -2179,7 +2393,6 @@ sub parse_options {
            $val_defaulted = 1;
            $val = "1";  #  this is an evil default; make 'em set it!
        } elsif ($sep eq "=") {
-
             if (s/ (["']) ( (?: \\. | (?! \1 ) [^\\] )* ) \1 //x) { 
                 my $quote = $1;
                 ($val = $2) =~ s/\\([$quote\\])/$1/g;
@@ -2205,7 +2418,8 @@ sub parse_options {
        print($OUT "Ambiguous option `$opt'\n"), next   if $matches > 1;
 
        if ($opt_needs_val{$option} && $val_defaulted) {
-           print $OUT "Option `$opt' is non-boolean.  Use `O $option=VAL' to set, `O $option?' to query\n";
+                        my $cmd = ($CommandSet eq '580') ? 'o' : 'O';
+           print $OUT "Option `$opt' is non-boolean.  Use `$cmd $option=VAL' to set, `$cmd $option?' to query\n";
            next;
        } 
 
@@ -2267,6 +2481,7 @@ sub catch {
 sub warn {
     my($msg)= join("",@_);
     $msg .= ": $!\n" unless $msg =~ /\n$/;
+    local $\ = '';
     print $OUT $msg;
 }
 
@@ -2301,7 +2516,7 @@ sub TTY {
     }
     &warn("Too late to set TTY, enabled on next `R'!\n") if $term and @_;
     # Useful if done through PERLDB_OPTS:
-    $tty = shift if @_;
+    $console = $tty = shift if @_;
     $tty or $console;
 }
 
@@ -2333,6 +2548,7 @@ sub tkRunning {
     if (${$term->Features}{tkRunning}) {
         return $term->tkRunning(@_);
     } else {
+       local $\ = '';
        print $OUT "tkRunning not supported by current ReadLine package.\n";
        0;
     }
@@ -2399,7 +2615,7 @@ sub LineInfo {
     $lineinfo;
 }
 
-sub list_versions {
+sub list_modules { # versions
   my %version;
   my $file;
   for (keys %INC) {
@@ -2422,6 +2638,183 @@ sub sethelp {
     #      eeevil ornaments enabled.  This is an insane mess.
 
     $help = "
+Help is currently only available for the new 580 CommandSet, 
+if you really want old behaviour, presumably you know what 
+you're doing ?-)
+
+B<T>           Stack trace.
+B<s> [I<expr>] Single step [in I<expr>].
+B<n> [I<expr>] Next, steps over subroutine calls [in I<expr>].
+<B<CR>>                Repeat last B<n> or B<s> command.
+B<r>           Return from current subroutine.
+B<c> [I<line>|I<sub>]  Continue; optionally inserts a one-time-only breakpoint
+               at the specified position.
+B<l> I<min>B<+>I<incr> List I<incr>+1 lines starting at I<min>.
+B<l> I<min>B<->I<max>  List lines I<min> through I<max>.
+B<l> I<line>           List single I<line>.
+B<l> I<subname>        List first window of lines from subroutine.
+B<l> I<\$var>          List first window of lines from subroutine referenced by I<\$var>.
+B<l>           List next window of lines.
+B<->           List previous window of lines.
+B<v> [I<line>] View window around I<line>.
+B<.>           Return to the executed line.
+B<f> I<filename>       Switch to viewing I<filename>. File must be already loaded.
+               I<filename> may be either the full name of the file, or a regular
+               expression matching the full file name:
+               B<f> I</home/me/foo.pl> and B<f> I<oo\\.> may access the same file.
+               Evals (with saved bodies) are considered to be filenames:
+               B<f> I<(eval 7)> and B<f> I<eval 7\\b> access the body of the 7th eval
+               (in the order of execution).
+B</>I<pattern>B</>     Search forwards for I<pattern>; final B</> is optional.
+B<?>I<pattern>B<?>     Search backwards for I<pattern>; final B<?> is optional.
+B<L> [I<a|b|w>]                List actions and or breakpoints and or watch-expressions.
+B<S> [[B<!>]I<pattern>]        List subroutine names [not] matching I<pattern>.
+B<t>           Toggle trace mode.
+B<t> I<expr>           Trace through execution of I<expr>.
+B<b>           Sets breakpoint on current line)
+B<b> [I<line>] [I<condition>]
+               Set breakpoint; I<line> defaults to the current execution line;
+               I<condition> breaks if it evaluates to true, defaults to '1'.
+B<b> I<subname> [I<condition>]
+               Set breakpoint at first line of subroutine.
+B<b> I<\$var>          Set breakpoint at first line of subroutine referenced by I<\$var>.
+B<b> B<load> I<filename> Set breakpoint on 'require'ing the given file.
+B<b> B<postpone> I<subname> [I<condition>]
+               Set breakpoint at first line of subroutine after 
+               it is compiled.
+B<b> B<compile> I<subname>
+               Stop after the subroutine is compiled.
+B<B> [I<line>] Delete the breakpoint for I<line>.
+B<B> I<*>             Delete all breakpoints.
+B<a> [I<line>] I<command>
+               Set an action to be done before the I<line> is executed;
+               I<line> defaults to the current execution line.
+               Sequence is: check for breakpoint/watchpoint, print line
+               if necessary, do action, prompt user if necessary,
+               execute line.
+B<a>           Does nothing
+B<A> [I<line>] Delete the action for I<line>.
+B<A> I<*>             Delete all actions.
+B<w> I<expr>           Add a global watch-expression.
+B<w>                   Does nothing
+B<W> I<expr>           Delete a global watch-expression.
+B<W> I<*>             Delete all watch-expressions.
+B<V> [I<pkg> [I<vars>]]        List some (default all) variables in package (default current).
+               Use B<~>I<pattern> and B<!>I<pattern> for positive and negative regexps.
+B<X> [I<vars>] Same as \"B<V> I<currentpackage> [I<vars>]\".
+B<x> I<expr>           Evals expression in list context, dumps the result.
+B<m> I<expr>           Evals expression in list context, prints methods callable
+               on the first element of the result.
+B<m> I<class>          Prints methods callable via the given class.
+B<M>           Show versions of loaded modules.
+
+B<<> ?                 List Perl commands to run before each prompt.
+B<<> I<expr>           Define Perl command to run before each prompt.
+B<<<> I<expr>          Add to the list of Perl commands to run before each prompt.
+B<>> ?                 List Perl commands to run after each prompt.
+B<>> I<expr>           Define Perl command to run after each prompt.
+B<>>B<>> I<expr>               Add to the list of Perl commands to run after each prompt.
+B<{> I<db_command>     Define debugger command to run before each prompt.
+B<{> ?                 List debugger commands to run before each prompt.
+B<{{> I<db_command>    Add to the list of debugger commands to run before each prompt.
+B<$prc> I<number>      Redo a previous command (default previous command).
+B<$prc> I<-number>     Redo number'th-to-last command.
+B<$prc> I<pattern>     Redo last command that started with I<pattern>.
+               See 'B<O> I<recallCommand>' too.
+B<$psh$psh> I<cmd>     Run cmd in a subprocess (reads from DB::IN, writes to DB::OUT)"
+  . ( $rc eq $sh ? "" : "
+B<$psh> [I<cmd>]       Run I<cmd> in subshell (forces \"\$SHELL -c 'cmd'\")." ) . "
+               See 'B<O> I<shellBang>' too.
+B<@>I<file>            Execute I<file> containing debugger commands (may nest).
+B<H> I<-number>        Display last number commands (default all).
+B<p> I<expr>           Same as \"I<print {DB::OUT} expr>\" in current package.
+B<|>I<dbcmd>           Run debugger command, piping DB::OUT to current pager.
+B<||>I<dbcmd>          Same as B<|>I<dbcmd> but DB::OUT is temporarilly select()ed as well.
+B<\=> [I<alias> I<value>]      Define a command alias, or list current aliases.
+I<command>             Execute as a perl statement in current package.
+B<R>           Pure-man-restart of debugger, some of debugger state
+               and command-line options may be lost.
+               Currently the following settings are preserved:
+               history, breakpoints and actions, debugger B<O>ptions 
+               and the following command-line options: I<-w>, I<-I>, I<-e>.
+
+B<o> [I<opt>] ...      Set boolean option to true
+B<o> [I<opt>B<?>]      Query options
+B<o> [I<opt>B<=>I<val>] [I<opt>=B<\">I<val>B<\">] ... 
+               Set options.  Use quotes in spaces in value.
+    I<recallCommand>, I<ShellBang>     chars used to recall command or spawn shell;
+    I<pager>                   program for output of \"|cmd\";
+    I<tkRunning>                       run Tk while prompting (with ReadLine);
+    I<signalLevel> I<warnLevel> I<dieLevel>    level of verbosity;
+    I<inhibit_exit>            Allows stepping off the end of the script.
+    I<ImmediateStop>           Debugger should stop as early as possible.
+    I<RemotePort>                      Remote hostname:port for remote debugging
+  The following options affect what happens with B<V>, B<X>, and B<x> commands:
+    I<arrayDepth>, I<hashDepth>        print only first N elements ('' for all);
+    I<compactDump>, I<veryCompact>     change style of array and hash dump;
+    I<globPrint>                       whether to print contents of globs;
+    I<DumpDBFiles>             dump arrays holding debugged files;
+    I<DumpPackages>            dump symbol tables of packages;
+    I<DumpReused>                      dump contents of \"reused\" addresses;
+    I<quote>, I<HighBit>, I<undefPrint>        change style of string dump;
+    I<bareStringify>           Do not print the overload-stringified value;
+  Other options include:
+    I<PrintRet>                affects printing of return value after B<r> command,
+    I<frame>           affects printing messages on subroutine entry/exit.
+    I<AutoTrace>       affects printing messages on possible breaking points.
+    I<maxTraceLen>     gives max length of evals/args listed in stack trace.
+    I<ornaments>       affects screen appearance of the command line.
+    I<CreateTTY>       bits control attempts to create a new TTY on events:
+                       1: on fork()    2: debugger is started inside debugger
+                       4: on startup
+       During startup options are initialized from \$ENV{PERLDB_OPTS}.
+       You can put additional initialization options I<TTY>, I<noTTY>,
+       I<ReadLine>, I<NonStop>, and I<RemotePort> there (or use
+       `B<R>' after you set them).
+
+B<q> or B<^D>          Quit. Set B<\$DB::finished = 0> to debug global destruction.
+B<h>           Summary of debugger commands.
+B<h> [I<db_command>]   Get help [on a specific debugger command], enter B<|h> to page.
+B<h h>         Long help for debugger commands
+B<$doccmd> I<manpage>  Runs the external doc viewer B<$doccmd> command on the 
+               named Perl I<manpage>, or on B<$doccmd> itself if omitted.
+               Set B<\$DB::doccmd> to change viewer.
+
+Type `|h h' for a paged display if this was too hard to read.
+
+"; # Fix balance of vi % matching: }}}}
+
+    #  note: tabs in the following section are not-so-helpful
+    $summary = <<"END_SUM";
+I<List/search source lines:>               I<Control script execution:>
+  B<l> [I<ln>|I<sub>]  List source code            B<T>           Stack trace
+  B<-> or B<.>      List previous/current line  B<s> [I<expr>]    Single step [in expr]
+  B<v> [I<line>]    View around line            B<n> [I<expr>]    Next, steps over subs
+  B<f> I<filename>  View source in file         <B<CR>/B<Enter>>  Repeat last B<n> or B<s>
+  B</>I<pattern>B</> B<?>I<patt>B<?>   Search forw/backw    B<r>           Return from subroutine
+  B<M>           Show module versions        B<c> [I<ln>|I<sub>]  Continue until position
+I<Debugger controls:>                        B<L>           List break/watch/actions
+  B<o> [...]     Set debugger options        B<t> [I<expr>]    Toggle trace [trace expr]
+  B<<>[B<<>]|B<{>[B<{>]|B<>>[B<>>] [I<cmd>] Do pre/post-prompt B<b> [I<ln>|I<event>|I<sub>] [I<cnd>] Set breakpoint
+  B<$prc> [I<N>|I<pat>]   Redo a previous command     B<B> I<ln|*>      Delete a/all breakpoints
+  B<H> [I<-num>]    Display last num commands   B<a> [I<ln>] I<cmd>  Do cmd before line
+  B<=> [I<a> I<val>]   Define/list an alias        B<A> I<ln|*>      Delete a/all actions
+  B<h> [I<db_cmd>]  Get help on command         B<w> I<expr>      Add a watch expression
+  B<h h>         Complete help page          B<W> I<expr|*>    Delete a/all watch expressions
+  B<|>[B<|>]I<db_cmd>  Send output to pager        B<$psh>\[B<$psh>\] I<syscmd> Run cmd in a subprocess
+  B<q> or B<^D>     Quit                        B<R>           Attempt a restart
+I<Data Examination:>     B<expr>     Execute perl code, also see: B<s>,B<n>,B<t> I<expr>
+  B<x>|B<m> I<expr>       Evals expr in list context, dumps the result or lists methods.
+  B<p> I<expr>         Print expression (uses script's current package).
+  B<S> [[B<!>]I<pat>]     List subroutine names [not] matching pattern
+  B<V> [I<Pk> [I<Vars>]]  List Variables in Package.  Vars can be ~pattern or !pattern.
+  B<X> [I<Vars>]       Same as \"B<V> I<current_package> [I<Vars>]\".
+For more help, type B<h> I<cmd_letter>, or run B<$doccmd perldebug> for all docs.
+END_SUM
+                               # ')}}; # Fix balance of vi % matching
+
+       # and this is really numb...
+       $pre580_help = "
 B<T>           Stack trace.
 B<s> [I<expr>] Single step [in I<expr>].
 B<n> [I<expr>] Next, steps over subroutine calls [in I<expr>].
@@ -2560,7 +2953,7 @@ Type `|h' for a paged display if this was too hard to read.
 "; # Fix balance of vi % matching: }}}}
 
     #  note: tabs in the following section are not-so-helpful
-    $summary = <<"END_SUM";
+    $pre580_summary = <<"END_SUM";
 I<List/search source lines:>               I<Control script execution:>
   B<l> [I<ln>|I<sub>]  List source code            B<T>           Stack trace
   B<-> or B<.>      List previous/current line  B<s> [I<expr>]    Single step [in expr]
@@ -2586,6 +2979,7 @@ I<Data Examination:>     B<expr>     Execute perl code, also see: B<s>,B<n>,B<t>
 For more help, type B<h> I<cmd_letter>, or run B<$doccmd perldebug> for all docs.
 END_SUM
                                # ')}}; # Fix balance of vi % matching
+
 }
 
 sub print_help {
@@ -2633,6 +3027,7 @@ sub print_help {
        . $Term::ReadLine::TermCap::rl_term_set[1]
     }gex;
 
+    local $\ = '';
     print $OUT $_;
 }
 
@@ -2661,6 +3056,7 @@ sub diesignal {
        &warn(Carp::longmess("Signal @_"));
     }
     else {
+       local $\ = '';
        print $DB::OUT "Got signal @_\n";
     }
     kill 'ABRT', $$;
@@ -2732,6 +3128,7 @@ sub warnLevel {
 }
 
 sub dieLevel {
+  local $\ = '';
   if (@_) {
     $prevdie = $SIG{__DIE__} unless $dieLevel;
     $dieLevel = shift;
@@ -2819,6 +3216,8 @@ sub methods_via {
   for $name (grep {defined &{${"${class}::"}{$_}}} 
             sort keys %{"${class}::"}) {
     next if $seen{ $name }++;
+    local $\ = '';
+    local $, = '';
     print $DB::OUT "$prepend$name\n";
   }
   return unless shift;         # Recurse?
@@ -3005,6 +3404,7 @@ sub db_complete {
 }
 
 sub end_report {
+  local $\ = '';
   print $OUT "Use `q' to quit or `R' to restart.  `h q' for details.\n"
 }
 
@@ -3024,6 +3424,123 @@ END {
   DB::fake::at_exit() unless $fall_off_end or $runnonstop;
 }
 
+
+# ===================================== pre580 ================================
+# this is very sad below here...
+#
+
+sub cmd_pre580_null {
+       # do nothing...
+}
+
+sub cmd_pre580_a {
+       my $cmd = shift;
+       if ($cmd =~ /^(\d*)\s*(.*)/) {
+               $i = $1 || $line; $j = $2;
+               if (length $j) {
+                       if ($dbline[$i] == 0) {
+                               print $OUT "Line $i may not have an action.\n";
+                       } else {
+                               $had_breakpoints{$filename} |= 2;
+                               $dbline{$i} =~ s/\0[^\0]*//;
+                               $dbline{$i} .= "\0" . action($j);
+                       }
+               } else {
+                       $dbline{$i} =~ s/\0[^\0]*//;
+                       delete $dbline{$i} if $dbline{$i} eq '';
+               }
+       }
+}
+
+sub cmd_pre580_b {
+       my $cmd    = shift;
+       my $dbline = shift;
+       if ($cmd =~ /^load\b\s*(.*)/) {
+               my $file = $1; $file =~ s/\s+$//;
+               &cmd_b_load($file);
+       } elsif ($cmd =~ /^(postpone|compile)\b\s*([':A-Za-z_][':\w]*)\s*(.*)/) {
+               my $cond = length $3 ? $3 : '1';
+               my ($subname, $break) = ($2, $1 eq 'postpone');
+               $subname =~ s/\'/::/g;
+               $subname = "${'package'}::" . $subname
+               unless $subname =~ /::/;
+               $subname = "main".$subname if substr($subname,0,2) eq "::";
+               $postponed{$subname} = $break ? "break +0 if $cond" : "compile";
+       } elsif ($cmd =~ /^([':A-Za-z_][':\w]*(?:\[.*\])?)\s*(.*)/) { 
+               my $subname = $1;
+               my $cond = length $2 ? $2 : '1';
+               &cmd_b_sub($subname, $cond);
+       } elsif ($cmd =~ /^(\d*)\s*(.*)/) {
+               my $i = $1 || $dbline;
+               my $cond = length $2 ? $2 : '1';
+               &cmd_b_line($i, $cond);
+       }
+}
+
+sub cmd_pre580_D {
+       my $cmd = shift;
+       if ($cmd =~ /^\s*$/) {
+               print $OUT "Deleting all breakpoints...\n";
+               my $file;
+               for $file (keys %had_breakpoints) {
+                       local *dbline = $main::{'_<' . $file};
+                       my $max = $#dbline;
+                       my $was;
+
+                       for ($i = 1; $i <= $max ; $i++) {
+                               if (defined $dbline{$i}) {
+                                       $dbline{$i} =~ s/^[^\0]+//;
+                                       if ($dbline{$i} =~ s/^\0?$//) {
+                                               delete $dbline{$i};
+                                       }
+                               }
+                       }
+
+                       if (not $had_breakpoints{$file} &= ~1) {
+                               delete $had_breakpoints{$file};
+                       }
+               }
+               undef %postponed;
+               undef %postponed_file;
+               undef %break_on_load;
+       }
+}
+
+sub cmd_pre580_h {
+       my $cmd = shift;
+       if ($cmd =~ /^\s*$/) {
+               print_help($pre580_help);
+       } elsif ($cmd =~ /^h\s*/) {
+               print_help($pre580_summary);
+       } elsif ($cmd =~ /^h\s+(\S.*)$/) { 
+               my $asked = $1;                 # for proper errmsg
+               my $qasked = quotemeta($asked); # for searching
+               # XXX: finds CR but not <CR>
+               if ($pre580_help =~ /^<?(?:[IB]<)$qasked/m) {
+                       while ($pre580_help =~ /^(<?(?:[IB]<)$qasked([\s\S]*?)\n)(?!\s)/mg) {
+                               print_help($1);
+                       }
+               } else {
+                       print_help("B<$asked> is not a debugger command.\n");
+               }
+       }
+}
+
+sub cmd_pre580_W {
+       my $cmd = shift;
+       if ($cmd =~ /^$/) { 
+               $trace &= ~2;
+               @to_watch = @old_watch = ();
+       } elsif ($cmd =~ /^(.*)/s) {
+               push @to_watch, $1;
+               $evalarg = $1;
+               my ($val) = &eval;
+               $val = (defined $val) ? "'$val'" : 'undef' ;
+               push @old_watch, $val;
+               $trace |= 2;
+       }
+}
+
 package DB::fake;
 
 sub at_exit {
@@ -3033,3 +3550,4 @@ sub at_exit {
 package DB;                    # Do not trace this 1; below!
 
 1;
+