File Coverage

lib/Devel/Trepan/CmdProcessor/Command/Break.pm
Criterion Covered Total %
statement 110 214 51.4
branch 11 68 16.1
condition 2 12 16.6
subroutine 29 34 85.2
pod 0 6 0.0
total 152 334 45.5


line stmt bran cond sub pod time code
1             # -*- coding: utf-8 -*-
2             # Copyright (C) 2011-2014 Rocky Bernstein <rocky@cpan.org>
3 12     12   17381 use warnings; no warnings 'redefine';
  12     12   35  
  12     2   459  
  12     2   74  
  12         32  
  12         405  
  2         14  
  2         5  
  2         52  
  2         10  
  2         5  
  2         51  
4 12     12   115 use rlib '../../../..';
  12     2   218  
  12         78  
  2         10  
  2         4  
  2         9  
5              
6 12     12   8229 use Devel::Trepan::DB::Sub;
  12     2   37  
  12         486  
  2         598  
  2         5  
  2         71  
7             # require_relative '../../app/condition'
8              
9             package Devel::Trepan::CmdProcessor::Command::Break;
10 12     12   826 use Devel::Trepan::DB::LineCache;
  12     2   34  
  12         2885  
  2         10  
  2         4  
  2         335  
11 12     12   102 use English qw( -no_match_vars );
  12     2   29  
  12         89  
  2         17  
  2         6  
  2         17  
12 12     12   5154 use if !@ISA, Devel::Trepan::CmdProcessor::Command;
  12     2   44  
  12         99  
  2         558  
  2         6  
  2         13  
13             unless (@ISA) {
14 12     12   85 eval <<'EOE';
  12     12   264  
  12     12   719  
  12     12   79  
  12     12   32  
  12     12   589  
  12         77  
  12         37  
  12         511  
  12         76  
  12         35  
  12         585  
  12         201  
  12         60  
  12         594  
  12         77  
  12         27  
  12         488  
15             use constant ALIASES => qw(b);
16             use constant CATEGORY => 'breakpoints';
17             use constant SHORT_HELP => 'Set a breakpoint';
18             use constant MIN_ARGS => 0; # Need at least this many
19             use constant MAX_ARGS => undef; # Need at most this many - undef -> unlimited.
20             use constant NEED_STACK => 0;
21             EOE
22             }
23              
24 12     12   2110 use strict; use vars qw(@ISA); @ISA = @CMD_ISA;
  12     12   34  
  12     2   284  
  12     2   64  
  12         31  
  12         590  
  2         120  
  2         4  
  2         37  
  2         7  
  2         3  
  2         92  
25 12     12   75 use vars @CMD_VARS; # Value inherited from parent
  12     2   30  
  12         10168  
  2         11  
  2         4  
  2         1579  
