home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / share / perl / 5.8.8 / Carp / Heavy.pm
Encoding:
Perl POD Document  |  2006-07-07  |  5.6 KB  |  234 lines

  1. # Carp::Heavy uses some variables in common with Carp.
  2. package Carp;
  3.  
  4. # use strict; # not yet
  5.  
  6. # On one line so MakeMaker will see it.
  7. use Carp;  our $VERSION = $Carp::VERSION;
  8.  
  9. our ($CarpLevel, $MaxArgNums, $MaxEvalLen, $MaxArgLen, $Verbose);
  10.  
  11. sub caller_info {
  12.   my $i = shift(@_) + 1;
  13.   package DB;
  14.   my %call_info;
  15.   @call_info{
  16.     qw(pack file line sub has_args wantarray evaltext is_require)
  17.   } = caller($i);
  18.   
  19.   unless (defined $call_info{pack}) {
  20.     return ();
  21.   }
  22.  
  23.   my $sub_name = Carp::get_subname(\%call_info);
  24.   if ($call_info{has_args}) {
  25.     my @args = map {Carp::format_arg($_)} @DB::args;
  26.     if ($MaxArgNums and @args > $MaxArgNums) { # More than we want to show?
  27.       $#args = $MaxArgNums;
  28.       push @args, '...';
  29.     }
  30.     # Push the args onto the subroutine
  31.     $sub_name .= '(' . join (', ', @args) . ')';
  32.   }
  33.   $call_info{sub_name} = $sub_name;
  34.   return wantarray() ? %call_info : \%call_info;
  35. }
  36.  
  37. # Transform an argument to a function into a string.
  38. sub format_arg {
  39.   my $arg = shift;
  40.   if (ref($arg)) {
  41.       $arg = defined($overload::VERSION) ? overload::StrVal($arg) : "$arg";
  42.   }elsif (not defined($arg)) {
  43.     $arg = 'undef';
  44.   }
  45.   $arg =~ s/'/\\'/g;
  46.   $arg = str_len_trim($arg, $MaxArgLen);
  47.   
  48.   # Quote it?
  49.   $arg = "'$arg'" unless $arg =~ /^-?[\d.]+\z/;
  50.  
  51.   # The following handling of "control chars" is direct from
  52.   # the original code - it is broken on Unicode though.
  53.   # Suggestions?
  54.   utf8::is_utf8($arg)
  55.     or $arg =~ s/([[:cntrl:]]|[[:^ascii:]])/sprintf("\\x{%x}",ord($1))/eg;
  56.   return $arg;
  57. }
  58.  
  59. # Takes an inheritance cache and a package and returns
  60. # an anon hash of known inheritances and anon array of
  61. # inheritances which consequences have not been figured
  62. # for.
  63. sub get_status {
  64.     my $cache = shift;
  65.     my $pkg = shift;
  66.     $cache->{$pkg} ||= [{$pkg => $pkg}, [trusts_directly($pkg)]];
  67.     return @{$cache->{$pkg}};
  68. }
  69.  
  70. # Takes the info from caller() and figures out the name of
  71. # the sub/require/eval
  72. sub get_subname {
  73.   my $info = shift;
  74.   if (defined($info->{evaltext})) {
  75.     my $eval = $info->{evaltext};
  76.     if ($info->{is_require}) {
  77.       return "require $eval";
  78.     }
  79.     else {
  80.       $eval =~ s/([\\\'])/\\$1/g;
  81.       return "eval '" . str_len_trim($eval, $MaxEvalLen) . "'";
  82.     }
  83.   }
  84.  
  85.   return ($info->{sub} eq '(eval)') ? 'eval {...}' : $info->{sub};
  86. }
  87.  
  88. # Figures out what call (from the point of view of the caller)
  89. # the long error backtrace should start at.
  90. sub long_error_loc {
  91.   my $i;
  92.   my $lvl = $CarpLevel;
  93.   {
  94.     my $pkg = caller(++$i);
  95.     unless(defined($pkg)) {
  96.       # This *shouldn't* happen.
  97.       if (%Internal) {
  98.         local %Internal;
  99.         $i = long_error_loc();
  100.         last;
  101.       }
  102.       else {
  103.         # OK, now I am irritated.
  104.         return 2;
  105.       }
  106.     }
  107.     redo if $CarpInternal{$pkg};
  108.     redo unless 0 > --$lvl;
  109.     redo if $Internal{$pkg};
  110.   }
  111.   return $i - 1;
  112. }
  113.  
  114. sub longmess_heavy {
  115.   return @_ if ref($_[0]); # don't break references as exceptions
  116.   my $i = long_error_loc();
  117.   return ret_backtrace($i, @_);
  118. }
  119.  
  120. # Returns a full stack backtrace starting from where it is
  121. # told.
  122. sub ret_backtrace {
  123.   my ($i, @error) = @_;
  124.   my $mess;
  125.   my $err = join '', @error;
  126.   $i++;
  127.  
  128.   my $tid_msg = '';
  129.   if (defined &Thread::tid) {
  130.     my $tid = Thread->self->tid;
  131.     $tid_msg = " thread $tid" if $tid;
  132.   }
  133.  
  134.   my %i = caller_info($i);
  135.   $mess = "$err at $i{file} line $i{line}$tid_msg\n";
  136.  
  137.   while (my %i = caller_info(++$i)) {
  138.       $mess .= "\t$i{sub_name} called at $i{file} line $i{line}$tid_msg\n";
  139.   }
  140.   
  141.   return $mess;
  142. }
  143.  
  144. sub ret_summary {
  145.   my ($i, @error) = @_;
  146.   my $err = join '', @error;
  147.   $i++;
  148.  
  149.   my $tid_msg = '';
  150.   if (defined &Thread::tid) {
  151.     my $tid = Thread->self->tid;
  152.     $tid_msg = " thread $tid" if $tid;
  153.   }
  154.  
  155.   my %i = caller_info($i);
  156.   return "$err at $i{file} line $i{line}$tid_msg\n";
  157. }
  158.  
  159. sub short_error_loc {
  160.   my $cache;
  161.   my $i = 1;
  162.   my $lvl = $CarpLevel;
  163.   {
  164.     my $called = caller($i++);
  165.     my $caller = caller($i);
  166.     return 0 unless defined($caller); # What happened?
  167.     redo if $Internal{$caller};
  168.     redo if $CarpInternal{$called};
  169.     redo if trusts($called, $caller, $cache);
  170.     redo if trusts($caller, $called, $cache);
  171.     redo unless 0 > --$lvl;
  172.   }
  173.   return $i - 1;
  174. }
  175.  
  176. sub shortmess_heavy {
  177.   return longmess_heavy(@_) if $Verbose;
  178.   return @_ if ref($_[0]); # don't break references as exceptions
  179.   my $i = short_error_loc();
  180.   if ($i) {
  181.     ret_summary($i, @_);
  182.   }
  183.   else {
  184.     longmess_heavy(@_);
  185.   }
  186. }
  187.  
  188. # If a string is too long, trims it with ...
  189. sub str_len_trim {
  190.   my $str = shift;
  191.   my $max = shift || 0;
  192.   if (2 < $max and $max < length($str)) {
  193.     substr($str, $max - 3) = '...';
  194.   }
  195.   return $str;
  196. }
  197.  
  198. # Takes two packages and an optional cache.  Says whether the
  199. # first inherits from the second.
  200. #
  201. # Recursive versions of this have to work to avoid certain
  202. # possible endless loops, and when following long chains of
  203. # inheritance are less efficient.
  204. sub trusts {
  205.     my $child = shift;
  206.     my $parent = shift;
  207.     my $cache = shift || {};
  208.     my ($known, $partial) = get_status($cache, $child);
  209.     # Figure out consequences until we have an answer
  210.     while (@$partial and not exists $known->{$parent}) {
  211.         my $anc = shift @$partial;
  212.         next if exists $known->{$anc};
  213.         $known->{$anc}++;
  214.         my ($anc_knows, $anc_partial) = get_status($cache, $anc);
  215.         my @found = keys %$anc_knows;
  216.         @$known{@found} = ();
  217.         push @$partial, @$anc_partial;
  218.     }
  219.     return exists $known->{$parent};
  220. }
  221.  
  222. # Takes a package and gives a list of those trusted directly
  223. sub trusts_directly {
  224.     my $class = shift;
  225.     no strict 'refs';
  226.     no warnings 'once'; 
  227.     return @{"$class\::CARP_NOT"}
  228.       ? @{"$class\::CARP_NOT"}
  229.       : @{"$class\::ISA"};
  230. }
  231.  
  232. 1;
  233.  
  234.