File Coverage

lib/Devel/Trepan/CmdProcessor/Frame.pm
Criterion Covered Total %
statement 27 105 25.7
branch 0 54 0.0
condition 0 13 0.0
subroutine 9 13 69.2
pod 0 4 0.0
total 36 189 19.0


line stmt bran cond sub pod time code
1             # -*- coding: utf-8 -*-
2             # Copyright (C) 2011-2012, 2014-2015 Rocky Bernstein <rocky@cpan.org>
3 12     12   82 use strict; use warnings;
  12     12   29  
  12         599  
  12         60  
  12         22  
  12         360  
4 12     12   63 use rlib '../../..';
  12         112  
  12         63  
5 12     12   4205 use Devel::Trepan::DB::LineCache; # for map_file and getline
  12         25  
  12         2308  
6 12     12   82 use Devel::Trepan::Complete;
  12         34  
  12         922  
7              
8             package Devel::Trepan::CmdProcessor;
9 12     12   75 use English qw( -no_match_vars );
  12         23  
  12         104  
10              
11 12     12   6416 my $have_deparse = eval q(use B::DeparseTree::Fragment; use Devel::Trepan::Deparse; 1);
  12     12   900206  
  12         1018  
  12         6119  
  12         5052  
  12         464  
12              
13             sub frame_complete($$;$)
14             {
15 0     0 0   my ($self, $prefix, $direction) = @_;
16 0 0         $direction = 1 unless defined $direction;
17 0           my ($low, $high) = $self->frame_low_high($direction);
18 0           my @ary = ($low..$high);
19 0           Devel::Trepan::Complete::complete_token(\@ary, $prefix);
20             }
21              
22             sub print_stack_entry
23             {
24 0     0 0   my ($self, $frame, $i, $prefix, $opts) = @_;
25 0 0         $opts->{maxstack} = 1e9 unless defined $opts->{maxstack};
26             # Set the separator so arrays print nice.
27 0           local $LIST_SEPARATOR = ', ';
28              
29             # Get the file name.
30 0           my $canonic_file = $self->canonic_file($frame->{file});
31 0 0         $canonic_file = '??' unless defined $canonic_file;
32              
33             # Put in a filename header if short is off.
34 0 0         my $file = ($canonic_file eq '-e') ? $canonic_file : "file `$canonic_file'" unless $opts->{short};
    0          
35              
36 0           my $not_last_frame = $i != ($self->{stack_size}-1);
37 0           my $s = '';
38             my $args =
39             defined $frame->{args}
40 0 0         ? "(@{ $frame->{args} })"
  0            
41             : '';
42 0 0         if ($not_last_frame) {
43             # Grab and stringify the arguments if they are there.
44              
45             # Shorten them up if $opts->{maxwidth} says they're too long.
46             $args = substr($args, 0, $opts->{maxwidth}-3) . '...'
47 0 0         if length($args) > $opts->{maxwidth};
48              
49             # Get the actual sub's name, and shorten to $maxwidth's requirement.
50 0 0         if (exists($frame->{fn})) {
51 0           $s = $frame->{fn};
52             $s = substr($s, 0, $opts->{maxwidth}-3) . '...'
53 0 0         if length($s) > $opts->{maxwidth};
54             }
55             }
56              
57             # Short report uses trimmed file and sub names.
58 0           my $want_array;
59 0 0         if (exists($frame->{wantarray})) {
60 0           $want_array = "$frame->{wantarray} = ";
61             } else {
62 0           $not_last_frame = 0;
63 0           $want_array = '' ;
64             }
65              
66 0   0       my $lineno = $frame->{line} || '??';
67 0 0 0       my $addr = $opts->{displayop} && $frame->{addr} ? sprintf("0x%x ", $frame->{addr}) : '';
68 0 0         if ($opts->{short}) {
69 0           my $fn = $s; # @_ >= 4 ? $_[3] : $s;
70 0           my $msg = sprintf("%s%s%s%s from %s:%d",
71             $want_array, $addr, $fn, $args, $file, $lineno);
72 0           $self->msg($msg);
73             } else {
74             # Non-short report includes full names.
75             # Lose the DB::DB hook call if frame is 0.
76 0 0         my $call_str = $not_last_frame ? "$addr$want_array$s$args in " : $addr;
77 0           my $prefix_call = "$prefix$call_str";
78 0           my $file_line = $file . " at line $lineno";
79              
80 0 0         if (length($prefix_call) + length($file_line) <= $opts->{maxwidth}) {
81 0           $self->msg($prefix_call . $file_line);
82             } else {
83 0           $self->msg($prefix_call);
84 0           $self->msg("\t" . $file_line);
85             }
86             }
87 0 0         if ($opts->{source}) {
88 0           my $line = getline($canonic_file, $lineno, $opts);
89 0 0         $self->msg($line) if $line;
90             }
91              
92              
93 0 0 0       if ($opts->{deparse} && $have_deparse && $addr) {
      0        
94 0 0         my $funcname = $not_last_frame ? $frame->{fn} : "DB::DB";
95 0           my $int_addr = $addr;
96 0           $int_addr =~ s/\s+$//g;
97 12     12   11377 no warnings 'portable';
  12         32  
  12         6961  
98 0           $int_addr = hex($int_addr);
99 0           my ($op_info) = deparse_offset($funcname, $int_addr);
100 0 0         if ($op_info) {
101 0 0         if ($i != 0) {
102             # All frames except the current frame we need to
103             # back up the op_info;
104 0           $op_info = get_prev_addr_info($op_info);
105             }
106 0           my $extract_texts = extract_node_info($op_info);
107 0 0         if ($extract_texts) {
108 0           pmsg($self, join("\n", @$extract_texts))
109             } else {
110 0           pmsg($self, $op_info->{text});
111             }
112             }
113             }
114              
115             }
116              
117             sub print_stack_trace_from_to($$$$$)
118             {
119 0     0 0   my ($self, $from, $to, $frames, $opts) = @_;
120 0           for (my $i=$from; $i <= $to; $i++) {
121 0 0         my $prefix = ($i == $opts->{current_pos}) ? '-->' : ' ';
122 0           $prefix .= sprintf ' #%d ', $i;
123 0           $self->print_stack_entry($frames->[$i], $i, $prefix, $opts);
124             }
125             }
126              
127             # Print `count' frame entries
128             sub print_stack_trace($$$)
129             {
130 0     0 0   my ($self, $frames, $opts)=@_;
131 0   0       $opts ||= {maxstack=>1e9, count=>1e9};
132 0           my $start = 0;
133 0           my $n = scalar @{$frames};
  0            
134 0           my $halfstack = $opts->{maxstack} / 2;
135              
136 0           my $count = $opts->{count};
137 0 0         if ($count < 0) {
    0          
138 0           $start = $n + $count;
139 0           $count = $n;
140             } elsif ($count < $n) {
141 0           $n = $count;
142 0           $halfstack = $n;
143             }
144              
145             # $opts = DEFAULT_STACK_TRACE_SETTINGS.merge(opts);
146 0 0         $n = $count if $opts->{count} < $n;
147 0 0         if ($n > ($halfstack * 2)) {
148 0           $self->print_stack_trace_from_to($start, $halfstack-1, $frames, $opts);
149 0           my $msg = sprintf "... %d levels ...", ($n - $halfstack*2);
150 0           $self->msg($msg);
151 0           $self->print_stack_trace_from_to($n - $halfstack, $n-1, $frames, $opts);
152             } else {
153 0           $self->print_stack_trace_from_to($start, $n-1, $frames, $opts);
154             }
155             }
156              
157             1;