26              
27             our $NAME = set_name();
28             =head2 Synopsis:
29              
30             =cut
31             our $HELP = <<'HELP';
32             =pod
33              
34             B<break> [I<location>] [B<if> I<condition>]
35              
36             Set a breakpoint. If I<location> is given use the current stopping
37             point. An optional condition may be given.
38              
39             =head2 Examples:
40              
41             break # set a breakpoint on the current line
42             break gcd # set a breakpoint in function gcd
43             break gcd if $a == 1 # set a breakpoint in function gcd with
44             # condition $a == 1
45             break 10 # set breakpoint on line 10
46              
47             When a breakpoint is hit the event icon is C<xx>.
48              
49             =head2 See also:
50              
51             C<help breakpoints>, L<C<info
52             breakpoints>|Devel::Trepan::CmdProcessor::Command::Info::Breakpoints>,
53             and L<C<help syntax location>|Devel::Trepan::CmdProcessor::Command::Help::location>.
54              
55             =cut
56             HELP
57              
58             # FIXME: Should we include all files?
59             # Combine with LIST completion.
60             sub complete($$)
61             {
62 0     0 0 0 my ($self, $prefix) = @_;
  0     0 0 0  
63 0         0 my $filename = $self->{proc}->filename;
  0         0  
64 0         0 my @completions = sort(('.', file_list, DB::subs,
  0         0  
65             trace_line_numbers($filename)));
66 0         0 Devel::Trepan::Complete::complete_token(\@completions, $prefix);
  0         0  
67             }
68              
69             # include Trepan::Condition
70              
71             # This method runs the command
72             sub run($$) {
73 0     0 0 0 my ($self, $args) = @_;
  3     3 0 1817  
74 0         0 my @args = @$args;
  3         8  
75 0         0 shift @args;
  3         7  
76 0         0 my $proc = $self->{proc};
  3         12  
77 0         0 my $bp;
  3         6  
78 0         0 my $arg_count = scalar @args;
  3         6  
79 0 0       0 if ($arg_count == 0) {
  3 100       8  
80 0         0 $bp = $self->{dbgr}->set_break($DB::filename, $DB::lineno);
  1         5  
81             } else {
82 0         0 my ($filename, $line_or_fn, $condition);
  2         5  
83 0 0       0 if ($arg_count > 2) {
  2 50       6  
84 0 0       0 if ($args[0] eq 'if') {
  0 0       0  
85 0         0 $line_or_fn = $DB::lineno;
  0         0  
86 0         0 $filename = $DB::filename;
  0         0  
87 0         0 unshift @args, $line_or_fn;
  0         0  
88             } else {
89 0         0 $filename = $args[0];
  0         0  
90 0 0       0 if ($args[1] =~ /\d+/) {
  0 0       0  
    0          
    0          
91 0         0 $line_or_fn = $args[1];
  0         0  
92 0         0 shift @args;
  0         0  
93             } elsif ($args[1] eq 'if') {
94 0         0 $line_or_fn = $args[0];
  0         0  
95             } else {
96 0         0 $line_or_fn = $args[0];
  0         0  
97             }
98             }
99             } else {
100             # $arg_count <= 2.
101 0         0 $line_or_fn = $args[0];
  2         4  
102 0 0       0 if ($line_or_fn =~ /^\d+/) {
  2 100       10  
103 0         0 $filename = $DB::filename;
  1         4  
104             } else {
105             # FIXME: create a subroutine and combine with Deparse.
106 0         0 my @matches = $self->{dbgr}->subs($args[0]);
  1         5  
107 0 0       0 if (scalar(@matches) == 1) {
  1 50       8  
108 0         0 $filename = $matches[0][0];
  1         3  
109             } else {
110 0         0 $filename = $args[0];
  0         0  
111 0         0 my $canonic_name = map_file($filename);
  0         0  
112 0 0       0 if (is_cached($canonic_name)) {
  0 0       0  
113 0         0 $filename = $canonic_name;
  0         0  
114             }
115             }
116             }
117 0 0 0     0 if ($arg_count == 2 && $args[1] =~ /\d+/) {
  2 100 66     14  
118 0         0 $line_or_fn = $args[1];
  1         3  
119 0         0 shift @args;
  1         2  
120             }
121             }
122 0         0 shift @args;
  2         4  
123 0 0       0 if (scalar @args) {
  2 50       9  
124 0 0       0 if ($args[0] eq 'if') {
  0 0       0  
125 0         0 shift @args;
  0         0  
126 0         0 $condition = join(' ', @args);
  0         0  
127             } else {
128 0         0 $proc->errmsg("Expecting 'if' to start breakpoint condition;" .
  0         0  
129             " got ${args[0]}");
130             }
131             }
132 0         0 my $msg = $self->{dbgr}->break_invalid(\$filename, $line_or_fn);
  2         8  
133 0         0 my $force = 0;
  2         7  
134 0 0       0 if ($msg) {
  2 50       6  
135 0 0       0 if ($msg =~ /not known to be a trace line/) {
  0 0       0  
136 0         0 $proc->errmsg($msg);
  0         0  
137 0         0 $proc->msg("Use 'info file $filename brkpts' to see breakpoints I know about");
  0         0  
138 0         0 $force = $self->{proc}->confirm('Set breakpoint anyway?', 0);
  0         0  
139 0 0       0 return unless $force;
  0 0       0  
140             }
141             }
142 0         0 $bp = $self->{dbgr}->set_break($filename, $line_or_fn,
  2         8  
143             $condition, undef, undef, undef, $force);
144             }
145 0 0       0 if (defined($bp)) {
  3 50       24  
146 0 0       0 my $prefix = $bp->type eq 'tbrkpt' ?
  0 0          
147             'Temporary breakpoint' : 'Breakpoint' ;
148 0         0 my $id = $bp->id;
  0            
149 0         0 my $filename = $proc->canonic_file($bp->filename);
  0            
150 0         0 my $line_num = $bp->line_num;
  0            
151 0         0 $proc->{brkpts}->add($bp);
  0            
152 0         0 $proc->msg("$prefix $id set in $filename at line $line_num");
  0            
153             # Warn if we are setting a breakpoint on a line that starts
154             # "use.."
155 0         0 my $text = getline($bp->filename, $line_num, {output => 'plain'});
  0            
156 0 0 0     0 if (defined($text) && $text =~ /^\s*use\s+/) {
  0 0 0        
157 0         0 $proc->msg("Warning: 'use' statements get evaluated at compile time... You may have already passed this statement.");
  0            
158             }
159             }
160             }
161              
162             unless (caller) {
163             # FIXME: DRY this code by putting in common location.
164             require Devel::Trepan::DB;
165             require Devel::Trepan::Core;
166             my $db = Devel::Trepan::Core->new;
167             my $intf = Devel::Trepan::Interface::User->new(undef, undef,
168             {readline => 0});
169             my $proc = Devel::Trepan::CmdProcessor->new([$intf], $db);
170             $proc->{stack_size} = 0;
171             my $cmd = __PACKAGE__->new($proc);
172              
173             eval {
174             sub db_setup() {
175 12     12   108 no warnings 'once';
  12     2   45  
  12         1647  
  2         14  
  2         4  
  2         214  
176 0     0 0   $DB::caller = [caller];
  0     0 0    
177             ($DB::package, $DB::filename, $DB::lineno, $DB::subroutine)
178 0           = @{$DB::caller};
  0            
  0            
  0            
179             }
180             };
181             db_setup();
182              
183             $cmd->run([$NAME]);
184             # $cmd->run([$NAME, "/usr/share/perl/5.14.2/File/Basename.pm", "3"]);
185             }
186              
187             1;