[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/se3-unattended/var/se3/unattended/install/linuxaux/opt/perl/lib/5.10.0/ -> Dumpvalue.pm (source)

   1  use 5.006_001;            # for (defined ref) and $#$v and our
   2  package Dumpvalue;
   3  use strict;
   4  our $VERSION = '1.12';
   5  our(%address, $stab, @stab, %stab, %subs);
   6  
   7  # documentation nits, handle complex data structures better by chromatic
   8  # translate control chars to ^X - Randal Schwartz
   9  # Modifications to print types by Peter Gordon v1.0
  10  
  11  # Ilya Zakharevich -- patches after 5.001 (and some before ;-)
  12  
  13  # Won't dump symbol tables and contents of debugged files by default
  14  
  15  # (IZ) changes for objectification:
  16  #   c) quote() renamed to method set_quote();
  17  #   d) unctrlSet() renamed to method set_unctrl();
  18  #   f) Compiles with `use strict', but in two places no strict refs is needed:
  19  #      maybe more problems are waiting...
  20  
  21  my %defaults = (
  22          globPrint          => 0,
  23          printUndef          => 1,
  24          tick              => "auto",
  25          unctrl              => 'quote',
  26          subdump              => 1,
  27          dumpReused          => 0,
  28          bareStringify          => 1,
  29          hashDepth          => '',
  30          arrayDepth          => '',
  31          dumpDBFiles          => '',
  32          dumpPackages          => '',
  33          quoteHighBit          => '',
  34          usageOnly          => '',
  35          compactDump          => '',
  36          veryCompact          => '',
  37          stopDbSignal          => '',
  38             );
  39  
  40  sub new {
  41    my $class = shift;
  42    my %opt = (%defaults, @_);
  43    bless \%opt, $class;
  44  }
  45  
  46  sub set {
  47    my $self = shift;
  48    my %opt = @_;
  49    @$self{keys %opt} = values %opt;
  50  }
  51  
  52  sub get {
  53    my $self = shift;
  54    wantarray ? @$self{@_} : $$self{pop @_};
  55  }
  56  
  57  sub dumpValue {
  58    my $self = shift;
  59    die "usage: \$dumper->dumpValue(value)" unless @_ == 1;
  60    local %address;
  61    local $^W=0;
  62    (print "undef\n"), return unless defined $_[0];
  63    (print $self->stringify($_[0]), "\n"), return unless ref $_[0];
  64    $self->unwrap($_[0],0);
  65  }
  66  
  67  sub dumpValues {
  68    my $self = shift;
  69    local %address;
  70    local $^W=0;
  71    (print "undef\n"), return unless defined $_[0];
  72    $self->unwrap(\@_,0);
  73  }
  74  
  75  # This one is good for variable names:
  76  
  77  sub unctrl {
  78    local($_) = @_;
  79  
  80    return \$_ if ref \$_ eq "GLOB";
  81    s/([\001-\037\177])/'^'.pack('c',ord($1)^64)/eg;
  82    $_;
  83  }
  84  
  85  sub stringify {
  86    my $self = shift;
  87    local $_ = shift;
  88    my $noticks = shift;
  89    my $tick = $self->{tick};
  90  
  91    return 'undef' unless defined $_ or not $self->{printUndef};
  92    return $_ . "" if ref \$_ eq 'GLOB';
  93    { no strict 'refs';
  94      $_ = &{'overload::StrVal'}($_)
  95        if $self->{bareStringify} and ref $_
  96      and %overload:: and defined &{'overload::StrVal'};
  97    }
  98  
  99    if ($tick eq 'auto') {
 100      if (/[\000-\011\013-\037\177]/) {
 101        $tick = '"';
 102      } else {
 103        $tick = "'";
 104      }
 105    }
 106    if ($tick eq "'") {
 107      s/([\'\\])/\\$1/g;
 108    } elsif ($self->{unctrl} eq 'unctrl') {
 109      s/([\"\\])/\\$1/g ;
 110      s/([\000-\037\177])/'^'.pack('c',ord($1)^64)/eg;
 111      s/([\200-\377])/'\\0x'.sprintf('%2X',ord($1))/eg
 112        if $self->{quoteHighBit};
 113    } elsif ($self->{unctrl} eq 'quote') {
 114      s/([\"\\\$\@])/\\$1/g if $tick eq '"';
 115      s/\033/\\e/g;
 116      s/([\000-\037\177])/'\\c'.chr(ord($1)^64)/eg;
 117    }
 118    s/([\200-\377])/'\\'.sprintf('%3o',ord($1))/eg if $self->{quoteHighBit};
 119    ($noticks || /^\d+(\.\d*)?\Z/)
 120      ? $_
 121        : $tick . $_ . $tick;
 122  }
 123  
 124  sub DumpElem {
 125    my ($self, $v) = (shift, shift);
 126    my $short = $self->stringify($v, ref $v);
 127    my $shortmore = '';
 128    if ($self->{veryCompact} && ref $v
 129        && (ref $v eq 'ARRAY' and !grep(ref $_, @$v) )) {
 130      my $depth = $#$v;
 131      ($shortmore, $depth) = (' ...', $self->{arrayDepth} - 1)
 132        if $self->{arrayDepth} and $depth >= $self->{arrayDepth};
 133      my @a = map $self->stringify($_), @$v[0..$depth];
 134      print "0..$#{$v}  @a$shortmore\n";
 135    } elsif ($self->{veryCompact} && ref $v
 136         && (ref $v eq 'HASH') and !grep(ref $_, values %$v)) {
 137      my @a = sort keys %$v;
 138      my $depth = $#a;
 139      ($shortmore, $depth) = (' ...', $self->{hashDepth} - 1)
 140        if $self->{hashDepth} and $depth >= $self->{hashDepth};
 141      my @b = map {$self->stringify($_) . " => " . $self->stringify($$v{$_})}
 142        @a[0..$depth];
 143      local $" = ', ';
 144      print "@b$shortmore\n";
 145    } else {
 146      print "$short\n";
 147      $self->unwrap($v,shift);
 148    }
 149  }
 150  
 151  sub unwrap {
 152    my $self = shift;
 153    return if $DB::signal and $self->{stopDbSignal};
 154    my ($v) = shift ;
 155    my ($s) = shift ;        # extra no of spaces
 156    my $sp;
 157    my (%v,@v,$address,$short,$fileno);
 158  
 159    $sp = " " x $s ;
 160    $s += 3 ;
 161  
 162    # Check for reused addresses
 163    if (ref $v) {
 164      my $val = $v;
 165      { no strict 'refs';
 166        $val = &{'overload::StrVal'}($v)
 167      if %overload:: and defined &{'overload::StrVal'};
 168      }
 169      ($address) = $val =~ /(0x[0-9a-f]+)\)$/ ;
 170      if (!$self->{dumpReused} && defined $address) {
 171        $address{$address}++ ;
 172        if ( $address{$address} > 1 ) {
 173      print "$sp}-> REUSED_ADDRESS\n" ;
 174      return ;
 175        }
 176      }
 177    } elsif (ref \$v eq 'GLOB') {
 178      $address = "$v" . "";    # To avoid a bug with globs
 179      $address{$address}++ ;
 180      if ( $address{$address} > 1 ) {
 181        print "$sp}*DUMPED_GLOB*\n" ;
 182        return ;
 183      }
 184    }
 185  
 186    if (ref $v eq 'Regexp') {
 187      my $re = "$v";
 188      $re =~ s,/,\\/,g;
 189      print "$sp-> qr/$re/\n";
 190      return;
 191    }
 192  
 193    if ( UNIVERSAL::isa($v, 'HASH') ) {
 194      my @sortKeys = sort keys(%$v) ;
 195      my $more;
 196      my $tHashDepth = $#sortKeys ;
 197      $tHashDepth = $#sortKeys < $self->{hashDepth}-1 ? $#sortKeys : $self->{hashDepth}-1
 198        unless $self->{hashDepth} eq '' ;
 199      $more = "....\n" if $tHashDepth < $#sortKeys ;
 200      my $shortmore = "";
 201      $shortmore = ", ..." if $tHashDepth < $#sortKeys ;
 202      $#sortKeys = $tHashDepth ;
 203      if ($self->{compactDump} && !grep(ref $_, values %{$v})) {
 204        $short = $sp;
 205        my @keys;
 206        for (@sortKeys) {
 207      push @keys, $self->stringify($_) . " => " . $self->stringify($v->{$_});
 208        }
 209        $short .= join ', ', @keys;
 210        $short .= $shortmore;
 211        (print "$short\n"), return if length $short <= $self->{compactDump};
 212      }
 213      for my $key (@sortKeys) {
 214        return if $DB::signal and $self->{stopDbSignal};
 215        my $value = $ {$v}{$key} ;
 216        print $sp, $self->stringify($key), " => ";
 217        $self->DumpElem($value, $s);
 218      }
 219      print "$sp  empty hash\n" unless @sortKeys;
 220      print "$sp$more" if defined $more ;
 221    } elsif ( UNIVERSAL::isa($v, 'ARRAY') ) {
 222      my $tArrayDepth = $#{$v} ;
 223      my $more ;
 224      $tArrayDepth = $#$v < $self->{arrayDepth}-1 ? $#$v : $self->{arrayDepth}-1
 225        unless  $self->{arrayDepth} eq '' ;
 226      $more = "....\n" if $tArrayDepth < $#{$v} ;
 227      my $shortmore = "";
 228      $shortmore = " ..." if $tArrayDepth < $#{$v} ;
 229      if ($self->{compactDump} && !grep(ref $_, @{$v})) {
 230        if ($#$v >= 0) {
 231      $short = $sp . "0..$#{$v}  " .
 232        join(" ", 
 233             map {exists $v->[$_] ? $self->stringify($v->[$_]) : "empty"} ($[..$tArrayDepth)
 234            ) . "$shortmore";
 235        } else {
 236      $short = $sp . "empty array";
 237        }
 238        (print "$short\n"), return if length $short <= $self->{compactDump};
 239      }
 240      for my $num ($[ .. $tArrayDepth) {
 241        return if $DB::signal and $self->{stopDbSignal};
 242        print "$sp$num  ";
 243        if (exists $v->[$num]) {
 244          $self->DumpElem($v->[$num], $s);
 245        } else {
 246      print "empty slot\n";
 247        }
 248      }
 249      print "$sp  empty array\n" unless @$v;
 250      print "$sp$more" if defined $more ;
 251    } elsif (  UNIVERSAL::isa($v, 'SCALAR') or ref $v eq 'REF' ) {
 252      print "$sp-> ";
 253      $self->DumpElem($$v, $s);
 254    } elsif ( UNIVERSAL::isa($v, 'CODE') ) {
 255      print "$sp-> ";
 256      $self->dumpsub(0, $v);
 257    } elsif ( UNIVERSAL::isa($v, 'GLOB') ) {
 258      print "$sp-> ",$self->stringify($$v,1),"\n";
 259      if ($self->{globPrint}) {
 260        $s += 3;
 261        $self->dumpglob('', $s, "{$$v}", $$v, 1);
 262      } elsif (defined ($fileno = fileno($v))) {
 263        print( (' ' x ($s+3)) .  "FileHandle({$$v}) => fileno($fileno)\n" );
 264      }
 265    } elsif (ref \$v eq 'GLOB') {
 266      if ($self->{globPrint}) {
 267        $self->dumpglob('', $s, "{$v}", $v, 1);
 268      } elsif (defined ($fileno = fileno(\$v))) {
 269        print( (' ' x $s) .  "FileHandle({$v}) => fileno($fileno)\n" );
 270      }
 271    }
 272  }
 273  
 274  sub matchvar {
 275    $_[0] eq $_[1] or
 276      ($_[1] =~ /^([!~])(.)([\x00-\xff]*)/) and
 277        ($1 eq '!') ^ (eval {($_[2] . "::" . $_[0]) =~ /$2$3/});
 278  }
 279  
 280  sub compactDump {
 281    my $self = shift;
 282    $self->{compactDump} = shift if @_;
 283    $self->{compactDump} = 6*80-1 
 284      if $self->{compactDump} and $self->{compactDump} < 2;
 285    $self->{compactDump};
 286  }
 287  
 288  sub veryCompact {
 289    my $self = shift;
 290    $self->{veryCompact} = shift if @_;
 291    $self->compactDump(1) if !$self->{compactDump} and $self->{veryCompact};
 292    $self->{veryCompact};
 293  }
 294  
 295  sub set_unctrl {
 296    my $self = shift;
 297    if (@_) {
 298      my $in = shift;
 299      if ($in eq 'unctrl' or $in eq 'quote') {
 300        $self->{unctrl} = $in;
 301      } else {
 302        print "Unknown value for `unctrl'.\n";
 303      }
 304    }
 305    $self->{unctrl};
 306  }
 307  
 308  sub set_quote {
 309    my $self = shift;
 310    if (@_ and $_[0] eq '"') {
 311      $self->{tick} = '"';
 312      $self->{unctrl} = 'quote';
 313    } elsif (@_ and $_[0] eq 'auto') {
 314      $self->{tick} = 'auto';
 315      $self->{unctrl} = 'quote';
 316    } elsif (@_) {        # Need to set
 317      $self->{tick} = "'";
 318      $self->{unctrl} = 'unctrl';
 319    }
 320    $self->{tick};
 321  }
 322  
 323  sub dumpglob {
 324    my $self = shift;
 325    return if $DB::signal and $self->{stopDbSignal};
 326    my ($package, $off, $key, $val, $all) = @_;
 327    local(*stab) = $val;
 328    my $fileno;
 329    if (($key !~ /^_</ or $self->{dumpDBFiles}) and defined $stab) {
 330      print( (' ' x $off) . "\$", &unctrl($key), " = " );
 331      $self->DumpElem($stab, 3+$off);
 332    }
 333    if (($key !~ /^_</ or $self->{dumpDBFiles}) and @stab) {
 334      print( (' ' x $off) . "\@$key = (\n" );
 335      $self->unwrap(\@stab,3+$off) ;
 336      print( (' ' x $off) .  ")\n" );
 337    }
 338    if ($key ne "main::" && $key ne "DB::" && %stab
 339        && ($self->{dumpPackages} or $key !~ /::$/)
 340        && ($key !~ /^_</ or $self->{dumpDBFiles})
 341        && !($package eq "Dumpvalue" and $key eq "stab")) {
 342      print( (' ' x $off) . "\%$key = (\n" );
 343      $self->unwrap(\%stab,3+$off) ;
 344      print( (' ' x $off) .  ")\n" );
 345    }
 346    if (defined ($fileno = fileno(*stab))) {
 347      print( (' ' x $off) .  "FileHandle($key) => fileno($fileno)\n" );
 348    }
 349    if ($all) {
 350      if (defined &stab) {
 351        $self->dumpsub($off, $key);
 352      }
 353    }
 354  }
 355  
 356  sub CvGV_name {
 357    my $self = shift;
 358    my $in = shift;
 359    return if $self->{skipCvGV};    # Backdoor to avoid problems if XS broken...
 360    $in = \&$in;            # Hard reference...
 361    eval {require Devel::Peek; 1} or return;
 362    my $gv = Devel::Peek::CvGV($in) or return;
 363    *$gv{PACKAGE} . '::' . *$gv{NAME};
 364  }
 365  
 366  sub dumpsub {
 367    my $self = shift;
 368    my ($off,$sub) = @_;
 369    my $ini = $sub;
 370    my $s;
 371    $sub = $1 if $sub =~ /^\{\*(.*)\}$/;
 372    my $subref = defined $1 ? \&$sub : \&$ini;
 373    my $place = $DB::sub{$sub} || (($s = $subs{"$subref"}) && $DB::sub{$s})
 374      || (($s = $self->CvGV_name($subref)) && $DB::sub{$s})
 375      || ($self->{subdump} && ($s = $self->findsubs("$subref"))
 376      && $DB::sub{$s});
 377    $s = $sub unless defined $s;
 378    $place = '???' unless defined $place;
 379    print( (' ' x $off) .  "&$s in $place\n" );
 380  }
 381  
 382  sub findsubs {
 383    my $self = shift;
 384    return undef unless %DB::sub;
 385    my ($addr, $name, $loc);
 386    while (($name, $loc) = each %DB::sub) {
 387      $addr = \&$name;
 388      $subs{"$addr"} = $name;
 389    }
 390    $self->{subdump} = 0;
 391    $subs{ shift() };
 392  }
 393  
 394  sub dumpvars {
 395    my $self = shift;
 396    my ($package,@vars) = @_;
 397    local(%address,$^W);
 398    my ($key,$val);
 399    $package .= "::" unless $package =~ /::$/;
 400    *stab = *main::;
 401  
 402    while ($package =~ /(\w+?::)/g) {
 403      *stab = $ {stab}{$1};
 404    }
 405    $self->{TotalStrings} = 0;
 406    $self->{Strings} = 0;
 407    $self->{CompleteTotal} = 0;
 408    while (($key,$val) = each(%stab)) {
 409      return if $DB::signal and $self->{stopDbSignal};
 410      next if @vars && !grep( matchvar($key, $_), @vars );
 411      if ($self->{usageOnly}) {
 412        $self->globUsage(\$val, $key)
 413      if ($package ne 'Dumpvalue' or $key ne 'stab')
 414         and ref(\$val) eq 'GLOB';
 415      } else {
 416        $self->dumpglob($package, 0,$key, $val);
 417      }
 418    }
 419    if ($self->{usageOnly}) {
 420      print <<EOP;
 421  String space: $self->{TotalStrings} bytes in $self->{Strings} strings.
 422  EOP
 423      $self->{CompleteTotal} += $self->{TotalStrings};
 424      print <<EOP;
 425  Grand total = $self->{CompleteTotal} bytes (1 level deep) + overhead.
 426  EOP
 427    }
 428  }
 429  
 430  sub scalarUsage {
 431    my $self = shift;
 432    my $size;
 433    if (UNIVERSAL::isa($_[0], 'ARRAY')) {
 434      $size = $self->arrayUsage($_[0]);
 435    } elsif (UNIVERSAL::isa($_[0], 'HASH')) {
 436      $size = $self->hashUsage($_[0]);
 437    } elsif (!ref($_[0])) {
 438      $size = length($_[0]);
 439    }
 440    $self->{TotalStrings} += $size;
 441    $self->{Strings}++;
 442    $size;
 443  }
 444  
 445  sub arrayUsage {        # array ref, name
 446    my $self = shift;
 447    my $size = 0;
 448    map {$size += $self->scalarUsage($_)} @{$_[0]};
 449    my $len = @{$_[0]};
 450    print "\@$_[1] = $len item", ($len > 1 ? "s" : ""), " (data: $size bytes)\n"
 451        if defined $_[1];
 452    $self->{CompleteTotal} +=  $size;
 453    $size;
 454  }
 455  
 456  sub hashUsage {            # hash ref, name
 457    my $self = shift;
 458    my @keys = keys %{$_[0]};
 459    my @values = values %{$_[0]};
 460    my $keys = $self->arrayUsage(\@keys);
 461    my $values = $self->arrayUsage(\@values);
 462    my $len = @keys;
 463    my $total = $keys + $values;
 464    print "\%$_[1] = $len item", ($len > 1 ? "s" : ""),
 465      " (keys: $keys; values: $values; total: $total bytes)\n"
 466        if defined $_[1];
 467    $total;
 468  }
 469  
 470  sub globUsage {            # glob ref, name
 471    my $self = shift;
 472    local *stab = *{$_[0]};
 473    my $total = 0;
 474    $total += $self->scalarUsage($stab) if defined $stab;
 475    $total += $self->arrayUsage(\@stab, $_[1]) if @stab;
 476    $total += $self->hashUsage(\%stab, $_[1]) 
 477      if %stab and $_[1] ne "main::" and $_[1] ne "DB::";    
 478    #and !($package eq "Dumpvalue" and $key eq "stab"));
 479    $total;
 480  }
 481  
 482  1;
 483  
 484  =head1 NAME
 485  
 486  Dumpvalue - provides screen dump of Perl data.
 487  
 488  =head1 SYNOPSIS
 489  
 490    use Dumpvalue;
 491    my $dumper = new Dumpvalue;
 492    $dumper->set(globPrint => 1);
 493    $dumper->dumpValue(\*::);
 494    $dumper->dumpvars('main');
 495    my $dump = $dumper->stringify($some_value);
 496  
 497  =head1 DESCRIPTION
 498  
 499  =head2 Creation
 500  
 501  A new dumper is created by a call
 502  
 503    $d = new Dumpvalue(option1 => value1, option2 => value2)
 504  
 505  Recognized options:
 506  
 507  =over 4
 508  
 509  =item C<arrayDepth>, C<hashDepth>
 510  
 511  Print only first N elements of arrays and hashes.  If false, prints all the
 512  elements.
 513  
 514  =item C<compactDump>, C<veryCompact>
 515  
 516  Change style of array and hash dump.  If true, short array
 517  may be printed on one line.
 518  
 519  =item C<globPrint>
 520  
 521  Whether to print contents of globs.
 522  
 523  =item C<dumpDBFiles>
 524  
 525  Dump arrays holding contents of debugged files.
 526  
 527  =item C<dumpPackages>
 528  
 529  Dump symbol tables of packages.
 530  
 531  =item C<dumpReused>
 532  
 533  Dump contents of "reused" addresses.
 534  
 535  =item C<tick>, C<quoteHighBit>, C<printUndef>
 536  
 537  Change style of string dump.  Default value of C<tick> is C<auto>, one
 538  can enable either double-quotish dump, or single-quotish by setting it
 539  to C<"> or C<'>.  By default, characters with high bit set are printed
 540  I<as is>.  If C<quoteHighBit> is set, they will be quoted.
 541  
 542  =item C<usageOnly>
 543  
 544  rudimentally per-package memory usage dump.  If set,
 545  C<dumpvars> calculates total size of strings in variables in the package.
 546  
 547  =item unctrl
 548  
 549  Changes the style of printout of strings.  Possible values are
 550  C<unctrl> and C<quote>.
 551  
 552  =item subdump
 553  
 554  Whether to try to find the subroutine name given the reference.
 555  
 556  =item bareStringify
 557  
 558  Whether to write the non-overloaded form of the stringify-overloaded objects.
 559  
 560  =item quoteHighBit
 561  
 562  Whether to print chars with high bit set in binary or "as is".
 563  
 564  =item stopDbSignal
 565  
 566  Whether to abort printing if debugger signal flag is raised.
 567  
 568  =back
 569  
 570  Later in the life of the object the methods may be queries with get()
 571  method and set() method (which accept multiple arguments).
 572  
 573  =head2 Methods
 574  
 575  =over 4
 576  
 577  =item dumpValue
 578  
 579    $dumper->dumpValue($value);
 580    $dumper->dumpValue([$value1, $value2]);
 581  
 582  Prints a dump to the currently selected filehandle.
 583  
 584  =item dumpValues
 585  
 586    $dumper->dumpValues($value1, $value2);
 587  
 588  Same as C< $dumper->dumpValue([$value1, $value2]); >.
 589  
 590  =item stringify
 591  
 592    my $dump = $dumper->stringify($value [,$noticks] );
 593  
 594  Returns the dump of a single scalar without printing. If the second
 595  argument is true, the return value does not contain enclosing ticks.
 596  Does not handle data structures.
 597  
 598  =item dumpvars
 599  
 600    $dumper->dumpvars('my_package');
 601    $dumper->dumpvars('my_package', 'foo', '~bar$', '!......');
 602  
 603  The optional arguments are considered as literal strings unless they
 604  start with C<~> or C<!>, in which case they are interpreted as regular
 605  expressions (possibly negated).
 606  
 607  The second example prints entries with names C<foo>, and also entries
 608  with names which ends on C<bar>, or are shorter than 5 chars.
 609  
 610  =item set_quote
 611  
 612    $d->set_quote('"');
 613  
 614  Sets C<tick> and C<unctrl> options to suitable values for printout with the
 615  given quote char.  Possible values are C<auto>, C<'> and C<">.
 616  
 617  =item set_unctrl
 618  
 619    $d->set_unctrl('unctrl');
 620  
 621  Sets C<unctrl> option with checking for an invalid argument.
 622  Possible values are C<unctrl> and C<quote>.
 623  
 624  =item compactDump
 625  
 626    $d->compactDump(1);
 627  
 628  Sets C<compactDump> option.  If the value is 1, sets to a reasonable
 629  big number.
 630  
 631  =item veryCompact
 632  
 633    $d->veryCompact(1);
 634  
 635  Sets C<compactDump> and C<veryCompact> options simultaneously.
 636  
 637  =item set
 638  
 639    $d->set(option1 => value1, option2 => value2);
 640  
 641  =item get
 642  
 643    @values = $d->get('option1', 'option2');
 644  
 645  =back
 646  
 647  =cut
 648  


Generated: Tue Mar 17 22:47:18 2015 Cross-referenced by PHPXref 0.7.1