line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Getopt::App; |
2
|
7
|
|
|
7
|
|
1600053
|
use feature qw(:5.16); |
|
7
|
|
|
|
|
50
|
|
|
7
|
|
|
|
|
1124
|
|
3
|
7
|
|
|
7
|
|
56
|
use strict; |
|
7
|
|
|
|
|
13
|
|
|
7
|
|
|
|
|
139
|
|
4
|
7
|
|
|
7
|
|
54
|
use warnings; |
|
7
|
|
|
|
|
14
|
|
|
7
|
|
|
|
|
212
|
|
5
|
7
|
|
|
7
|
|
44
|
use utf8; |
|
7
|
|
|
|
|
18
|
|
|
7
|
|
|
|
|
46
|
|
6
|
|
|
|
|
|
|
|
7
|
7
|
|
|
7
|
|
237
|
use Carp qw(croak); |
|
7
|
|
|
|
|
11
|
|
|
7
|
|
|
|
|
323
|
|
8
|
7
|
|
|
7
|
|
5831
|
use Getopt::Long (); |
|
7
|
|
|
|
|
74809
|
|
|
7
|
|
|
|
|
266
|
|
9
|
7
|
|
|
7
|
|
57
|
use List::Util qw(first); |
|
7
|
|
|
|
|
21
|
|
|
7
|
|
|
|
|
10128
|
|
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
our $VERSION = '0.11'; |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
our ($OPT_COMMENT_RE, $OPTIONS, $SUBCOMMAND, $SUBCOMMANDS, %APPS) = (qr{\s+\#\s+}); |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
our $call_maybe = sub { |
16
|
|
|
|
|
|
|
my ($app, $m) = (shift, shift); |
17
|
|
|
|
|
|
|
local $Getopt::App::APP_CLASS; |
18
|
|
|
|
|
|
|
$m = $app->can($m) || __PACKAGE__->can("_$m"); |
19
|
|
|
|
|
|
|
return $m ? $app->$m(@_) : undef; |
20
|
|
|
|
|
|
|
}; |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
sub bundle { |
23
|
1
|
|
|
1
|
1
|
7552
|
my ($class, $script, $OUT) = (@_, \*STDOUT); |
24
|
1
|
|
|
|
|
4
|
my ($package, @script); |
25
|
|
|
|
|
|
|
|
26
|
1
|
50
|
|
|
|
50
|
open my $SCRIPT, '<', $script or croak "Can't read $script: $!"; |
27
|
1
|
|
|
|
|
41
|
while (my $line = readline $SCRIPT) { |
28
|
2
|
100
|
|
|
|
18
|
if ($line =~ m!^\s*package\s+\S+\s*;!) { # look for app class name |
|
|
50
|
|
|
|
|
|
29
|
1
|
|
|
|
|
15
|
$package .= $line; |
30
|
1
|
|
|
|
|
4
|
last; |
31
|
|
|
|
|
|
|
} |
32
|
|
|
|
|
|
|
elsif ($. == 1) { # look for hashbang |
33
|
1
|
50
|
|
|
|
8
|
$line =~ m/^#!/ ? print {$OUT} $line : do { print {$OUT} "#!$^X\n"; push @script, $line }; |
|
1
|
|
|
|
|
7
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
34
|
|
|
|
|
|
|
} |
35
|
|
|
|
|
|
|
else { |
36
|
0
|
|
|
|
|
0
|
push @script, $line; |
37
|
0
|
0
|
|
|
|
0
|
last if $line =~ m!^[^#]+;!; |
38
|
|
|
|
|
|
|
} |
39
|
|
|
|
|
|
|
} |
40
|
|
|
|
|
|
|
|
41
|
1
|
|
|
|
|
8
|
my $out_line = ''; |
42
|
1
|
50
|
|
|
|
56
|
open my $SELF, '<', __FILE__ or croak "Can't read Getopt::App: $!"; |
43
|
1
|
|
|
|
|
70
|
while (my $line = readline $SELF) { |
44
|
267
|
100
|
|
|
|
1504
|
next if $line =~ m!(?:\bVERSION\s|^\s*$)!; # TODO: Should version get skipped? |
45
|
220
|
100
|
|
|
|
420
|
next if $line =~ m!^sub bundle\s\{! .. $line =~ m!^}$!; # skip bundle() |
46
|
177
|
100
|
|
|
|
280
|
last if $line =~ m!^1;\s*$!; # do not include POD |
47
|
|
|
|
|
|
|
|
48
|
176
|
|
|
|
|
214
|
chomp $line; |
49
|
176
|
100
|
|
|
|
331
|
if ($line =~ m!^sub\s!) { |
|
|
100
|
|
|
|
|
|
50
|
15
|
100
|
|
|
|
35
|
print {$OUT} $out_line, "\n" if $out_line; |
|
1
|
|
|
|
|
5
|
|
51
|
15
|
100
|
|
|
|
46
|
$line =~ m!\}$! ? print {$OUT} $line, "\n" : ($out_line = $line); |
|
2
|
|
|
|
|
9
|
|
52
|
|
|
|
|
|
|
} |
53
|
|
|
|
|
|
|
elsif ($line =~ m!^}$!) { |
54
|
13
|
|
|
|
|
23
|
print {$OUT} $out_line, $line, "\n"; |
|
13
|
|
|
|
|
30
|
|
55
|
13
|
|
|
|
|
37
|
$out_line = ''; |
56
|
|
|
|
|
|
|
} |
57
|
|
|
|
|
|
|
else { |
58
|
148
|
|
|
|
|
385
|
$line =~ s!^[ ]{2,}!!; # remove leading white space |
59
|
148
|
|
|
|
|
230
|
$line =~ s!\#\s.*!!; # remove comments |
60
|
148
|
|
|
|
|
392
|
$out_line .= $line; |
61
|
|
|
|
|
|
|
} |
62
|
|
|
|
|
|
|
} |
63
|
|
|
|
|
|
|
|
64
|
1
|
|
|
|
|
12
|
print {$OUT} qq(BEGIN{\$INC{'Getopt/App.pm'}='BUNDLED'}\n); |
|
1
|
|
|
|
|
6
|
|
65
|
1
|
|
50
|
|
|
3
|
print {$OUT} +($package || "package main\n"); |
|
1
|
|
|
|
|
4
|
|
66
|
1
|
|
|
|
|
4
|
print {$OUT} @script; |
|
1
|
|
|
|
|
14
|
|
67
|
1
|
|
|
|
|
6
|
print {$OUT} $_ while readline $SCRIPT; |
|
2
|
|
|
|
|
39
|
|
68
|
|
|
|
|
|
|
} |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
sub capture { |
71
|
22
|
|
|
22
|
1
|
47510
|
my ($app, $argv) = @_; |
72
|
22
|
|
|
|
|
61
|
my ($exit_value, $stderr, $stdout) = (-1, '', ''); |
73
|
|
|
|
|
|
|
|
74
|
22
|
|
|
|
|
56
|
local *STDERR; |
75
|
22
|
|
|
|
|
42
|
local *STDOUT; |
76
|
5
|
|
|
5
|
|
34
|
open STDERR, '>', \$stderr; |
|
5
|
|
|
|
|
10
|
|
|
5
|
|
|
|
|
37
|
|
|
22
|
|
|
|
|
359
|
|
77
|
22
|
|
|
|
|
4460
|
open STDOUT, '>', \$stdout; |
78
|
22
|
|
|
|
|
77
|
($!, $@) = (0, ''); |
79
|
|
|
|
|
|
|
eval { |
80
|
22
|
|
100
|
|
|
102
|
$exit_value = $app->($argv || [@ARGV]); |
81
|
19
|
|
|
|
|
69
|
1; |
82
|
22
|
100
|
|
|
|
44
|
} or do { |
83
|
3
|
|
|
|
|
93
|
print STDERR $@; |
84
|
3
|
|
|
|
|
51
|
$exit_value = int $!; |
85
|
|
|
|
|
|
|
}; |
86
|
|
|
|
|
|
|
|
87
|
22
|
|
|
|
|
173
|
return [$stdout, $stderr, $exit_value]; |
88
|
|
|
|
|
|
|
} |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
sub extract_usage { |
91
|
4
|
|
|
4
|
1
|
23
|
my %pod2usage; |
92
|
4
|
|
|
|
|
11
|
$pod2usage{'-sections'} = shift; |
93
|
4
|
|
33
|
|
|
27
|
$pod2usage{'-input'} = shift || (caller)[1]; |
94
|
4
|
100
|
|
|
|
16
|
$pod2usage{'-verbose'} = 99 if $pod2usage{'-sections'}; |
95
|
|
|
|
|
|
|
|
96
|
4
|
|
|
|
|
1182
|
require Pod::Usage; |
97
|
4
|
|
|
|
|
79023
|
open my $USAGE, '>', \my $usage; |
98
|
4
|
|
|
|
|
40
|
Pod::Usage::pod2usage(-exitval => 'noexit', -output => $USAGE, %pod2usage); |
99
|
4
|
|
|
|
|
13719
|
close $USAGE; |
100
|
|
|
|
|
|
|
|
101
|
4
|
|
100
|
|
|
20
|
$usage //= ''; |
102
|
4
|
100
|
|
|
|
21
|
$usage =~ s!^(.*?)\n!!s if $pod2usage{'-sections'}; |
103
|
4
|
|
|
|
|
27
|
$usage =~ s!^Usage:\n\s+([A-Z])!$1!s; # Remove "Usage" header if SYNOPSIS has a description |
104
|
4
|
|
|
|
|
17
|
$usage =~ s!^ !!gm; |
105
|
|
|
|
|
|
|
|
106
|
4
|
|
100
|
|
|
30
|
return join '', $usage, _usage_for_subcommands($SUBCOMMANDS || []), _usage_for_options($OPTIONS || []); |
|
|
|
50
|
|
|
|
|
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
sub import { |
110
|
20
|
|
|
20
|
|
18592
|
my ($class, @flags) = @_; |
111
|
20
|
|
|
|
|
56
|
my $caller = caller; |
112
|
|
|
|
|
|
|
|
113
|
20
|
|
|
|
|
463
|
$_->import for qw(strict warnings utf8); |
114
|
20
|
|
|
|
|
1519
|
feature->import(':5.16'); |
115
|
|
|
|
|
|
|
|
116
|
20
|
|
|
|
|
47
|
my $skip_default; |
117
|
7
|
|
|
7
|
|
88
|
no strict qw(refs); |
|
7
|
|
|
|
|
21
|
|
|
7
|
|
|
|
|
16836
|
|
118
|
20
|
|
|
|
|
84
|
while (my $flag = shift @flags) { |
119
|
10
|
100
|
|
|
|
97
|
if ($flag eq '-capture') { |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
120
|
6
|
|
|
|
|
14
|
*{"$caller\::capture"} = \&capture; |
|
6
|
|
|
|
|
37
|
|
121
|
6
|
|
|
|
|
25
|
$skip_default = 1; |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
elsif ($flag eq '-complete') { |
124
|
2
|
|
|
|
|
460
|
require Getopt::App::Complete; |
125
|
2
|
|
|
|
|
8
|
*{"$caller\::generate_completion_script"} = \&Getopt::App::Complete::generate_completion_script; |
|
2
|
|
|
|
|
23
|
|
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
elsif ($flag eq '-signatures') { |
128
|
0
|
|
|
|
|
0
|
require experimental; |
129
|
0
|
|
|
|
|
0
|
experimental->import(qw(signatures)); |
130
|
|
|
|
|
|
|
} |
131
|
|
|
|
|
|
|
elsif ($flag !~ /^-/) { |
132
|
2
|
100
|
|
|
|
207
|
croak "package definition required - cannot extend main with $flag!" if $caller eq 'main'; |
133
|
1
|
50
|
|
|
|
110
|
croak "require $flag FAIL $@" unless eval "require $flag;1"; |
134
|
1
|
|
|
|
|
9
|
push @{"${caller}::ISA"}, $flag; |
|
1
|
|
|
|
|
20
|
|
135
|
|
|
|
|
|
|
} |
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
|
138
|
19
|
100
|
|
|
|
12000
|
unless ($skip_default) { |
139
|
13
|
50
|
|
|
|
218
|
*{"$caller\::extract_usage"} = \&extract_usage unless $caller->can('extract_usage'); |
|
13
|
|
|
|
|
65
|
|
140
|
13
|
50
|
|
|
|
89
|
*{"$caller\::new"} = \&new unless $caller->can('new'); |
|
13
|
|
|
|
|
43
|
|
141
|
13
|
|
|
|
|
32
|
*{"$caller\::run"} = \&run; |
|
13
|
|
|
|
|
1468
|
|
142
|
|
|
|
|
|
|
} |
143
|
|
|
|
|
|
|
} |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
sub new { |
146
|
49
|
|
|
49
|
1
|
2246
|
my $class = shift; |
147
|
49
|
100
|
33
|
|
|
276
|
bless @_ ? @_ > 1 ? {@_} : {%{$_[0]}} : {}, ref $class || $class; |
|
1
|
100
|
|
|
|
8
|
|
148
|
|
|
|
|
|
|
} |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
sub run { |
151
|
57
|
|
|
57
|
1
|
263
|
my @rules = @_; |
152
|
57
|
|
66
|
|
|
182
|
my $class = $Getopt::App::APP_CLASS || caller; |
153
|
45
|
|
|
45
|
|
6624
|
return sub { local $Getopt::App::APP_CLASS = $class; run(@_, @rules) } |
|
45
|
|
|
|
|
119
|
|
154
|
57
|
100
|
66
|
|
|
290
|
if !$Getopt::App::APP_CLASS and defined wantarray; |
155
|
|
|
|
|
|
|
|
156
|
45
|
|
|
|
|
84
|
my $cb = pop @rules; |
157
|
45
|
50
|
|
|
|
136
|
my $argv = ref $rules[0] eq 'ARRAY' ? shift @rules : [@ARGV]; |
158
|
45
|
|
|
|
|
107
|
local $OPTIONS = [@rules]; |
159
|
45
|
|
|
|
|
80
|
@rules = map {s!$OPT_COMMENT_RE.*$!!r} @rules; |
|
76
|
|
|
|
|
523
|
|
160
|
|
|
|
|
|
|
|
161
|
45
|
|
|
|
|
221
|
my $app = $class->new; |
162
|
45
|
100
|
66
|
|
|
184
|
return $app->$call_maybe('getopt_complete_reply') if defined $ENV{COMP_POINT} and defined $ENV{COMP_LINE}; |
163
|
|
|
|
|
|
|
|
164
|
35
|
|
|
|
|
105
|
$app->$call_maybe(getopt_pre_process_argv => $argv); |
165
|
|
|
|
|
|
|
|
166
|
35
|
|
|
|
|
119
|
local $SUBCOMMANDS = $app->$call_maybe('getopt_subcommands'); |
167
|
35
|
100
|
|
|
|
358
|
my $exit_value = $SUBCOMMANDS ? _subcommand_run_maybe($app, $SUBCOMMANDS, $argv) : undef; |
168
|
31
|
100
|
|
|
|
82
|
return _exit($app, $exit_value) if defined $exit_value; |
169
|
|
|
|
|
|
|
|
170
|
24
|
|
|
|
|
51
|
my @configure = $app->$call_maybe('getopt_configure'); |
171
|
24
|
|
|
|
|
98
|
my $prev = Getopt::Long::Configure(@configure); |
172
|
24
|
100
|
|
|
|
1792
|
my $valid = Getopt::Long::GetOptionsFromArray($argv, $app, @rules) ? 1 : 0; |
173
|
24
|
|
|
|
|
5182
|
Getopt::Long::Configure($prev); |
174
|
24
|
|
|
|
|
455
|
$app->$call_maybe(getopt_post_process_argv => $argv, {valid => $valid}); |
175
|
|
|
|
|
|
|
|
176
|
22
|
100
|
|
|
|
252
|
return _exit($app, $valid ? $app->$cb(@$argv) : 1); |
177
|
|
|
|
|
|
|
} |
178
|
|
|
|
|
|
|
|
179
|
10
|
|
|
10
|
|
35
|
sub _getopt_complete_reply { Getopt::App::Complete::complete_reply(@_) } |
180
|
|
|
|
|
|
|
|
181
|
22
|
|
|
22
|
|
76
|
sub _getopt_configure {qw(bundling no_auto_abbrev no_ignore_case pass_through require_order)} |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
sub _getopt_load_subcommand { |
184
|
6
|
|
|
6
|
|
41
|
my ($app, $subcommand, $argv) = @_; |
185
|
6
|
50
|
|
|
|
30
|
return $subcommand->[1] if ref $subcommand->[1] eq 'CODE'; |
186
|
|
|
|
|
|
|
|
187
|
6
|
|
|
|
|
34
|
($@, $!) = ('', 0); |
188
|
6
|
100
|
|
|
|
2872
|
croak "Unable to load subcommand $subcommand->[0]: $@ ($!)" unless my $code = do $subcommand->[1]; |
189
|
5
|
|
|
|
|
24
|
return $code; |
190
|
|
|
|
|
|
|
} |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
sub _getopt_post_process_argv { |
193
|
21
|
|
|
21
|
|
49
|
my ($app, $argv, $state) = @_; |
194
|
21
|
50
|
|
|
|
53
|
return unless $state->{valid}; |
195
|
21
|
100
|
100
|
|
|
87
|
return unless $argv->[0] and $argv->[0] =~ m!^-!; |
196
|
1
|
|
|
|
|
3
|
$! = 1; |
197
|
1
|
|
|
|
|
14
|
die "Invalid argument or argument order: @$argv\n"; |
198
|
|
|
|
|
|
|
} |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
sub _getopt_unknown_subcommand { |
201
|
1
|
|
|
1
|
|
4
|
my ($app, $argv) = @_; |
202
|
1
|
|
|
|
|
3
|
$! = 2; |
203
|
1
|
|
|
|
|
14
|
die "Unknown subcommand: $argv->[0]\n"; |
204
|
|
|
|
|
|
|
} |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
sub _exit { |
207
|
29
|
|
|
29
|
|
156
|
my ($app, $exit_value) = @_; |
208
|
29
|
|
100
|
|
|
58
|
$exit_value = $app->$call_maybe(getopt_post_process_exit_value => $exit_value) // $exit_value; |
209
|
29
|
100
|
100
|
|
|
175
|
$exit_value = 0 unless $exit_value and $exit_value =~ m!^\d{1,3}$!; |
210
|
29
|
100
|
|
|
|
70
|
$exit_value = 255 unless $exit_value < 255; |
211
|
29
|
50
|
|
|
|
61
|
exit $exit_value unless $Getopt::App::APP_CLASS; |
212
|
29
|
|
|
|
|
274
|
return $exit_value; |
213
|
|
|
|
|
|
|
} |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
sub _subcommand_run { |
216
|
11
|
|
|
11
|
|
25
|
my ($app, $subcommand, $argv) = @_; |
217
|
11
|
|
|
|
|
40
|
local $Getopt::App::SUBCOMMAND = $subcommand; |
218
|
11
|
100
|
|
|
|
38
|
unless ($APPS{$subcommand->[1]}) { |
219
|
6
|
|
|
|
|
17
|
$APPS{$subcommand->[1]} = $app->$call_maybe(getopt_load_subcommand => $subcommand, $argv); |
220
|
5
|
50
|
|
|
|
25
|
croak "$subcommand->[0] did not return a code ref" unless ref $APPS{$subcommand->[1]} eq 'CODE'; |
221
|
|
|
|
|
|
|
} |
222
|
|
|
|
|
|
|
|
223
|
10
|
|
|
|
|
49
|
return $APPS{$subcommand->[1]}->([@$argv[1 .. $#$argv]]); |
224
|
|
|
|
|
|
|
} |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
sub _subcommand_run_maybe { |
227
|
15
|
|
|
15
|
|
37
|
my ($app, $subcommands, $argv) = @_; |
228
|
15
|
100
|
100
|
|
|
93
|
return undef unless $argv->[0] and $argv->[0] =~ m!^\w!; |
229
|
|
|
|
|
|
|
return $app->$call_maybe(getopt_unknown_subcommand => $argv) |
230
|
12
|
100
|
|
35
|
|
90
|
unless my $subcommand = first { $_->[0] eq $argv->[0] } @$subcommands; |
|
35
|
|
|
|
|
79
|
|
231
|
8
|
|
|
|
|
35
|
return _subcommand_run($app, $subcommand, $argv); |
232
|
|
|
|
|
|
|
} |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
sub _usage_for_options { |
235
|
4
|
|
|
4
|
|
9
|
my ($rules) = @_; |
236
|
4
|
100
|
|
|
|
31
|
return '' unless @$rules; |
237
|
|
|
|
|
|
|
|
238
|
3
|
|
|
|
|
13
|
my ($len, @options) = (0); |
239
|
3
|
|
|
|
|
9
|
for (@$rules) { |
240
|
8
|
|
|
|
|
51
|
my @o = split $OPT_COMMENT_RE, $_, 2; |
241
|
8
|
|
|
|
|
29
|
$o[0] =~ s/(=[si][@%]?|\!|\+)$//; |
242
|
8
|
100
|
|
|
|
28
|
$o[0] = join ', ', map { length($_) == 1 ? "-$_" : "--$_" } sort { length($b) <=> length($a) } split /\|/, $o[0]; |
|
10
|
|
|
|
|
44
|
|
|
2
|
|
|
|
|
9
|
|
243
|
8
|
|
100
|
|
|
34
|
$o[1] //= ''; |
244
|
|
|
|
|
|
|
|
245
|
8
|
|
|
|
|
11
|
my $l = length $o[0]; |
246
|
8
|
100
|
|
|
|
19
|
$len = $l if $l > $len; |
247
|
8
|
|
|
|
|
21
|
push @options, \@o; |
248
|
|
|
|
|
|
|
} |
249
|
|
|
|
|
|
|
|
250
|
3
|
|
|
|
|
8
|
return "Options:\n" . join('', map { sprintf " %-${len}s %s\n", @$_ } @options) . "\n"; |
|
8
|
|
|
|
|
71
|
|
251
|
|
|
|
|
|
|
} |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
sub _usage_for_subcommands { |
254
|
4
|
|
|
4
|
|
11
|
my ($subcommands) = @_; |
255
|
4
|
100
|
|
|
|
28
|
return '' unless @$subcommands; |
256
|
|
|
|
|
|
|
|
257
|
1
|
|
|
|
|
5
|
my ($len, @cmds) = (0); |
258
|
1
|
|
|
|
|
6
|
for my $s (@$subcommands) { |
259
|
5
|
|
|
|
|
10
|
my $l = length $s->[0]; |
260
|
5
|
100
|
|
|
|
11
|
$len = $l if $l > $len; |
261
|
5
|
|
50
|
|
|
15
|
push @cmds, [$s->[0], $s->[2] // '']; |
262
|
|
|
|
|
|
|
} |
263
|
|
|
|
|
|
|
|
264
|
1
|
|
|
|
|
7
|
return "Subcommands:\n" . join('', map { sprintf " %-${len}s %s\n", @$_ } @cmds) . "\n"; |
|
5
|
|
|
|
|
30
|
|
265
|
|
|
|
|
|
|
} |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
1; |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
=encoding utf8 |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
=head1 NAME |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
Getopt::App - Write and test your script with ease |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
=head1 SYNOPSIS |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
=head2 The script file |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
#!/usr/bin/env perl |
280
|
|
|
|
|
|
|
package My::Script; |
281
|
|
|
|
|
|
|
use Getopt::App -complete, -signatures; |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
# See "APPLICATION METHODS" |
284
|
|
|
|
|
|
|
sub getopt_post_process_argv ($app, $argv, $state) { ... } |
285
|
|
|
|
|
|
|
sub getopt_configure ($app) { ... } |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
# run() must be the last statement in the script |
288
|
|
|
|
|
|
|
run( |
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
# Specify your Getopt::Long options and optionally a help text |
291
|
|
|
|
|
|
|
'h|help # Output help', |
292
|
|
|
|
|
|
|
'v+ # Verbose output', |
293
|
|
|
|
|
|
|
'name=s # Specify a name', |
294
|
|
|
|
|
|
|
'completion-script # Print autocomplete script', |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
# Here is the main sub that will run the script |
297
|
|
|
|
|
|
|
sub ($app, @extra) { |
298
|
|
|
|
|
|
|
return print generate_completion_script() if $app->{'completion-script'}; |
299
|
|
|
|
|
|
|
return print extract_usage() if $app->{h}; |
300
|
|
|
|
|
|
|
say $app->{name} // 'no name'; # Access command line options |
301
|
|
|
|
|
|
|
return 42; # Reture value is used as exit code |
302
|
|
|
|
|
|
|
} |
303
|
|
|
|
|
|
|
); |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
=head2 Running the script |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
The example script above can be run like any other script: |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
$ my-script --name superwoman; # prints "superwoman" |
310
|
|
|
|
|
|
|
$ echo $? # 42 |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
=head2 Testing |
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
use Test::More; |
315
|
|
|
|
|
|
|
use Cwd qw(abs_path); |
316
|
|
|
|
|
|
|
use Getopt::App -capture; |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
# Sourcing the script returns a callback |
319
|
|
|
|
|
|
|
my $app = do(abs_path('./bin/myapp')); |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
# The callback can be called with any @ARGV |
322
|
|
|
|
|
|
|
subtest name => sub { |
323
|
|
|
|
|
|
|
my $got = capture($app, [qw(--name superwoman)]); |
324
|
|
|
|
|
|
|
is $got->[0], "superwoman\n", 'stdout'; |
325
|
|
|
|
|
|
|
is $got->[1], '', 'stderr'; |
326
|
|
|
|
|
|
|
is $got->[2], 42, 'exit value'; |
327
|
|
|
|
|
|
|
}; |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
done_testing; |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
=head2 Subcommands |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
#!/usr/bin/env perl |
334
|
|
|
|
|
|
|
# Define a package to avoid mixing methods after loading the subcommand script |
335
|
|
|
|
|
|
|
package My::App::main; |
336
|
|
|
|
|
|
|
use Getopt::App -complete; |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
# getopt_subcommands() is called by Getopt::App |
339
|
|
|
|
|
|
|
sub getopt_subcommands { |
340
|
|
|
|
|
|
|
my $app = shift; |
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
return [ |
343
|
|
|
|
|
|
|
['find', '/path/to/subcommand/find.pl', 'Find things'], |
344
|
|
|
|
|
|
|
['update', '/path/to/subcommand/update.pl', 'Update things'], |
345
|
|
|
|
|
|
|
]; |
346
|
|
|
|
|
|
|
} |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
# run() is only called if there are no matching sub commands |
349
|
|
|
|
|
|
|
run( |
350
|
|
|
|
|
|
|
'h # Print help', |
351
|
|
|
|
|
|
|
'completion-script # Print autocomplete script', |
352
|
|
|
|
|
|
|
sub { |
353
|
|
|
|
|
|
|
my ($app, @args) = @_; |
354
|
|
|
|
|
|
|
return print generate_completion_script() if $app->{'completion-script'}; |
355
|
|
|
|
|
|
|
return print extract_usage(); |
356
|
|
|
|
|
|
|
} |
357
|
|
|
|
|
|
|
); |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
See L and L |
360
|
|
|
|
|
|
|
for more details. |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
=head1 DESCRIPTION |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
L is a module that helps you structure your scripts and integrates |
365
|
|
|
|
|
|
|
L with a very simple API. In addition it makes it very easy to |
366
|
|
|
|
|
|
|
test your script, since the script file can be sourced without actually being |
367
|
|
|
|
|
|
|
run. |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
L also supports infinite nested L |
370
|
|
|
|
|
|
|
and a method for L this module with your script to prevent |
371
|
|
|
|
|
|
|
depending on a module from CPAN. |
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
=head1 APPLICATION METHODS |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
These methods are optional, but can be defined in your script to override the |
376
|
|
|
|
|
|
|
default behavior. |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
=head2 getopt_complete_reply |
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
$app->getopt_complete_reply; |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
This method will be called instead of the L callback when the |
383
|
|
|
|
|
|
|
C and C environment variables are set. The default |
384
|
|
|
|
|
|
|
implementation will call L. |
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
See also "Completion" under L. |
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
=head2 getopt_configure |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
@configure = $app->getopt_configure; |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
This method can be defined if you want L to be set up |
393
|
|
|
|
|
|
|
differently. The default return value is: |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
qw(bundling no_auto_abbrev no_ignore_case pass_through require_order) |
396
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
The default return value is currently EXPERIMENTAL. |
398
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
=head2 getopt_load_subcommand |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
$code = $app->getopt_load_subcommand($subcommand, [@ARGV]); |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
Takes the subcommand found in the L list and the command |
404
|
|
|
|
|
|
|
line arguments and must return a CODE block. The default implementation is |
405
|
|
|
|
|
|
|
simply: |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
$code = do($subcommand->[1]); |
408
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
=head2 getopt_post_process_argv |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
$bool = $app->getopt_post_process_argv([@ARGV], {%state}); |
412
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
This method can be used to post process the options. C<%state> contains a key |
414
|
|
|
|
|
|
|
"valid" which is true or false, depending on the return value from |
415
|
|
|
|
|
|
|
L. |
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
This method can C and optionally set C<$!> to avoid calling the function |
418
|
|
|
|
|
|
|
passed to L. |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
The default behavior is to check if the first item in C<$argv> starts with a |
421
|
|
|
|
|
|
|
hyphen, and C with an error message if so: |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
Invalid argument or argument order: @$argv\n |
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
=head2 getopt_post_process_exit_value |
426
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
$exit_value = $app->getopt_post_process_exit_value($exit_value); |
428
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
A method to be called after the L function has been called. |
430
|
|
|
|
|
|
|
C<$exit_value> holds the return value from L which could be any value, |
431
|
|
|
|
|
|
|
not just 0-255. This value can then be changed to change the exit value from |
432
|
|
|
|
|
|
|
the program. |
433
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
sub getopt_post_process_exit_value ($app, $exit_value) { |
435
|
|
|
|
|
|
|
return int(1 + rand 10); |
436
|
|
|
|
|
|
|
} |
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
=head2 getopt_pre_process_argv |
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
$app->getopt_pre_process_argv($argv); |
441
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
This method can be defined to pre-process C<$argv> before it is passed on to |
443
|
|
|
|
|
|
|
L. Example: |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
sub getopt_pre_process_argv ($app, $argv) { |
446
|
|
|
|
|
|
|
$app->{first_non_option} = shift @$argv if @$argv and $argv->[0] =~ m!^[a-z]!; |
447
|
|
|
|
|
|
|
} |
448
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
This method can C and optionally set C<$!> to avoid calling the actual |
450
|
|
|
|
|
|
|
L function. |
451
|
|
|
|
|
|
|
|
452
|
|
|
|
|
|
|
=head2 getopt_subcommands |
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
$subcommands = $app->getopt_subcommands; |
455
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
This method must be defined in the script to enable sub commands. The return |
457
|
|
|
|
|
|
|
value must be either C to disable subcommands or an array-ref of |
458
|
|
|
|
|
|
|
array-refs like this: |
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
[["subname", "/abs/path/to/sub-command-script", "help text"], ...] |
461
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
The first element in each array-ref "subname" will be matched against the first |
463
|
|
|
|
|
|
|
argument passed to the script, and when matched the "sub-command-script" will |
464
|
|
|
|
|
|
|
be sourced and run inside the same perl process. The sub command script must |
465
|
|
|
|
|
|
|
also use L for this to work properly. |
466
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
The sub-command will have C<$Getopt::App::SUBCOMMAND> set to the item found in |
468
|
|
|
|
|
|
|
the list. |
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
See L for a working |
471
|
|
|
|
|
|
|
example. |
472
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
=head2 getopt_unknown_subcommand |
474
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
$exit_value = $app->getopt_unknown_subcommand($argv); |
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
Will be called when L is defined but C<$argv> does not |
478
|
|
|
|
|
|
|
match an item in the list. Default behavior is to C with an error message: |
479
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
Unknown subcommand: $argv->[0]\n |
481
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
Returning C instead of dying or a number (0-255) will cause the L |
483
|
|
|
|
|
|
|
callback to be called. |
484
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
=head1 EXPORTED FUNCTIONS |
486
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
=head2 capture |
488
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
use Getopt::App -capture; |
490
|
|
|
|
|
|
|
my $app = do '/path/to/bin/myapp'; |
491
|
|
|
|
|
|
|
my $array_ref = capture($app, [@ARGV]); # [$stdout, $stderr, $exit_value] |
492
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
Used to run an C<$app> and capture STDOUT, STDERR and the exit value in that |
494
|
|
|
|
|
|
|
order in C<$array_ref>. This function will also capture C. C<$@> will be |
495
|
|
|
|
|
|
|
set and captured in the second C<$array_ref> element, and C<$exit_value> will |
496
|
|
|
|
|
|
|
be set to C<$!>. |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
=head2 extract_usage |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
# Default to "SYNOPSIS" from current file |
501
|
|
|
|
|
|
|
my $str = extract_usage($section, $file); |
502
|
|
|
|
|
|
|
my $str = extract_usage($section); |
503
|
|
|
|
|
|
|
my $str = extract_usage(); |
504
|
|
|
|
|
|
|
|
505
|
|
|
|
|
|
|
Will extract a C<$section> from POD C<$file> and append command line option |
506
|
|
|
|
|
|
|
descriptions when called from inside of L. Command line options can |
507
|
|
|
|
|
|
|
optionally have a description with "spaces-hash-spaces-description", like this: |
508
|
|
|
|
|
|
|
|
509
|
|
|
|
|
|
|
run( |
510
|
|
|
|
|
|
|
'o|option # Some description', |
511
|
|
|
|
|
|
|
'v|verbose # Enable verbose output', |
512
|
|
|
|
|
|
|
sub { |
513
|
|
|
|
|
|
|
... |
514
|
|
|
|
|
|
|
}, |
515
|
|
|
|
|
|
|
); |
516
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
This function will I be exported if a function with the same name already |
518
|
|
|
|
|
|
|
exists in the script. |
519
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
=head2 new |
521
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
my $obj = new($class, %args); |
523
|
|
|
|
|
|
|
my $obj = new($class, \%args); |
524
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
This function is exported into the caller package so we can construct a new |
526
|
|
|
|
|
|
|
object: |
527
|
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
my $app = Application::Class->new(\%args); |
529
|
|
|
|
|
|
|
|
530
|
|
|
|
|
|
|
This function will I be exported if a function with the same name already |
531
|
|
|
|
|
|
|
exists in the script. |
532
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
=head2 run |
534
|
|
|
|
|
|
|
|
535
|
|
|
|
|
|
|
# Run a code block on valid @ARGV |
536
|
|
|
|
|
|
|
run(@rules, sub ($app, @extra) { ... }); |
537
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
# For testing |
539
|
|
|
|
|
|
|
my $cb = run(@rules, sub ($app, @extra) { ... }); |
540
|
|
|
|
|
|
|
my $exit_value = $cb->([@ARGV]); |
541
|
|
|
|
|
|
|
|
542
|
|
|
|
|
|
|
L can be used to call a callback when valid command line options is |
543
|
|
|
|
|
|
|
provided. On invalid arguments, warnings will be issued and the program exit |
544
|
|
|
|
|
|
|
with C<$?> set to 1. |
545
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
C<$app> inside the callback is a hash blessed to the caller package. The keys |
547
|
|
|
|
|
|
|
in the hash are the parsed command line options, while C<@extra> is the extra |
548
|
|
|
|
|
|
|
unparsed command line options. |
549
|
|
|
|
|
|
|
|
550
|
|
|
|
|
|
|
C<@rules> are the same options as L can take. Example: |
551
|
|
|
|
|
|
|
|
552
|
|
|
|
|
|
|
# app.pl -vv --name superwoman -o OptX cool beans |
553
|
|
|
|
|
|
|
run(qw(h|help v+ name=s o=s@), sub ($app, @extra) { |
554
|
|
|
|
|
|
|
die "No help here" if $app->{h}; |
555
|
|
|
|
|
|
|
warn $app->{v}; # 2 |
556
|
|
|
|
|
|
|
warn $app->{name}; # "superwoman" |
557
|
|
|
|
|
|
|
warn @{$app->{o}}; # "OptX" |
558
|
|
|
|
|
|
|
warn @extra; # "cool beans" |
559
|
|
|
|
|
|
|
return 0; # Used as exit code |
560
|
|
|
|
|
|
|
}); |
561
|
|
|
|
|
|
|
|
562
|
|
|
|
|
|
|
In the example above, C<@extra> gets populated, since there is a non-flag value |
563
|
|
|
|
|
|
|
"cool" after a list of valid command line options. |
564
|
|
|
|
|
|
|
|
565
|
|
|
|
|
|
|
=head1 METHODS |
566
|
|
|
|
|
|
|
|
567
|
|
|
|
|
|
|
=head2 bundle |
568
|
|
|
|
|
|
|
|
569
|
|
|
|
|
|
|
Getopt::App->bundle($path_to_script); |
570
|
|
|
|
|
|
|
Getopt::App->bundle($path_to_script, $fh); |
571
|
|
|
|
|
|
|
|
572
|
|
|
|
|
|
|
This method can be used to combine L and C<$path_to_script> into a |
573
|
|
|
|
|
|
|
a single script that does not need to have L installed from CPAN. |
574
|
|
|
|
|
|
|
This is for example useful for sysadmin scripts that otherwise only depends on |
575
|
|
|
|
|
|
|
core Perl modules. |
576
|
|
|
|
|
|
|
|
577
|
|
|
|
|
|
|
The script will be printed to C<$fh>, which defaults to C. |
578
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
Example usage: |
580
|
|
|
|
|
|
|
|
581
|
|
|
|
|
|
|
perl -MGetopt::App -e'Getopt::App->bundle(shift)' ./src/my-script.pl > ./bin/my-script; |
582
|
|
|
|
|
|
|
|
583
|
|
|
|
|
|
|
=head2 import |
584
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
use Getopt::App; |
586
|
|
|
|
|
|
|
use Getopt::App 'My::Script::Base', -signatures; |
587
|
|
|
|
|
|
|
use Getopt::App -capture; |
588
|
|
|
|
|
|
|
|
589
|
|
|
|
|
|
|
=over 2 |
590
|
|
|
|
|
|
|
|
591
|
|
|
|
|
|
|
=item * Default |
592
|
|
|
|
|
|
|
|
593
|
|
|
|
|
|
|
use Getopt::App; |
594
|
|
|
|
|
|
|
|
595
|
|
|
|
|
|
|
Passing in no flags will export the default functions L, |
596
|
|
|
|
|
|
|
L and L. In addition it will save you from a lot of typing, since |
597
|
|
|
|
|
|
|
it will also import the following: |
598
|
|
|
|
|
|
|
|
599
|
|
|
|
|
|
|
use strict; |
600
|
|
|
|
|
|
|
use warnings; |
601
|
|
|
|
|
|
|
use utf8; |
602
|
|
|
|
|
|
|
use feature ':5.16'; |
603
|
|
|
|
|
|
|
|
604
|
|
|
|
|
|
|
=item * Completion |
605
|
|
|
|
|
|
|
|
606
|
|
|
|
|
|
|
use Getopt::App -complete; |
607
|
|
|
|
|
|
|
|
608
|
|
|
|
|
|
|
Same as L, but will also load L and import |
609
|
|
|
|
|
|
|
L. |
610
|
|
|
|
|
|
|
|
611
|
|
|
|
|
|
|
=item * Signatures |
612
|
|
|
|
|
|
|
|
613
|
|
|
|
|
|
|
use Getopt::App -signatures; |
614
|
|
|
|
|
|
|
|
615
|
|
|
|
|
|
|
Same as L, but will also import L. This |
616
|
|
|
|
|
|
|
requires Perl 5.20+. |
617
|
|
|
|
|
|
|
|
618
|
|
|
|
|
|
|
=item * Class name |
619
|
|
|
|
|
|
|
|
620
|
|
|
|
|
|
|
package My::Script::Foo; |
621
|
|
|
|
|
|
|
use Getopt::App 'My::Script'; |
622
|
|
|
|
|
|
|
|
623
|
|
|
|
|
|
|
Same as L but will also make C inherit from |
624
|
|
|
|
|
|
|
L. Note that a package definition is required. |
625
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
=item * Capture |
627
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
use Getopt::App -capture; |
629
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
This will only export L. |
631
|
|
|
|
|
|
|
|
632
|
|
|
|
|
|
|
=back |
633
|
|
|
|
|
|
|
|
634
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
635
|
|
|
|
|
|
|
|
636
|
|
|
|
|
|
|
This library is free software. You can redistribute it and/or modify it under |
637
|
|
|
|
|
|
|
the same terms as Perl itself. |
638
|
|
|
|
|
|
|
|
639
|
|
|
|
|
|
|
=head1 AUTHOR |
640
|
|
|
|
|
|
|
|
641
|
|
|
|
|
|
|
Jan Henning Thorsen - C |
642
|
|
|
|
|
|
|
|
643
|
|
|
|
|
|
|
=cut |