This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Refactoring the /Can't return (?:array|hash) to scalar context/ croak
[perl5.git] / lib / Dumpvalue.pm
index 22a10af..f182297 100644 (file)
@@ -1,8 +1,10 @@
-require 5.005;                 # For (defined ref) and $#$v
+use 5.006_001;                 # for (defined ref) and $#$v and our
 package Dumpvalue;
 use strict;
-use vars qw(%address *stab %subs);
+our $VERSION = '1.12';
+our(%address, $stab, @stab, %stab, %subs);
 
+# documentation nits, handle complex data structures better by chromatic
 # translate control chars to ^X - Randal Schwartz
 # Modifications to print types by Peter Gordon v1.0
 
@@ -227,9 +229,9 @@ sub unwrap {
     if ($self->{compactDump} && !grep(ref $_, @{$v})) {
       if ($#$v >= 0) {
        $short = $sp . "0..$#{$v}  " .
-         join(" ",
-              map {$self->stringify($_)} @{$v}[0..$tArrayDepth])
-           . "$shortmore";
+         join(" ", 
+              map {exists $v->[$_] ? $self->stringify($v->[$_]) : "empty"} ($[..$tArrayDepth)
+             ) . "$shortmore";
       } else {
        $short = $sp . "empty array";
       }
@@ -238,7 +240,11 @@ sub unwrap {
     for my $num ($[ .. $tArrayDepth) {
       return if $DB::signal and $self->{stopDbSignal};
       print "$sp$num  ";
-      $self->DumpElem($v->[$num], $s);
+      if (exists $v->[$num]) {
+        $self->DumpElem($v->[$num], $s);
+      } else {
+       print "empty slot\n";
+      }
     }
     print "$sp  empty array\n" unless @$v;
     print "$sp$more" if defined $more ;
@@ -347,16 +353,30 @@ sub dumpglob {
   }
 }
 
+sub CvGV_name {
+  my $self = shift;
+  my $in = shift;
+  return if $self->{skipCvGV}; # Backdoor to avoid problems if XS broken...
+  $in = \&$in;                 # Hard reference...
+  eval {require Devel::Peek; 1} or return;
+  my $gv = Devel::Peek::CvGV($in) or return;
+  *$gv{PACKAGE} . '::' . *$gv{NAME};
+}
+
 sub dumpsub {
   my $self = shift;
   my ($off,$sub) = @_;
+  my $ini = $sub;
+  my $s;
   $sub = $1 if $sub =~ /^\{\*(.*)\}$/;
-  my $subref = \&$sub;
-  my $place = $DB::sub{$sub} || (($sub = $subs{"$subref"}) && $DB::sub{$sub})
-    || ($self->{subdump} && ($sub = $self->findsubs("$subref"))
-       && $DB::sub{$sub});
+  my $subref = defined $1 ? \&$sub : \&$ini;
+  my $place = $DB::sub{$sub} || (($s = $subs{"$subref"}) && $DB::sub{$s})
+    || (($s = $self->CvGV_name($subref)) && $DB::sub{$s})
+    || ($self->{subdump} && ($s = $self->findsubs("$subref"))
+       && $DB::sub{$s});
+  $s = $sub unless defined $s;
   $place = '???' unless defined $place;
-  print( (' ' x $off) .  "&$sub in $place\n" );
+  print( (' ' x $off) .  "&$s in $place\n" );
 }
 
 sub findsubs {
@@ -390,7 +410,8 @@ sub dumpvars {
     next if @vars && !grep( matchvar($key, $_), @vars );
     if ($self->{usageOnly}) {
       $self->globUsage(\$val, $key)
-       unless $package eq 'Dumpvalue' and $key eq 'stab';
+       if ($package ne 'Dumpvalue' or $key ne 'stab')
+          and ref(\$val) eq 'GLOB';
     } else {
       $self->dumpglob($package, 0,$key, $val);
     }
@@ -408,7 +429,14 @@ EOP
 
 sub scalarUsage {
   my $self = shift;
-  my $size = length($_[0]);
+  my $size;
+  if (UNIVERSAL::isa($_[0], 'ARRAY')) {
+       $size = $self->arrayUsage($_[0]);
+  } elsif (UNIVERSAL::isa($_[0], 'HASH')) {
+       $size = $self->hashUsage($_[0]);
+  } elsif (!ref($_[0])) {
+       $size = length($_[0]);
+  }
   $self->{TotalStrings} += $size;
   $self->{Strings}++;
   $size;
@@ -457,13 +485,14 @@ sub globUsage {                   # glob ref, name
 
 Dumpvalue - provides screen dump of Perl data.
 
-=head1 SYNOPSYS
+=head1 SYNOPSIS
 
   use Dumpvalue;
   my $dumper = new Dumpvalue;
   $dumper->set(globPrint => 1);
   $dumper->dumpValue(\*::);
   $dumper->dumpvars('main');
+  my $dump = $dumper->stringify($some_value);
 
 =head1 DESCRIPTION
 
@@ -475,7 +504,7 @@ A new dumper is created by a call
 
 Recognized options:
 
-=over
+=over 4
 
 =item C<arrayDepth>, C<hashDepth>
 
@@ -491,28 +520,28 @@ may be printed on one line.
 
 Whether to print contents of globs.
 
-=item C<DumpDBFiles>
+=item C<dumpDBFiles>
 
 Dump arrays holding contents of debugged files.
 
-=item C<DumpPackages>
+=item C<dumpPackages>
 
 Dump symbol tables of packages.
 
-=item C<DumpReused>
+=item C<dumpReused>
 
 Dump contents of "reused" addresses.
 
-=item C<tick>, C<HighBit>, C<printUndef>
+=item C<tick>, C<quoteHighBit>, C<printUndef>
 
 Change style of string dump.  Default value of C<tick> is C<auto>, one
 can enable either double-quotish dump, or single-quotish by setting it
 to C<"> or C<'>.  By default, characters with high bit set are printed
-I<as is>.
+I<as is>.  If C<quoteHighBit> is set, they will be quoted.
 
-=item C<UsageOnly>
+=item C<usageOnly>
 
-I<very> rudimentally per-package memory usage dump.  If set,
+rudimentally per-package memory usage dump.  If set,
 C<dumpvars> calculates total size of strings in variables in the package.
 
 =item unctrl
@@ -543,17 +572,29 @@ method and set() method (which accept multiple arguments).
 
 =head2 Methods
 
-=over
+=over 4
 
 =item dumpValue
 
   $dumper->dumpValue($value);
   $dumper->dumpValue([$value1, $value2]);
 
+Prints a dump to the currently selected filehandle.
+
 =item dumpValues
 
   $dumper->dumpValues($value1, $value2);
 
+Same as C< $dumper->dumpValue([$value1, $value2]); >.
+
+=item stringify
+
+  my $dump = $dumper->stringify($value [,$noticks] );
+
+Returns the dump of a single scalar without printing. If the second
+argument is true, the return value does not contain enclosing ticks.
+Does not handle data structures.
+
 =item dumpvars
 
   $dumper->dumpvars('my_package');
@@ -575,7 +616,7 @@ given quote char.  Possible values are C<auto>, C<'> and C<">.
 
 =item set_unctrl
 
-  $d->set_unctrl('"');
+  $d->set_unctrl('unctrl');
 
 Sets C<unctrl> option with checking for an invalid argument.
 Possible values are C<unctrl> and C<quote>.