| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
# -*- coding: utf-8 -*- |
|
2
|
|
|
|
|
|
|
# Copyright (C) 2011-2012, 2014 Rocky Bernstein <rocky@cpan.org> |
|
3
|
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
# Part of Devel::Trepan::CmdProcessor that loads up debugger commands from |
|
5
|
|
|
|
|
|
|
# builtin and user directories. |
|
6
|
|
|
|
|
|
|
# Sets @commands, @aliases, @macros |
|
7
|
12
|
|
|
12
|
|
82541
|
use rlib '../../..'; |
|
|
12
|
|
|
|
|
35
|
|
|
|
12
|
|
|
|
|
70
|
|
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
package Devel::Trepan::CmdProcessor; |
|
10
|
|
|
|
|
|
|
$Load_seen = 1; |
|
11
|
12
|
|
|
12
|
|
7212
|
use warnings; use strict; |
|
|
12
|
|
|
12
|
|
26
|
|
|
|
12
|
|
|
|
|
315
|
|
|
|
12
|
|
|
|
|
98
|
|
|
|
12
|
|
|
|
|
59
|
|
|
|
12
|
|
|
|
|
284
|
|
|
12
|
12
|
|
|
12
|
|
59
|
no warnings 'redefine'; |
|
|
12
|
|
|
|
|
25
|
|
|
|
12
|
|
|
|
|
379
|
|
|
13
|
|
|
|
|
|
|
|
|
14
|
12
|
|
|
12
|
|
60
|
use File::Spec; |
|
|
12
|
|
|
|
|
31
|
|
|
|
12
|
|
|
|
|
405
|
|
|
15
|
12
|
|
|
12
|
|
71
|
use File::Basename; |
|
|
12
|
|
|
|
|
21
|
|
|
|
12
|
|
|
|
|
812
|
|
|
16
|
12
|
|
|
12
|
|
88
|
use Cwd 'abs_path'; |
|
|
12
|
|
|
|
|
22
|
|
|
|
12
|
|
|
|
|
18223
|
|
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
=head2 load_cmds_initialize |
|
19
|
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
load_debugger_commands($self) -> undef |
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
Loads in our built-in commands. |
|
23
|
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
Called from Devel::Trepan::CmdProcessor->new in CmdProcessor.pm |
|
25
|
|
|
|
|
|
|
=cut |
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
sub load_cmds_initialize($) |
|
28
|
|
|
|
|
|
|
{ |
|
29
|
13
|
|
|
13
|
0
|
50
|
my $self = shift; |
|
30
|
13
|
|
|
|
|
59
|
$self->{commands} = {}; |
|
31
|
13
|
|
|
|
|
73
|
$self->{aliases} = {}; |
|
32
|
13
|
|
|
|
|
66
|
$self->{macros} = {}; |
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
my @cmd_dirs = ( |
|
35
|
|
|
|
|
|
|
File::Spec->catfile(dirname(__FILE__), 'Command'), |
|
36
|
13
|
|
|
|
|
1945
|
@{$self->{settings}{cmddir}} |
|
|
13
|
|
|
|
|
110
|
|
|
37
|
|
|
|
|
|
|
); |
|
38
|
13
|
|
|
|
|
93
|
for my $cmd_dir (@cmd_dirs) { |
|
39
|
13
|
50
|
|
|
|
561
|
$self->load_debugger_commands($cmd_dir) if -d $cmd_dir; |
|
40
|
|
|
|
|
|
|
} |
|
41
|
|
|
|
|
|
|
} |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
=head2 load_debugger_commands |
|
44
|
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
load_debugger_commands($self, $file_or_dir) -> @errors |
|
46
|
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
Loads in debugger commands by require'ing each Perl file in the |
|
48
|
|
|
|
|
|
|
'command' directory. Then a new instance of each class of the |
|
49
|
|
|
|
|
|
|
form Trepan::xxCommand is added to @commands and that array |
|
50
|
|
|
|
|
|
|
is returned. |
|
51
|
|
|
|
|
|
|
=cut |
|
52
|
|
|
|
|
|
|
sub load_debugger_commands($$) |
|
53
|
|
|
|
|
|
|
{ |
|
54
|
13
|
|
|
13
|
0
|
75
|
my ($self, $file_or_dir) = @_; |
|
55
|
13
|
|
|
|
|
50
|
my @errors = (); |
|
56
|
13
|
50
|
|
|
|
206
|
if ( -d $file_or_dir ) { |
|
|
|
0
|
|
|
|
|
|
|
57
|
13
|
|
|
|
|
1171
|
my $dir = abs_path($file_or_dir); |
|
58
|
|
|
|
|
|
|
# change $0 so it doesn't get in the way of __FILE__ eq $0 |
|
59
|
|
|
|
|
|
|
# old_dollar0 = $0 |
|
60
|
|
|
|
|
|
|
# $0 = '' |
|
61
|
13
|
|
|
|
|
7493
|
for my $pm (glob(File::Spec->catfile($dir, '*.pm'))) { |
|
62
|
494
|
|
|
|
|
1552
|
my $err = $self->load_debugger_command($pm); |
|
63
|
494
|
50
|
|
|
|
1584
|
push @errors, $err if $err; |
|
64
|
|
|
|
|
|
|
} |
|
65
|
|
|
|
|
|
|
# $0 = old_dollar0 |
|
66
|
|
|
|
|
|
|
} elsif (-r $file_or_dir) { |
|
67
|
0
|
|
|
|
|
0
|
my $err = $self->load_debugger_command($file_or_dir); |
|
68
|
0
|
0
|
|
|
|
0
|
push @errors, $err if $err; |
|
69
|
|
|
|
|
|
|
} |
|
70
|
13
|
|
|
|
|
155
|
return @errors; |
|
71
|
|
|
|
|
|
|
} |
|
72
|
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
=head2 load_debugger_command |
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
load_debugger_command($self, $command_file, [$force]) |
|
76
|
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
Loads a debugger command. Returns a string containing the error or '' if no error. |
|
78
|
|
|
|
|
|
|
=cut |
|
79
|
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
sub load_debugger_command($$;$) |
|
81
|
|
|
|
|
|
|
{ |
|
82
|
494
|
|
|
494
|
0
|
1298
|
my ($self, $command_file, $force) = @_; |
|
83
|
494
|
50
|
|
|
|
13965
|
return unless -r $command_file; |
|
84
|
494
|
|
|
|
|
2819
|
my $rc = ''; |
|
85
|
494
|
|
|
|
|
907
|
eval { $rc = do $command_file; }; |
|
|
494
|
|
|
|
|
202766
|
|
|
86
|
494
|
50
|
33
|
|
|
4092
|
if (!$rc or $rc eq 'Skip me!') { |
|
|
|
50
|
|
|
|
|
|
|
87
|
0
|
|
|
|
|
0
|
return 'skipped'; |
|
88
|
|
|
|
|
|
|
} elsif ($rc) { |
|
89
|
|
|
|
|
|
|
# Instantiate each Command class found by the above require(s). |
|
90
|
494
|
|
|
|
|
17778
|
my $name = basename($command_file, '.pm'); |
|
91
|
494
|
|
|
|
|
2480
|
return $self->setup_command($name); |
|
92
|
|
|
|
|
|
|
} else { |
|
93
|
0
|
|
|
|
|
0
|
my $errmsg = "Trouble reading ${command_file}: $@"; |
|
94
|
0
|
|
|
|
|
0
|
$self->errmsg($errmsg); |
|
95
|
0
|
|
|
|
|
0
|
return $errmsg; |
|
96
|
|
|
|
|
|
|
} |
|
97
|
|
|
|
|
|
|
} |
|
98
|
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
=head2 run_cmd |
|
100
|
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
run_cmd($self, $cmd_arry) |
|
102
|
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
Looks up cmd_array[0] in @commands and runs that. We do lots of |
|
104
|
|
|
|
|
|
|
validity testing on cmd_array. |
|
105
|
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
=cut |
|
107
|
|
|
|
|
|
|
sub run_cmd($$) |
|
108
|
|
|
|
|
|
|
{ |
|
109
|
3
|
|
|
3
|
0
|
2493
|
my ($self, $cmd_array) = @_; |
|
110
|
3
|
100
|
|
|
|
13
|
unless ('ARRAY' eq ref $cmd_array) { |
|
111
|
1
|
50
|
|
|
|
5
|
my $ref_msg = ref($cmd_array) ? ", got: " . ref($cmd_array): ''; |
|
112
|
1
|
|
|
|
|
7
|
$self->errmsg("run_cmd argument should be an Array reference$ref_msg"); |
|
113
|
1
|
|
|
|
|
19
|
return; |
|
114
|
|
|
|
|
|
|
} |
|
115
|
|
|
|
|
|
|
# if ($cmd_array.detect{|item| !item.is_a?(String)}) { |
|
116
|
|
|
|
|
|
|
# $self ->errmsg("run_cmd argument Array should only contain strings. " . |
|
117
|
|
|
|
|
|
|
# "Got #{cmd_array.inspect}"); |
|
118
|
|
|
|
|
|
|
# return; |
|
119
|
|
|
|
|
|
|
# } |
|
120
|
2
|
100
|
|
|
|
9
|
if (0 == scalar @$cmd_array) { |
|
121
|
1
|
|
|
|
|
14
|
$self->errmsg("run_cmd Array should have at least one item"); |
|
122
|
1
|
|
|
|
|
20
|
return; |
|
123
|
|
|
|
|
|
|
} |
|
124
|
1
|
|
|
|
|
4
|
my $cmd_name = $cmd_array->[0]; |
|
125
|
1
|
50
|
|
|
|
4
|
if (exists($self->{commands}{$cmd_name})) { |
|
126
|
1
|
|
|
|
|
8
|
$self->{commands}{$cmd_name}->run($cmd_array); |
|
127
|
|
|
|
|
|
|
} |
|
128
|
|
|
|
|
|
|
} |
|
129
|
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
# sub save_commands(opts) |
|
131
|
|
|
|
|
|
|
# { |
|
132
|
|
|
|
|
|
|
# save_filename = opts[:filename] || |
|
133
|
|
|
|
|
|
|
# File.join(Dir.tmpdir, Dir::Tmpname.make_tmpname(['trepanning-save', '.txt'], nil)) |
|
134
|
|
|
|
|
|
|
# begin |
|
135
|
|
|
|
|
|
|
# save_file = File.open(save_filename, 'w') |
|
136
|
|
|
|
|
|
|
# rescue => exc |
|
137
|
|
|
|
|
|
|
# errmsg("Can't open #{save_filename} for writing.") |
|
138
|
|
|
|
|
|
|
# errmsg("System reports: #{exc.inspect}") |
|
139
|
|
|
|
|
|
|
# return nil |
|
140
|
|
|
|
|
|
|
# } |
|
141
|
|
|
|
|
|
|
# save_file.print "#\n# Commands to restore trepanning environment\n#\n" |
|
142
|
|
|
|
|
|
|
# @commands.each do |cmd_name, cmd_obj| |
|
143
|
|
|
|
|
|
|
# cmd_obj.save_command if cmd_obj.respond_to?(:save_command) |
|
144
|
|
|
|
|
|
|
# next unless cmd_obj.is_a?(Trepan::SubcommandMgr) |
|
145
|
|
|
|
|
|
|
# cmd_obj.subcmds.subcmds.each do |subcmd_name, subcmd_obj| |
|
146
|
|
|
|
|
|
|
# save_file.print subcmd_obj.save_command if |
|
147
|
|
|
|
|
|
|
# subcmd_obj.respond_to?(:save_command) |
|
148
|
|
|
|
|
|
|
# next unless subcmd_obj.is_a?(Trepan::SubSubcommandMgr) |
|
149
|
|
|
|
|
|
|
# subcmd_obj.subcmds.subcmds.each do |subsubcmd_name, subsubcmd_obj| |
|
150
|
|
|
|
|
|
|
# save_file.print subsubcmd_obj.save_command if |
|
151
|
|
|
|
|
|
|
# subsubcmd_obj.respond_to?(:save_command) |
|
152
|
|
|
|
|
|
|
# } |
|
153
|
|
|
|
|
|
|
# } |
|
154
|
|
|
|
|
|
|
# } |
|
155
|
|
|
|
|
|
|
# save_file.print "!FileUtils.rm #{save_filename.inspect}" if |
|
156
|
|
|
|
|
|
|
# opts[:erase] |
|
157
|
|
|
|
|
|
|
# save_file.close |
|
158
|
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
# return save_filename |
|
160
|
|
|
|
|
|
|
# } |
|
161
|
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
=head2 setup_command |
|
163
|
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
setup_command($self, $name) |
|
165
|
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
Instantiate a Devel::Trepan::Command and extract info: the NAME, ALIASES |
|
167
|
|
|
|
|
|
|
and store the command in @commands. |
|
168
|
|
|
|
|
|
|
=cut |
|
169
|
|
|
|
|
|
|
sub setup_command($$) |
|
170
|
|
|
|
|
|
|
{ |
|
171
|
494
|
|
|
494
|
0
|
1232
|
my ($self, $name) = @_; |
|
172
|
494
|
|
|
|
|
781
|
my $cmd_obj; |
|
173
|
494
|
|
|
|
|
965
|
my $cmd_name = lc $name; |
|
174
|
494
|
|
|
|
|
1298
|
my $new_cmd = "\$cmd_obj=Devel::Trepan::CmdProcessor::Command::${name}" . |
|
175
|
|
|
|
|
|
|
"->new(\$self, \$cmd_name); 1"; |
|
176
|
494
|
50
|
|
|
|
39513
|
if (eval $new_cmd) { |
|
177
|
|
|
|
|
|
|
# Add to list of commands and aliases. |
|
178
|
494
|
50
|
|
|
|
4358
|
if ($cmd_obj->{aliases}) { |
|
179
|
494
|
|
|
|
|
918
|
for my $a (@{$cmd_obj->{aliases}}) { |
|
|
494
|
|
|
|
|
1514
|
|
|
180
|
559
|
|
|
|
|
2388
|
$self->{aliases}{$a} = $cmd_name; |
|
181
|
|
|
|
|
|
|
} |
|
182
|
|
|
|
|
|
|
} |
|
183
|
494
|
|
|
|
|
2425
|
$self->{commands}{$cmd_name} = $cmd_obj; |
|
184
|
494
|
|
|
|
|
3972
|
return ''; |
|
185
|
|
|
|
|
|
|
} else { |
|
186
|
0
|
|
|
|
|
|
$self->errmsg("Error instantiating $name"); |
|
187
|
0
|
|
|
|
|
|
$self->errmsg($@); |
|
188
|
0
|
|
|
|
|
|
return $@; |
|
189
|
|
|
|
|
|
|
} |
|
190
|
|
|
|
|
|
|
} |
|
191
|
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
unless (caller) { |
|
193
|
|
|
|
|
|
|
require Devel::Trepan::CmdProcessor; |
|
194
|
|
|
|
|
|
|
my $cmdproc = Devel::Trepan::CmdProcessor->new; |
|
195
|
|
|
|
|
|
|
require Array::Columnize; |
|
196
|
|
|
|
|
|
|
my @cmds = sort keys(%{$cmdproc->{commands}}); |
|
197
|
|
|
|
|
|
|
print Array::Columnize::columnize(\@cmds); |
|
198
|
|
|
|
|
|
|
my $sep = '=' x 20 . "\n"; |
|
199
|
|
|
|
|
|
|
print $sep; |
|
200
|
|
|
|
|
|
|
my @aliases = sort keys(%{$cmdproc->{aliases}}); |
|
201
|
|
|
|
|
|
|
print Array::Columnize::columnize(\@aliases); |
|
202
|
|
|
|
|
|
|
print $sep; |
|
203
|
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
$cmdproc->run_cmd('foo'); # Invalid - not an Array |
|
205
|
|
|
|
|
|
|
$cmdproc->run_cmd([]); # Invalid - empty Array |
|
206
|
|
|
|
|
|
|
$cmdproc->run_cmd(['help', '*']); |
|
207
|
|
|
|
|
|
|
# $cmdproc->run_cmd(['list', 5]); # Invalid - nonstring arg |
|
208
|
|
|
|
|
|
|
} |
|
209
|
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
1; |