| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
# Paranoid::Args -- Command-line argument parsing functions |
|
2
|
|
|
|
|
|
|
# |
|
3
|
|
|
|
|
|
|
# $Id: lib/Paranoid/Args.pm, 2.10 2022/03/08 00:01:04 acorliss Exp $ |
|
4
|
|
|
|
|
|
|
# |
|
5
|
|
|
|
|
|
|
# This software is free software. Similar to Perl, you can redistribute it |
|
6
|
|
|
|
|
|
|
# and/or modify it under the terms of either: |
|
7
|
|
|
|
|
|
|
# |
|
8
|
|
|
|
|
|
|
# a) the GNU General Public License |
|
9
|
|
|
|
|
|
|
# as published by the |
|
10
|
|
|
|
|
|
|
# Free Software Foundation ; either version 1 |
|
11
|
|
|
|
|
|
|
# , or any later version |
|
12
|
|
|
|
|
|
|
# , or |
|
13
|
|
|
|
|
|
|
# b) the Artistic License 2.0 |
|
14
|
|
|
|
|
|
|
# , |
|
15
|
|
|
|
|
|
|
# |
|
16
|
|
|
|
|
|
|
# subject to the following additional term: No trademark rights to |
|
17
|
|
|
|
|
|
|
# "Paranoid" have been or are conveyed under any of the above licenses. |
|
18
|
|
|
|
|
|
|
# However, "Paranoid" may be used fairly to describe this unmodified |
|
19
|
|
|
|
|
|
|
# software, in good faith, but not as a trademark. |
|
20
|
|
|
|
|
|
|
# |
|
21
|
|
|
|
|
|
|
# (c) 2005 - 2020, Arthur Corliss (corliss@digitalmages.com) |
|
22
|
|
|
|
|
|
|
# (tm) 2008 - 2020, Paranoid Inc. (www.paranoid.com) |
|
23
|
|
|
|
|
|
|
# |
|
24
|
|
|
|
|
|
|
##################################################################### |
|
25
|
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
##################################################################### |
|
27
|
|
|
|
|
|
|
# |
|
28
|
|
|
|
|
|
|
# Environment definitions |
|
29
|
|
|
|
|
|
|
# |
|
30
|
|
|
|
|
|
|
##################################################################### |
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
package Paranoid::Args; |
|
33
|
|
|
|
|
|
|
|
|
34
|
2
|
|
|
2
|
|
949
|
use 5.008; |
|
|
2
|
|
|
|
|
6
|
|
|
35
|
|
|
|
|
|
|
|
|
36
|
2
|
|
|
2
|
|
8
|
use strict; |
|
|
2
|
|
|
|
|
2
|
|
|
|
2
|
|
|
|
|
31
|
|
|
37
|
2
|
|
|
2
|
|
6
|
use warnings; |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
44
|
|
|
38
|
2
|
|
|
2
|
|
8
|
use vars qw($VERSION @EXPORT @EXPORT_OK %EXPORT_TAGS); |
|
|
2
|
|
|
|
|
10
|
|
|
|
2
|
|
|
|
|
119
|
|
|
39
|
2
|
|
|
2
|
|
11
|
use base qw(Exporter); |
|
|
2
|
|
|
|
|
3
|
|
|
|
2
|
|
|
|
|
122
|
|
|
40
|
2
|
|
|
2
|
|
9
|
use Paranoid; |
|
|
2
|
|
|
|
|
11
|
|
|
|
2
|
|
|
|
|
98
|
|
|
41
|
2
|
|
|
2
|
|
815
|
use Paranoid::Debug qw(:all); |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
443
|
|
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
($VERSION) = ( q$Revision: 2.10 $ =~ /(\d+(?:\.\d+)+)/sm ); |
|
44
|
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
@EXPORT = qw(parseArgs); |
|
46
|
|
|
|
|
|
|
@EXPORT_OK = ( @EXPORT, qw(PA_DEBUG PA_VERBOSE PA_HELP PA_VERSION) ); |
|
47
|
|
|
|
|
|
|
%EXPORT_TAGS = ( |
|
48
|
|
|
|
|
|
|
all => [@EXPORT_OK], |
|
49
|
|
|
|
|
|
|
template => [qw(PA_DEBUG PA_VERBOSE PA_HELP PA_VERSION)], |
|
50
|
|
|
|
|
|
|
); |
|
51
|
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
# I know, this really doesn't protect the contents... |
|
53
|
2
|
|
|
|
|
114
|
use constant PA_DEBUG => { |
|
54
|
|
|
|
|
|
|
Short => 'D', |
|
55
|
|
|
|
|
|
|
Long => 'debug', |
|
56
|
|
|
|
|
|
|
CountShort => 1, |
|
57
|
2
|
|
|
2
|
|
13
|
}; |
|
|
2
|
|
|
|
|
4
|
|
|
58
|
2
|
|
|
|
|
116
|
use constant PA_VERBOSE => { |
|
59
|
|
|
|
|
|
|
Short => 'v', |
|
60
|
|
|
|
|
|
|
Long => 'verbose', |
|
61
|
|
|
|
|
|
|
CountShort => 1, |
|
62
|
2
|
|
|
2
|
|
36
|
}; |
|
|
2
|
|
|
|
|
5
|
|
|
63
|
2
|
|
|
|
|
92
|
use constant PA_HELP => { |
|
64
|
|
|
|
|
|
|
Short => 'h', |
|
65
|
|
|
|
|
|
|
Long => 'help', |
|
66
|
2
|
|
|
2
|
|
11
|
}; |
|
|
2
|
|
|
|
|
3
|
|
|
67
|
2
|
|
|
|
|
5606
|
use constant PA_VERSION => { |
|
68
|
|
|
|
|
|
|
Short => 'V', |
|
69
|
|
|
|
|
|
|
Long => 'version', |
|
70
|
2
|
|
|
2
|
|
9
|
}; |
|
|
2
|
|
|
|
|
4
|
|
|
71
|
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
##################################################################### |
|
73
|
|
|
|
|
|
|
# |
|
74
|
|
|
|
|
|
|
# Module code follows |
|
75
|
|
|
|
|
|
|
# |
|
76
|
|
|
|
|
|
|
##################################################################### |
|
77
|
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
{ |
|
79
|
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
# Internal boolean flag for noOptions |
|
81
|
|
|
|
|
|
|
my $noOptions = 0; |
|
82
|
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
sub _NOOPTIONS : lvalue { |
|
84
|
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
# Purpose: Gets/sets value of boolean flag $noOptions |
|
86
|
|
|
|
|
|
|
# Returns: Value of $noOptions |
|
87
|
|
|
|
|
|
|
# Usage: $flag = _NOOPTIONS; |
|
88
|
|
|
|
|
|
|
# Usage: _NOOPTIONS = 1; |
|
89
|
|
|
|
|
|
|
|
|
90
|
70
|
|
|
70
|
|
192
|
$noOptions; |
|
91
|
|
|
|
|
|
|
} |
|
92
|
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
# Internal errors array |
|
94
|
|
|
|
|
|
|
my @errors; |
|
95
|
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
sub _resetErrors { |
|
97
|
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
# Purpose: Empties @errors |
|
99
|
|
|
|
|
|
|
# Returns: True (1) |
|
100
|
|
|
|
|
|
|
# Usage: resetErrors(); |
|
101
|
|
|
|
|
|
|
|
|
102
|
14
|
|
|
14
|
|
23
|
@errors = (); |
|
103
|
14
|
|
|
|
|
16
|
return 1; |
|
104
|
|
|
|
|
|
|
} |
|
105
|
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
sub _pushErrors { |
|
107
|
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
# Purpose: Pushes a new string onto the @errors array |
|
109
|
|
|
|
|
|
|
# Returns: Same argument as called with |
|
110
|
|
|
|
|
|
|
# Usage: _pushErrors($message); |
|
111
|
|
|
|
|
|
|
|
|
112
|
7
|
|
|
7
|
|
10
|
my $message = shift; |
|
113
|
7
|
|
|
|
|
9
|
push @errors, $message; |
|
114
|
7
|
|
|
|
|
8
|
return $message; |
|
115
|
|
|
|
|
|
|
} |
|
116
|
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
sub listErrors { |
|
118
|
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
# Purpose: Gets the contents of @errors |
|
120
|
|
|
|
|
|
|
# Returns: Contents of @errors |
|
121
|
|
|
|
|
|
|
# Usage: @errors = listErrors(); |
|
122
|
|
|
|
|
|
|
|
|
123
|
6
|
|
|
6
|
1
|
11
|
my ( %messages, $n, @indices ); |
|
124
|
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
# Filter out redundant messages |
|
126
|
6
|
|
|
|
|
7
|
$n = 0; |
|
127
|
6
|
|
|
|
|
11
|
foreach (@errors) { |
|
128
|
7
|
|
|
|
|
12
|
$messages{$_}++; |
|
129
|
7
|
100
|
|
|
|
16
|
push @indices, $n if $messages{$_} > 1; |
|
130
|
7
|
|
|
|
|
9
|
$n++; |
|
131
|
|
|
|
|
|
|
} |
|
132
|
6
|
|
|
|
|
13
|
foreach ( sort { $b <=> $a } @indices ) { |
|
|
0
|
|
|
|
|
0
|
|
|
133
|
2
|
|
|
|
|
5
|
splice @errors, $_, 1; |
|
134
|
|
|
|
|
|
|
} |
|
135
|
|
|
|
|
|
|
|
|
136
|
6
|
|
|
|
|
14
|
return @errors; |
|
137
|
|
|
|
|
|
|
} |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
# Internal options hash |
|
140
|
|
|
|
|
|
|
my %options; |
|
141
|
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
sub _getOption { |
|
143
|
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
# Purpose: Gets the template associated with passed option |
|
145
|
|
|
|
|
|
|
# Returns: Reference to template hash or undef should the |
|
146
|
|
|
|
|
|
|
# requested option not be defined |
|
147
|
|
|
|
|
|
|
# Usage: $tref = _getOption($option); |
|
148
|
|
|
|
|
|
|
|
|
149
|
502
|
|
|
502
|
|
558
|
my $option = shift; |
|
150
|
|
|
|
|
|
|
|
|
151
|
502
|
100
|
|
|
|
892
|
return exists $options{$option} ? $options{$option} : undef; |
|
152
|
|
|
|
|
|
|
} |
|
153
|
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
sub _setOption { |
|
155
|
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
# Purpose: Associates the passed option to the passed template in |
|
157
|
|
|
|
|
|
|
# %options |
|
158
|
|
|
|
|
|
|
# Returns: True (1) |
|
159
|
|
|
|
|
|
|
# Usage: _setOption($option, $tref); |
|
160
|
|
|
|
|
|
|
|
|
161
|
203
|
|
|
203
|
|
211
|
my $option = shift; |
|
162
|
203
|
|
|
|
|
191
|
my $tref = shift; |
|
163
|
|
|
|
|
|
|
|
|
164
|
203
|
|
|
|
|
259
|
$options{$option} = $tref; |
|
165
|
|
|
|
|
|
|
|
|
166
|
203
|
|
|
|
|
224
|
return 1; |
|
167
|
|
|
|
|
|
|
} |
|
168
|
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
sub _optionsKeys { |
|
170
|
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
# Purpose: Returns a list of keys from %options |
|
172
|
|
|
|
|
|
|
# Returns: keys %options |
|
173
|
|
|
|
|
|
|
# Usage: @keys = _optionsKeys(); |
|
174
|
|
|
|
|
|
|
|
|
175
|
14
|
|
|
14
|
|
48
|
return keys %options; |
|
176
|
|
|
|
|
|
|
} |
|
177
|
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
sub _resetOptions { |
|
179
|
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
# Purpose: Empties the %options |
|
181
|
|
|
|
|
|
|
# Returns: True (1) |
|
182
|
|
|
|
|
|
|
# Usage: _resetOptions(); |
|
183
|
|
|
|
|
|
|
|
|
184
|
14
|
|
|
14
|
|
118
|
%options = (); |
|
185
|
|
|
|
|
|
|
|
|
186
|
14
|
|
|
|
|
16
|
return 1; |
|
187
|
|
|
|
|
|
|
} |
|
188
|
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
# Internal arguments list |
|
190
|
|
|
|
|
|
|
my @arguments; |
|
191
|
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
sub _getArgRef { |
|
193
|
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
# Purpose: Gets a reference the argument array |
|
195
|
|
|
|
|
|
|
# Returns: Array reference |
|
196
|
|
|
|
|
|
|
# Usage: $argRef = _getArgRef(); |
|
197
|
|
|
|
|
|
|
|
|
198
|
64
|
|
|
64
|
|
84
|
return \@arguments; |
|
199
|
|
|
|
|
|
|
} |
|
200
|
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
sub clearMemory { |
|
202
|
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
# Purpose: Empties all internal data structures |
|
204
|
|
|
|
|
|
|
# Returns: True (1) |
|
205
|
|
|
|
|
|
|
# Usage: clearMemory(); |
|
206
|
|
|
|
|
|
|
|
|
207
|
14
|
|
|
14
|
1
|
22
|
_NOOPTIONS = 0; |
|
208
|
14
|
|
|
|
|
29
|
_resetErrors(); |
|
209
|
14
|
|
|
|
|
22
|
_resetOptions(); |
|
210
|
14
|
|
|
|
|
15
|
@{ _getArgRef() } = (); |
|
|
14
|
|
|
|
|
19
|
|
|
211
|
|
|
|
|
|
|
|
|
212
|
14
|
|
|
|
|
15
|
return 1; |
|
213
|
|
|
|
|
|
|
} |
|
214
|
|
|
|
|
|
|
} |
|
215
|
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
sub _tLint { |
|
217
|
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
# Purpose: Performs basic checks on a given option template for |
|
219
|
|
|
|
|
|
|
# correctness |
|
220
|
|
|
|
|
|
|
# Returns: True (1) if all checks pass, False (0) otherwise |
|
221
|
|
|
|
|
|
|
# Usage: $rv = _tLint($templateRef); |
|
222
|
|
|
|
|
|
|
|
|
223
|
108
|
|
|
108
|
|
114
|
my $tref = shift; # Reference to option template hash |
|
224
|
108
|
|
|
|
|
113
|
my $rv = 1; |
|
225
|
108
|
|
|
|
|
124
|
my ( $oname, @at ); |
|
226
|
|
|
|
|
|
|
|
|
227
|
108
|
|
|
|
|
215
|
subPreamble( PDLEVEL2, '$', $tref ); |
|
228
|
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
# Get the option name for reporting purposes (should have been populated |
|
230
|
|
|
|
|
|
|
# within parseArgs below) |
|
231
|
108
|
|
|
|
|
139
|
$oname = $$tref{Name}; |
|
232
|
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
# Make sure a short or long option is declared |
|
234
|
108
|
50
|
|
|
|
169
|
if ( !defined $oname ) { |
|
235
|
0
|
|
|
|
|
0
|
_pushErrors('No short or long option name declared'); |
|
236
|
0
|
|
|
|
|
0
|
$rv = 0; |
|
237
|
|
|
|
|
|
|
} |
|
238
|
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
# Make sure the argument template is defined |
|
240
|
108
|
50
|
|
|
|
140
|
if ($rv) { |
|
241
|
108
|
50
|
|
|
|
161
|
unless ( defined $$tref{Template} ) { |
|
242
|
0
|
|
|
|
|
0
|
_pushErrors("$oname option declared without a template"); |
|
243
|
0
|
|
|
|
|
0
|
$rv = 0; |
|
244
|
|
|
|
|
|
|
} |
|
245
|
|
|
|
|
|
|
} |
|
246
|
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
# Make sure the template contains only supported characters |
|
248
|
108
|
50
|
|
|
|
149
|
if ($rv) { |
|
249
|
108
|
50
|
33
|
|
|
402
|
unless ( defined $$tref{Template} |
|
250
|
|
|
|
|
|
|
&& $$tref{Template} =~ /^[\$\@]*$/s ) { |
|
251
|
0
|
|
|
|
|
0
|
_pushErrors( "$oname option declared with an invalid template" |
|
252
|
|
|
|
|
|
|
. "($$tref{Template})" ); |
|
253
|
0
|
|
|
|
|
0
|
$rv = 0; |
|
254
|
|
|
|
|
|
|
} |
|
255
|
|
|
|
|
|
|
} |
|
256
|
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
# Make sure option names are sane |
|
258
|
108
|
50
|
|
|
|
167
|
if ($rv) { |
|
259
|
108
|
100
|
|
|
|
175
|
if ( defined $$tref{Short} ) { |
|
260
|
95
|
50
|
|
|
|
176
|
unless ( $$tref{Short} =~ /^[a-zA-Z0-9]$/s ) { |
|
261
|
0
|
|
|
|
|
0
|
_pushErrors( |
|
262
|
|
|
|
|
|
|
"Invalid name for the short option ($$tref{Short})"); |
|
263
|
0
|
|
|
|
|
0
|
$rv = 0; |
|
264
|
|
|
|
|
|
|
} |
|
265
|
|
|
|
|
|
|
} |
|
266
|
108
|
50
|
|
|
|
165
|
if ( defined $$tref{Long} ) { |
|
267
|
108
|
50
|
|
|
|
248
|
unless ( $$tref{Long} =~ /^[a-zA-Z0-9-]{2,}$/s ) { |
|
268
|
0
|
|
|
|
|
0
|
_pushErrors( |
|
269
|
|
|
|
|
|
|
"Invalid name for the long option ($$tref{Long})"); |
|
270
|
0
|
|
|
|
|
0
|
$rv = 0; |
|
271
|
|
|
|
|
|
|
} |
|
272
|
|
|
|
|
|
|
} |
|
273
|
|
|
|
|
|
|
} |
|
274
|
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
# Make sure '@' is only used once, if at all, and the option isn't |
|
276
|
|
|
|
|
|
|
# set to allow bundling |
|
277
|
108
|
50
|
|
|
|
159
|
if ($rv) { |
|
278
|
108
|
100
|
|
|
|
196
|
if ( $$tref{Template} =~ /\@/sm ) { |
|
279
|
26
|
|
|
|
|
63
|
@at = ( $$tref{Template} =~ m#(\@)#sg ); |
|
280
|
26
|
50
|
|
|
|
57
|
if ( @at > 1 ) { |
|
281
|
0
|
|
|
|
|
0
|
_pushErrors( 'The \'@\' symbol can only be used once in the ' |
|
282
|
|
|
|
|
|
|
. "template for $oname: $_" ); |
|
283
|
0
|
|
|
|
|
0
|
$rv = 0; |
|
284
|
|
|
|
|
|
|
} |
|
285
|
26
|
50
|
33
|
|
|
55
|
if ( $$tref{CanBundle} and defined $$tref{Short} ) { |
|
286
|
0
|
|
|
|
|
0
|
_pushErrors( |
|
287
|
|
|
|
|
|
|
"Option $$tref{Short} must have CanBundle set to false " |
|
288
|
|
|
|
|
|
|
. 'if the template contains \'@\'' ); |
|
289
|
0
|
|
|
|
|
0
|
$rv = 0; |
|
290
|
|
|
|
|
|
|
} |
|
291
|
|
|
|
|
|
|
} |
|
292
|
|
|
|
|
|
|
} |
|
293
|
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
# Make sure all values in our lists are defined |
|
295
|
108
|
50
|
|
|
|
146
|
if ($rv) { |
|
296
|
108
|
50
|
|
|
|
193
|
unless ( ref( $$tref{ExclusiveOf} ) eq 'ARRAY' ) { |
|
297
|
0
|
|
|
|
|
0
|
_pushErrors( "Option ${oname}'s parameter ExclusiveOf must be an " |
|
298
|
|
|
|
|
|
|
. 'array reference' ); |
|
299
|
0
|
|
|
|
|
0
|
$rv = 0; |
|
300
|
|
|
|
|
|
|
} |
|
301
|
108
|
50
|
|
|
|
167
|
unless ( ref( $$tref{AccompaniedBy} ) eq 'ARRAY' ) { |
|
302
|
0
|
|
|
|
|
0
|
_pushErrors( |
|
303
|
|
|
|
|
|
|
"Option ${oname}'s parameter AccompaniedBy must be an " |
|
304
|
|
|
|
|
|
|
. 'array reference' ); |
|
305
|
0
|
|
|
|
|
0
|
$rv = 0; |
|
306
|
|
|
|
|
|
|
} |
|
307
|
108
|
50
|
|
|
|
143
|
if ($rv) { |
|
308
|
108
|
50
|
|
|
|
109
|
if ( grep { !defined } @{ $$tref{ExclusiveOf} } ) { |
|
|
26
|
|
|
|
|
53
|
|
|
|
108
|
|
|
|
|
203
|
|
|
309
|
0
|
|
|
|
|
0
|
_pushErrors( |
|
310
|
|
|
|
|
|
|
"Option $oname has undefined values in ExclusiveOf"); |
|
311
|
0
|
|
|
|
|
0
|
$rv = 0; |
|
312
|
|
|
|
|
|
|
} |
|
313
|
108
|
50
|
|
|
|
123
|
if ( grep { !defined } @{ $$tref{AccompaniedBy} } ) { |
|
|
26
|
|
|
|
|
72
|
|
|
|
108
|
|
|
|
|
180
|
|
|
314
|
0
|
|
|
|
|
0
|
_pushErrors( |
|
315
|
|
|
|
|
|
|
"Option $oname has undefined values in ExclusiveOf"); |
|
316
|
0
|
|
|
|
|
0
|
$rv = 0; |
|
317
|
|
|
|
|
|
|
} |
|
318
|
|
|
|
|
|
|
} |
|
319
|
|
|
|
|
|
|
} |
|
320
|
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
# Make sure CountShort is enabled only for those with a template of '' |
|
322
|
|
|
|
|
|
|
# or '$' |
|
323
|
108
|
50
|
|
|
|
139
|
if ($rv) { |
|
324
|
|
|
|
|
|
|
|
|
325
|
108
|
100
|
|
|
|
160
|
if ( $$tref{CountShort} ) { |
|
326
|
15
|
50
|
|
|
|
36
|
unless ( $$tref{Template} =~ /^\$?$/sm ) { |
|
327
|
0
|
|
|
|
|
0
|
_pushErrors( "Option $oname has CountShort set but with an " |
|
328
|
|
|
|
|
|
|
. 'incompatible template' ); |
|
329
|
0
|
|
|
|
|
0
|
$rv = 0; |
|
330
|
|
|
|
|
|
|
} |
|
331
|
|
|
|
|
|
|
} |
|
332
|
|
|
|
|
|
|
} |
|
333
|
|
|
|
|
|
|
|
|
334
|
108
|
|
|
|
|
221
|
subPostamble( PDLEVEL2, '$', $rv ); |
|
335
|
|
|
|
|
|
|
|
|
336
|
108
|
|
|
|
|
221
|
return $rv; |
|
337
|
|
|
|
|
|
|
} |
|
338
|
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
sub _getArgs ($$\@) { |
|
340
|
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
# Purpose: Takes passed argument template and extracts the requisite |
|
342
|
|
|
|
|
|
|
# arguments to satisfy it from the argument list. The |
|
343
|
|
|
|
|
|
|
# results are stored in the passed option list. |
|
344
|
|
|
|
|
|
|
# Results: True (1) if successful, False (0) if not |
|
345
|
|
|
|
|
|
|
# Usage: $rv = _getArgs($option, $argTemplate, @optionArgs); |
|
346
|
|
|
|
|
|
|
|
|
347
|
36
|
|
|
36
|
|
41
|
my $option = shift; # Option name |
|
348
|
36
|
|
|
|
|
37
|
my $argTemplate = shift; # Option argument template |
|
349
|
36
|
|
|
|
|
37
|
my $lref = shift; # Array reference for retrieved arguments |
|
350
|
36
|
|
|
|
|
42
|
my $rv = 1; |
|
351
|
36
|
|
|
|
|
42
|
my $argRef = _getArgRef(); |
|
352
|
36
|
|
|
|
|
37
|
my @tmp; |
|
353
|
|
|
|
|
|
|
|
|
354
|
36
|
|
|
|
|
75
|
subPreamble( PDLEVEL2, '$$$', $option, $argTemplate, $lref ); |
|
355
|
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
# Empty the array |
|
357
|
36
|
|
|
|
|
45
|
@$lref = (); |
|
358
|
|
|
|
|
|
|
|
|
359
|
36
|
|
|
|
|
78
|
pdebug( 'contents of args: %s', PDLEVEL4, @$argRef ); |
|
360
|
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
# Start checking the contents of $argTemplate |
|
362
|
36
|
100
|
|
|
|
90
|
if ( $argTemplate eq '' ) { |
|
|
|
100
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
# Template is '' (boolean option) |
|
365
|
17
|
|
|
|
|
21
|
@$lref = (1); |
|
366
|
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
} elsif ( $argTemplate =~ /\@/s ) { |
|
368
|
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
# Template has a '@' in it -- we'll need to |
|
370
|
|
|
|
|
|
|
# grab as many of the next arguments as possible. |
|
371
|
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
# Check the noOptions flags |
|
373
|
5
|
50
|
|
|
|
8
|
if (_NOOPTIONS) { |
|
374
|
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
# True: gobble up everything left |
|
376
|
0
|
|
|
|
|
0
|
push @$lref, @$argRef; |
|
377
|
0
|
|
|
|
|
0
|
@$argRef = (); |
|
378
|
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
} else { |
|
380
|
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
# False: gobble up to the next option-looking thing |
|
382
|
5
|
|
100
|
|
|
44
|
while ( @$argRef and $$argRef[0] !~ /^--?(?:\w+.*)?$/s ) { |
|
383
|
18
|
|
|
|
|
54
|
push @$lref, shift @$argRef; |
|
384
|
|
|
|
|
|
|
} |
|
385
|
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
# Now, we check to see if the first remaining argument is '--'. |
|
387
|
|
|
|
|
|
|
# If it is then we must set noOptions to true and gobble the |
|
388
|
|
|
|
|
|
|
# rest. |
|
389
|
5
|
100
|
100
|
|
|
15
|
if ( @$argRef and $$argRef[0] eq '--' ) { |
|
390
|
1
|
|
|
|
|
3
|
_NOOPTIONS = 1; |
|
391
|
1
|
|
|
|
|
2
|
shift @$argRef; |
|
392
|
1
|
|
|
|
|
2
|
push @$lref, @$argRef; |
|
393
|
1
|
|
|
|
|
2
|
@$argRef = (); |
|
394
|
|
|
|
|
|
|
} |
|
395
|
|
|
|
|
|
|
} |
|
396
|
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
} else { |
|
398
|
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
# The template is not empty and has no '@', so we'll just grab the next |
|
400
|
|
|
|
|
|
|
# n arguments, n being the length of the template |
|
401
|
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
# Check the noOptions flag |
|
403
|
14
|
50
|
|
|
|
21
|
if (_NOOPTIONS) { |
|
404
|
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
# True: grab everything we need |
|
406
|
0
|
|
0
|
|
|
0
|
while ( @$argRef and @$lref < length $argTemplate ) { |
|
407
|
0
|
|
|
|
|
0
|
push @$lref, shift @$argRef; |
|
408
|
|
|
|
|
|
|
} |
|
409
|
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
} else { |
|
411
|
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
# False: grab as many non-option-looking things as we can |
|
413
|
14
|
|
100
|
|
|
396
|
while ( @$argRef |
|
|
|
|
100
|
|
|
|
|
|
414
|
|
|
|
|
|
|
and $$argRef[0] !~ /^--?(?:\w+.*)$/s |
|
415
|
|
|
|
|
|
|
and @$lref < length $argTemplate ) { |
|
416
|
14
|
|
|
|
|
59
|
push @$lref, shift @$argRef; |
|
417
|
|
|
|
|
|
|
} |
|
418
|
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
# Now, we check to see if we still need more arguments and if |
|
420
|
|
|
|
|
|
|
# the first remaining argument is '--'. If it is then we must |
|
421
|
|
|
|
|
|
|
# set noOptions to true and gobble what we need. |
|
422
|
14
|
0
|
33
|
|
|
36
|
if ( @$lref < length $argTemplate |
|
|
|
|
33
|
|
|
|
|
|
423
|
|
|
|
|
|
|
and @$argRef |
|
424
|
|
|
|
|
|
|
and $$argRef[0] eq '--' ) { |
|
425
|
0
|
|
|
|
|
0
|
_NOOPTIONS = 1; |
|
426
|
0
|
|
|
|
|
0
|
shift @$argRef; |
|
427
|
0
|
|
0
|
|
|
0
|
while ( @$argRef and @$lref < length $argTemplate ) { |
|
428
|
0
|
|
|
|
|
0
|
push @$lref, shift @$argRef; |
|
429
|
|
|
|
|
|
|
} |
|
430
|
|
|
|
|
|
|
} |
|
431
|
|
|
|
|
|
|
} |
|
432
|
|
|
|
|
|
|
} |
|
433
|
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
# Final check: did we get minimum requisite number of arguments? |
|
435
|
36
|
100
|
|
|
|
59
|
if ( @$lref < length $argTemplate ) { |
|
436
|
1
|
|
|
|
|
3
|
_pushErrors( |
|
437
|
|
|
|
|
|
|
pdebug( |
|
438
|
|
|
|
|
|
|
'Missing the minimum number of arguments for %s', PDLEVEL1, |
|
439
|
|
|
|
|
|
|
$option |
|
440
|
|
|
|
|
|
|
) ); |
|
441
|
1
|
|
|
|
|
29
|
$rv = 0; |
|
442
|
|
|
|
|
|
|
} else { |
|
443
|
35
|
|
|
|
|
56
|
pdebug( 'extracted the following arguments: %s', PDLEVEL3, @$lref ); |
|
444
|
|
|
|
|
|
|
} |
|
445
|
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
# sublist '@' portions of multicharacter templates |
|
447
|
36
|
100
|
100
|
|
|
117
|
if ( $rv and $argTemplate =~ /\@/sm and length $argTemplate > 1 ) { |
|
|
|
|
66
|
|
|
|
|
|
448
|
4
|
|
|
|
|
9
|
@tmp = ( [], [], [] ); |
|
449
|
|
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
# First, shift off all preceding '$'s |
|
451
|
4
|
50
|
|
|
|
10
|
if ( $argTemplate =~ /^(\$+)/s ) { |
|
452
|
4
|
|
|
|
|
11
|
@{ $tmp[0] } = splice @$lref, 0, length $1; |
|
|
4
|
|
|
|
|
6
|
|
|
453
|
|
|
|
|
|
|
} |
|
454
|
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
# Next, pop off all trailing '$' |
|
456
|
4
|
100
|
|
|
|
12
|
if ( $argTemplate =~ /(\$+)\$/s ) { |
|
457
|
2
|
|
|
|
|
5
|
@{ $tmp[2] } = splice @$lref, -1 * length $1; |
|
|
2
|
|
|
|
|
3
|
|
|
458
|
|
|
|
|
|
|
} |
|
459
|
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
# Everything left belongs to the '@' |
|
461
|
4
|
|
|
|
|
6
|
@{ $tmp[1] } = @$lref; |
|
|
4
|
|
|
|
|
7
|
|
|
462
|
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
# Let's put it all together... |
|
464
|
4
|
|
|
|
|
6
|
@$lref = (); |
|
465
|
4
|
50
|
|
|
|
3
|
push @$lref, @{ $tmp[0] } if @{ $tmp[0] }; |
|
|
4
|
|
|
|
|
6
|
|
|
|
4
|
|
|
|
|
9
|
|
|
466
|
4
|
|
|
|
|
4
|
push @$lref, $tmp[1]; |
|
467
|
4
|
100
|
|
|
|
5
|
push @$lref, @{ $tmp[2] } if @{ $tmp[2] }; |
|
|
2
|
|
|
|
|
2
|
|
|
|
4
|
|
|
|
|
7
|
|
|
468
|
|
|
|
|
|
|
|
|
469
|
4
|
|
|
|
|
7
|
pdebug( 'sublisted arguments into: %s', PDLEVEL3, @$lref ); |
|
470
|
|
|
|
|
|
|
} |
|
471
|
|
|
|
|
|
|
|
|
472
|
36
|
|
|
|
|
74
|
subPostamble( PDLEVEL2, '$', $rv ); |
|
473
|
|
|
|
|
|
|
|
|
474
|
36
|
|
|
|
|
69
|
return $rv; |
|
475
|
|
|
|
|
|
|
} |
|
476
|
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
sub _storeArgs ($$\@) { |
|
478
|
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
# Purpose: Stores the passed option arguments in the passed option |
|
480
|
|
|
|
|
|
|
# template's Value, but in accordance with parameters in the |
|
481
|
|
|
|
|
|
|
# template |
|
482
|
|
|
|
|
|
|
# Returns: True (1) |
|
483
|
|
|
|
|
|
|
# Usage: _storeArgs($optionTemplate, $argTemplate, @optionArgs); |
|
484
|
|
|
|
|
|
|
|
|
485
|
35
|
|
|
35
|
|
43
|
my $tref = shift; |
|
486
|
35
|
|
|
|
|
40
|
my $argTemplate = shift; |
|
487
|
35
|
|
|
|
|
33
|
my $lref = shift; |
|
488
|
|
|
|
|
|
|
|
|
489
|
35
|
|
|
|
|
69
|
subPreamble( PDLEVEL2, '$$$', $tref, $argTemplate, $lref ); |
|
490
|
|
|
|
|
|
|
|
|
491
|
35
|
|
|
|
|
73
|
pdebug( 'adding values to %s', PDLEVEL3, $$tref{Name} ); |
|
492
|
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
# Increment our usage counter |
|
494
|
35
|
|
|
|
|
51
|
$$tref{Count}++; |
|
495
|
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
# Store arguments according to the template |
|
497
|
35
|
100
|
|
|
|
55
|
if ( $argTemplate eq '' ) { |
|
|
|
100
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
# Template is '' |
|
500
|
17
|
100
|
|
|
|
29
|
$$tref{Value} = 0 unless defined $$tref{Value}; |
|
501
|
17
|
|
|
|
|
20
|
$$tref{Value}++; |
|
502
|
17
|
|
|
|
|
28
|
pdebug( 'Value is now %s', PDLEVEL3, $$tref{Value} ); |
|
503
|
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
} elsif ( $argTemplate eq '$' ) { |
|
505
|
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
# Template is '$' |
|
507
|
14
|
100
|
100
|
|
|
56
|
if ( not $$tref{Multiple} or $$tref{CountShort} ) { |
|
508
|
|
|
|
|
|
|
|
|
509
|
|
|
|
|
|
|
# Store the value directly since we |
|
510
|
|
|
|
|
|
|
# can only be used once |
|
511
|
12
|
|
|
|
|
19
|
$$tref{Value} = $$lref[0]; |
|
512
|
12
|
|
|
|
|
22
|
pdebug( 'Value is now %s', PDLEVEL3, $$tref{Value} ); |
|
513
|
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
} else { |
|
515
|
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
# Store the value as part of a list since |
|
517
|
|
|
|
|
|
|
# we can be used multiple times |
|
518
|
|
|
|
|
|
|
$$tref{Value} = [] |
|
519
|
|
|
|
|
|
|
unless defined $$tref{Value} |
|
520
|
2
|
100
|
66
|
|
|
9
|
and ref $$tref{Value} eq 'ARRAY'; |
|
521
|
2
|
|
|
|
|
3
|
push @{ $$tref{Value} }, $$lref[0]; |
|
|
2
|
|
|
|
|
4
|
|
|
522
|
2
|
|
|
|
|
3
|
pdebug( 'Value is now %s', PDLEVEL3, @{ $$tref{Value} } ); |
|
|
2
|
|
|
|
|
4
|
|
|
523
|
|
|
|
|
|
|
} |
|
524
|
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
} else { |
|
526
|
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
# Template is anything else |
|
528
|
4
|
50
|
|
|
|
9
|
if ( not $$tref{Multiple} ) { |
|
529
|
|
|
|
|
|
|
|
|
530
|
|
|
|
|
|
|
# Store the values directly in a an array |
|
531
|
|
|
|
|
|
|
# since we can only be used once |
|
532
|
4
|
|
|
|
|
6
|
$$tref{Value} = [@$lref]; |
|
533
|
4
|
|
|
|
|
7
|
pdebug( 'Value is now %s', PDLEVEL3, @{ $$tref{Value} } ); |
|
|
4
|
|
|
|
|
9
|
|
|
534
|
|
|
|
|
|
|
|
|
535
|
|
|
|
|
|
|
} else { |
|
536
|
|
|
|
|
|
|
|
|
537
|
|
|
|
|
|
|
# Store the values as an element of an |
|
538
|
|
|
|
|
|
|
# array since we can be used multiple times |
|
539
|
|
|
|
|
|
|
$$tref{Value} = [] |
|
540
|
|
|
|
|
|
|
unless defined $$tref{Value} |
|
541
|
0
|
0
|
0
|
|
|
0
|
and ref $$tref{Value} eq 'ARRAY'; |
|
542
|
0
|
|
|
|
|
0
|
push @{ $$tref{Value} }, [@$lref]; |
|
|
0
|
|
|
|
|
0
|
|
|
543
|
|
|
|
|
|
|
pdebug( 'Value now has %d sets', |
|
544
|
0
|
|
|
|
|
0
|
PDLEVEL3, scalar @{ $$tref{Value} } ); |
|
|
0
|
|
|
|
|
0
|
|
|
545
|
|
|
|
|
|
|
} |
|
546
|
|
|
|
|
|
|
} |
|
547
|
|
|
|
|
|
|
|
|
548
|
35
|
|
|
|
|
70
|
subPostamble( PDLEVEL1, '$', 1 ); |
|
549
|
|
|
|
|
|
|
|
|
550
|
35
|
|
|
|
|
78
|
return 1; |
|
551
|
|
|
|
|
|
|
} |
|
552
|
|
|
|
|
|
|
|
|
553
|
|
|
|
|
|
|
sub parseArgs (\@\%;\@) { |
|
554
|
|
|
|
|
|
|
|
|
555
|
|
|
|
|
|
|
# Purpose: Extracts and validates all command-line arguments and options, |
|
556
|
|
|
|
|
|
|
# storing them in an organized hash for easy retrieval |
|
557
|
|
|
|
|
|
|
# Returns: True (1) if successful, False (0) if not |
|
558
|
|
|
|
|
|
|
# Usage: $rv = parseArgs(@templates, %options); |
|
559
|
|
|
|
|
|
|
# Usage: $rv = parseArgs(@templates, %options, @args); |
|
560
|
|
|
|
|
|
|
|
|
561
|
14
|
|
|
14
|
1
|
2460
|
my $tlref = shift; # Templates list ref |
|
562
|
14
|
|
|
|
|
17
|
my $oref = shift; # Options hash ref |
|
563
|
14
|
|
|
|
|
14
|
my $paref = shift; # Program argument list ref |
|
564
|
14
|
|
|
|
|
14
|
my $rv = 1; |
|
565
|
14
|
|
|
|
|
29
|
my ( $tref, $oname, $argRef, $arg, $argTemplate ); |
|
566
|
14
|
|
|
|
|
0
|
my ( @tmp, @oargs, $regex ); |
|
567
|
|
|
|
|
|
|
|
|
568
|
14
|
|
|
|
|
36
|
subPreamble( PDLEVEL1, '$$$', $tlref, $oref, $paref ); |
|
569
|
|
|
|
|
|
|
|
|
570
|
|
|
|
|
|
|
# Validate arguments |
|
571
|
14
|
50
|
|
|
|
25
|
$paref = \@ARGV unless defined $paref; |
|
572
|
|
|
|
|
|
|
|
|
573
|
|
|
|
|
|
|
# Clear all internal data structures and reset flag |
|
574
|
14
|
|
|
|
|
22
|
clearMemory(); |
|
575
|
|
|
|
|
|
|
|
|
576
|
|
|
|
|
|
|
# Empty the passed options hash |
|
577
|
14
|
|
|
|
|
26
|
%$oref = (); |
|
578
|
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
# Make a copy of the argument list |
|
580
|
14
|
|
|
|
|
15
|
$argRef = _getArgRef(); |
|
581
|
14
|
|
|
|
|
28
|
@$argRef = (@$paref); |
|
582
|
|
|
|
|
|
|
|
|
583
|
|
|
|
|
|
|
# Assemble %options and lint-check the templates |
|
584
|
14
|
|
|
|
|
25
|
foreach (@$tlref) { |
|
585
|
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
# Make sure the element is a hash reference |
|
587
|
108
|
50
|
|
|
|
182
|
unless ( ref $_ eq 'HASH' ) { |
|
588
|
0
|
|
|
|
|
0
|
_pushErrors('Illegal non-hash reference in templates array'); |
|
589
|
0
|
|
|
|
|
0
|
$rv = 0; |
|
590
|
0
|
|
|
|
|
0
|
next; |
|
591
|
|
|
|
|
|
|
} |
|
592
|
|
|
|
|
|
|
|
|
593
|
|
|
|
|
|
|
# Establish a base template and copy the contents of the passed hash |
|
594
|
|
|
|
|
|
|
$tref = { |
|
595
|
108
|
|
|
|
|
562
|
Short => undef, |
|
596
|
|
|
|
|
|
|
Long => undef, |
|
597
|
|
|
|
|
|
|
Template => '', |
|
598
|
|
|
|
|
|
|
Multiple => 0, |
|
599
|
|
|
|
|
|
|
ExclusiveOf => [], |
|
600
|
|
|
|
|
|
|
AccompaniedBy => [], |
|
601
|
|
|
|
|
|
|
CanBundle => 0, |
|
602
|
|
|
|
|
|
|
CountShort => 0, |
|
603
|
|
|
|
|
|
|
Value => undef, |
|
604
|
|
|
|
|
|
|
%$_, |
|
605
|
|
|
|
|
|
|
}; |
|
606
|
|
|
|
|
|
|
|
|
607
|
|
|
|
|
|
|
# Set AllOptions for error message reporting |
|
608
|
|
|
|
|
|
|
$$tref{Name} = |
|
609
|
|
|
|
|
|
|
defined $$tref{Short} |
|
610
|
|
|
|
|
|
|
&& defined $$tref{Long} ? "-$$tref{Short}/--$$tref{Long}" |
|
611
|
|
|
|
|
|
|
: defined $$tref{Short} ? "-$$tref{Short}" |
|
612
|
108
|
50
|
66
|
|
|
493
|
: defined $$tref{Long} ? "--$$tref{Long}" |
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
613
|
|
|
|
|
|
|
: undef; |
|
614
|
|
|
|
|
|
|
|
|
615
|
|
|
|
|
|
|
# Initialize our usage counter |
|
616
|
108
|
|
|
|
|
155
|
$$tref{Count} = 0; |
|
617
|
|
|
|
|
|
|
|
|
618
|
|
|
|
|
|
|
# Anything that has CountShort enabled implies Multiple/CanBundle |
|
619
|
|
|
|
|
|
|
# and a template of '$' |
|
620
|
108
|
100
|
|
|
|
165
|
if ( $$tref{CountShort} ) { |
|
621
|
15
|
|
|
|
|
21
|
$$tref{CanBundle} = $$tref{Multiple} = 1; |
|
622
|
15
|
50
|
|
|
|
26
|
$$tref{Template} = '$' if defined $$tref{Long}; |
|
623
|
|
|
|
|
|
|
} |
|
624
|
|
|
|
|
|
|
|
|
625
|
|
|
|
|
|
|
# Anything that has a Short option and a template of '$' or '' |
|
626
|
|
|
|
|
|
|
# implies CanBundle |
|
627
|
|
|
|
|
|
|
$$tref{CanBundle} = 1 |
|
628
|
108
|
100
|
100
|
|
|
252
|
if defined $$tref{Short} and $$tref{Template} eq ''; |
|
629
|
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
# We'll associate both the long and short options to the same hash |
|
631
|
|
|
|
|
|
|
# to make sure that we count/collect everything appropriately. |
|
632
|
|
|
|
|
|
|
# |
|
633
|
|
|
|
|
|
|
# Store the short option |
|
634
|
108
|
100
|
66
|
|
|
254
|
if ( defined $$tref{Short} and length $$tref{Short} ) { |
|
635
|
|
|
|
|
|
|
|
|
636
|
|
|
|
|
|
|
# See if a template is already defined |
|
637
|
95
|
50
|
|
|
|
143
|
if ( defined _getOption( $$tref{Short} ) ) { |
|
638
|
|
|
|
|
|
|
|
|
639
|
|
|
|
|
|
|
# It is -- report the error |
|
640
|
|
|
|
|
|
|
Paranoid::ERROR = _pushErrors( |
|
641
|
|
|
|
|
|
|
pdebug( |
|
642
|
|
|
|
|
|
|
'the %s option has more than one template', |
|
643
|
0
|
|
|
|
|
0
|
PDLEVEL1, $$tref{Short} ) ); |
|
644
|
0
|
|
|
|
|
0
|
$rv = 0; |
|
645
|
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
} else { |
|
647
|
|
|
|
|
|
|
|
|
648
|
|
|
|
|
|
|
# It's not -- go ahead and store it |
|
649
|
95
|
|
|
|
|
133
|
_setOption( $$tref{Short}, $tref ); |
|
650
|
|
|
|
|
|
|
} |
|
651
|
|
|
|
|
|
|
} |
|
652
|
|
|
|
|
|
|
|
|
653
|
|
|
|
|
|
|
# Store the long option |
|
654
|
108
|
50
|
33
|
|
|
273
|
if ( defined $$tref{Long} and length $$tref{Long} ) { |
|
655
|
|
|
|
|
|
|
|
|
656
|
|
|
|
|
|
|
# See if a template is already defined |
|
657
|
108
|
50
|
|
|
|
141
|
if ( defined _getOption( $$tref{Long} ) ) { |
|
658
|
|
|
|
|
|
|
|
|
659
|
|
|
|
|
|
|
# It is -- report the error |
|
660
|
|
|
|
|
|
|
Paranoid::ERROR = _pushErrors( |
|
661
|
|
|
|
|
|
|
pdebug( |
|
662
|
|
|
|
|
|
|
'the %s option has more than one template', |
|
663
|
0
|
|
|
|
|
0
|
PDLEVEL1, $$tref{Long} ) ); |
|
664
|
0
|
|
|
|
|
0
|
$rv = 0; |
|
665
|
|
|
|
|
|
|
|
|
666
|
|
|
|
|
|
|
} else { |
|
667
|
|
|
|
|
|
|
|
|
668
|
|
|
|
|
|
|
# It's not -- go ahead and store it |
|
669
|
108
|
|
|
|
|
160
|
_setOption( $$tref{Long}, $tref ); |
|
670
|
|
|
|
|
|
|
} |
|
671
|
|
|
|
|
|
|
} |
|
672
|
|
|
|
|
|
|
|
|
673
|
|
|
|
|
|
|
# Do a basic lint-check on the template |
|
674
|
108
|
50
|
|
|
|
127
|
$rv = 0 unless _tLint($tref); |
|
675
|
|
|
|
|
|
|
} |
|
676
|
|
|
|
|
|
|
|
|
677
|
14
|
50
|
|
|
|
25
|
if ($rv) { |
|
678
|
|
|
|
|
|
|
|
|
679
|
14
|
|
|
|
|
20
|
while (@$argRef) { |
|
680
|
35
|
|
|
|
|
47
|
$arg = shift @$argRef; |
|
681
|
35
|
50
|
|
|
|
57
|
next unless defined $arg; |
|
682
|
|
|
|
|
|
|
|
|
683
|
|
|
|
|
|
|
# Start testing $arg |
|
684
|
35
|
100
|
66
|
|
|
70
|
if ( $arg eq '--' and not _NOOPTIONS ) { |
|
|
|
100
|
100
|
|
|
|
|
|
685
|
|
|
|
|
|
|
|
|
686
|
|
|
|
|
|
|
# $arg is '--', so set the no options flag |
|
687
|
1
|
|
|
|
|
2
|
_NOOPTIONS = 1; |
|
688
|
|
|
|
|
|
|
|
|
689
|
|
|
|
|
|
|
} elsif ( not _NOOPTIONS and $arg =~ /^--?/s ) { |
|
690
|
|
|
|
|
|
|
|
|
691
|
|
|
|
|
|
|
# '--' hasn't been passed yet and this looks |
|
692
|
|
|
|
|
|
|
# like an option... |
|
693
|
|
|
|
|
|
|
|
|
694
|
|
|
|
|
|
|
# Test types of options |
|
695
|
27
|
100
|
|
|
|
88
|
if ( $arg =~ /^-(\w.*)$/s ) { |
|
|
|
50
|
|
|
|
|
|
|
696
|
|
|
|
|
|
|
|
|
697
|
|
|
|
|
|
|
# With a single '-' it should be a short option. However, |
|
698
|
|
|
|
|
|
|
# we'll split the option portion, in case there's more |
|
699
|
|
|
|
|
|
|
# than one character |
|
700
|
14
|
|
|
|
|
42
|
@tmp = split //s, $1; |
|
701
|
|
|
|
|
|
|
|
|
702
|
|
|
|
|
|
|
# If there's more than one character for the option name |
|
703
|
|
|
|
|
|
|
# it must be either a bunch of bundled options or an |
|
704
|
|
|
|
|
|
|
# option with a concatenated argument. In case of the |
|
705
|
|
|
|
|
|
|
# latter (assuming that CanBundle is set to false (a |
|
706
|
|
|
|
|
|
|
# prerequisite of argument concatenation) and it has a |
|
707
|
|
|
|
|
|
|
# template of '$' (another prerequisite)) we'll unshift |
|
708
|
|
|
|
|
|
|
# the rest of the characters back onto the argument list. |
|
709
|
|
|
|
|
|
|
# |
|
710
|
|
|
|
|
|
|
# Oh, but first we'll need to get the applicable |
|
711
|
|
|
|
|
|
|
# option template and then start testing... |
|
712
|
14
|
|
|
|
|
22
|
$tref = _getOption( $tmp[0] ); |
|
713
|
14
|
100
|
66
|
|
|
73
|
if ( $#tmp |
|
|
|
|
66
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
714
|
|
|
|
|
|
|
and defined $tref |
|
715
|
|
|
|
|
|
|
and $$tref{Template} eq '$' |
|
716
|
|
|
|
|
|
|
and not $$tref{CanBundle} ) { |
|
717
|
3
|
|
|
|
|
11
|
unshift @$argRef, join '', @tmp[ 1 .. $#tmp ]; |
|
718
|
3
|
|
|
|
|
6
|
splice @tmp, 1; |
|
719
|
|
|
|
|
|
|
} |
|
720
|
|
|
|
|
|
|
|
|
721
|
|
|
|
|
|
|
# Start processing all remaining short options in @tmp |
|
722
|
14
|
|
|
|
|
24
|
foreach (@tmp) { |
|
723
|
|
|
|
|
|
|
|
|
724
|
|
|
|
|
|
|
# Get the template |
|
725
|
25
|
|
|
|
|
33
|
$tref = _getOption($_); |
|
726
|
|
|
|
|
|
|
|
|
727
|
|
|
|
|
|
|
# Make sure the option is supported |
|
728
|
25
|
50
|
|
|
|
40
|
if ( defined $tref ) { |
|
729
|
|
|
|
|
|
|
|
|
730
|
|
|
|
|
|
|
# Make sure option allows bundling if bundled |
|
731
|
25
|
100
|
|
|
|
31
|
if ($#tmp) { |
|
732
|
16
|
50
|
|
|
|
28
|
unless ( $$tref{CanBundle} ) { |
|
733
|
0
|
|
|
|
|
0
|
_pushErrors( |
|
734
|
|
|
|
|
|
|
"Option $_ used bundled with " |
|
735
|
|
|
|
|
|
|
. 'other options' ); |
|
736
|
0
|
|
|
|
|
0
|
$rv = 0; |
|
737
|
0
|
|
|
|
|
0
|
next; |
|
738
|
|
|
|
|
|
|
} |
|
739
|
|
|
|
|
|
|
} |
|
740
|
|
|
|
|
|
|
|
|
741
|
|
|
|
|
|
|
# Get the argument template |
|
742
|
25
|
|
|
|
|
36
|
$argTemplate = $$tref{Template}; |
|
743
|
|
|
|
|
|
|
|
|
744
|
|
|
|
|
|
|
# Override the template if CountShort is true |
|
745
|
|
|
|
|
|
|
$argTemplate = '' |
|
746
|
|
|
|
|
|
|
if $argTemplate eq '$' |
|
747
|
25
|
100
|
100
|
|
|
70
|
and $$tref{CountShort}; |
|
748
|
|
|
|
|
|
|
|
|
749
|
|
|
|
|
|
|
# Get any accompanying arguments |
|
750
|
25
|
50
|
|
|
|
50
|
unless ( _getArgs( "-$_", $argTemplate, @oargs ) ) |
|
751
|
|
|
|
|
|
|
{ |
|
752
|
0
|
|
|
|
|
0
|
$rv = 0; |
|
753
|
0
|
|
|
|
|
0
|
next; |
|
754
|
|
|
|
|
|
|
} |
|
755
|
|
|
|
|
|
|
|
|
756
|
|
|
|
|
|
|
# Check if we've call this more than once |
|
757
|
25
|
50
|
66
|
|
|
64
|
if ( not $$tref{Multiple} |
|
758
|
|
|
|
|
|
|
and $$tref{Count} > 0 ) { |
|
759
|
0
|
|
|
|
|
0
|
_pushErrors( |
|
760
|
|
|
|
|
|
|
"Option $$tref{Name} is only allowed " |
|
761
|
|
|
|
|
|
|
. 'to be used once' ); |
|
762
|
0
|
|
|
|
|
0
|
$rv = 0; |
|
763
|
0
|
|
|
|
|
0
|
next; |
|
764
|
|
|
|
|
|
|
} |
|
765
|
|
|
|
|
|
|
|
|
766
|
|
|
|
|
|
|
# Store the values |
|
767
|
25
|
|
|
|
|
42
|
_storeArgs( $tref, $argTemplate, @oargs ); |
|
768
|
|
|
|
|
|
|
|
|
769
|
|
|
|
|
|
|
} else { |
|
770
|
|
|
|
|
|
|
|
|
771
|
|
|
|
|
|
|
# Warn that this is an unknown option |
|
772
|
0
|
|
|
|
|
0
|
_pushErrors("Unknown short option used: $_"); |
|
773
|
0
|
|
|
|
|
0
|
$rv = 0; |
|
774
|
|
|
|
|
|
|
} |
|
775
|
|
|
|
|
|
|
} |
|
776
|
|
|
|
|
|
|
|
|
777
|
|
|
|
|
|
|
} elsif ( $arg =~ /^--([\w-]+)(?:=(.+))?$/sm ) { |
|
778
|
|
|
|
|
|
|
|
|
779
|
|
|
|
|
|
|
# Starts with '--', so must be a long option |
|
780
|
|
|
|
|
|
|
|
|
781
|
|
|
|
|
|
|
# Save the extracted option/argument portion |
|
782
|
13
|
|
|
|
|
32
|
@tmp = ($1); |
|
783
|
13
|
100
|
66
|
|
|
36
|
push @tmp, $2 if defined $2 and length $2; |
|
784
|
|
|
|
|
|
|
|
|
785
|
|
|
|
|
|
|
# If this option had an argument portion we need to |
|
786
|
|
|
|
|
|
|
# unshift it back onto the argument list *provided* it was |
|
787
|
|
|
|
|
|
|
# a legal argument, i.e., this option had a template of |
|
788
|
|
|
|
|
|
|
# '$'. |
|
789
|
13
|
|
|
|
|
21
|
$tref = _getOption( $tmp[0] ); |
|
790
|
13
|
100
|
66
|
|
|
27
|
if ( $#tmp and defined $tref ) { |
|
791
|
|
|
|
|
|
|
|
|
792
|
|
|
|
|
|
|
# Test for various templates |
|
793
|
1
|
50
|
|
|
|
3
|
if ( $$tref{Template} eq '$' ) { |
|
|
|
0
|
|
|
|
|
|
|
794
|
|
|
|
|
|
|
|
|
795
|
|
|
|
|
|
|
# Legal invocation -- unshift away |
|
796
|
1
|
|
|
|
|
3
|
unshift @$argRef, $tmp[1]; |
|
797
|
|
|
|
|
|
|
|
|
798
|
|
|
|
|
|
|
} elsif ( $$tref{Template} eq '' ) { |
|
799
|
|
|
|
|
|
|
|
|
800
|
|
|
|
|
|
|
# Illegal, no arguments expected |
|
801
|
0
|
|
|
|
|
0
|
_pushErrors( "--$tmp[0] does not require any " |
|
802
|
|
|
|
|
|
|
. 'arguments' ); |
|
803
|
0
|
|
|
|
|
0
|
$rv = 0; |
|
804
|
0
|
|
|
|
|
0
|
next; |
|
805
|
|
|
|
|
|
|
|
|
806
|
|
|
|
|
|
|
} else { |
|
807
|
|
|
|
|
|
|
|
|
808
|
|
|
|
|
|
|
# Illegal, can't use concatenated arguments in |
|
809
|
|
|
|
|
|
|
# more complex templates |
|
810
|
0
|
|
|
|
|
0
|
_pushErrors( "--$tmp[0] cannot be called like " |
|
811
|
|
|
|
|
|
|
. 'this when multiple arguments are ' |
|
812
|
|
|
|
|
|
|
. 'required.' ); |
|
813
|
|
|
|
|
|
|
} |
|
814
|
|
|
|
|
|
|
} |
|
815
|
|
|
|
|
|
|
|
|
816
|
|
|
|
|
|
|
# Handle known options |
|
817
|
13
|
100
|
|
|
|
20
|
if ( defined $tref ) { |
|
818
|
|
|
|
|
|
|
|
|
819
|
|
|
|
|
|
|
# Get the argument template |
|
820
|
11
|
|
|
|
|
14
|
$argTemplate = $$tref{Template}; |
|
821
|
|
|
|
|
|
|
|
|
822
|
|
|
|
|
|
|
# Snarf extra arguments |
|
823
|
11
|
100
|
|
|
|
30
|
unless ( |
|
824
|
|
|
|
|
|
|
_getArgs( "--$tmp[0]", $argTemplate, @oargs ) ) { |
|
825
|
1
|
|
|
|
|
2
|
$rv = 0; |
|
826
|
1
|
|
|
|
|
3
|
next; |
|
827
|
|
|
|
|
|
|
} |
|
828
|
|
|
|
|
|
|
|
|
829
|
|
|
|
|
|
|
# Check if we've call this more than once |
|
830
|
10
|
50
|
66
|
|
|
34
|
if ( not $$tref{Multiple} and $$tref{Count} > 0 ) { |
|
831
|
0
|
|
|
|
|
0
|
_pushErrors( |
|
832
|
|
|
|
|
|
|
"Option $$tref{Name} is only allowed to be used once" |
|
833
|
|
|
|
|
|
|
); |
|
834
|
0
|
|
|
|
|
0
|
$rv = 0; |
|
835
|
0
|
|
|
|
|
0
|
next; |
|
836
|
|
|
|
|
|
|
} |
|
837
|
|
|
|
|
|
|
|
|
838
|
|
|
|
|
|
|
# Store the values |
|
839
|
10
|
|
|
|
|
17
|
_storeArgs( $tref, $argTemplate, @oargs ); |
|
840
|
|
|
|
|
|
|
|
|
841
|
|
|
|
|
|
|
} else { |
|
842
|
|
|
|
|
|
|
|
|
843
|
|
|
|
|
|
|
# Unknown long option |
|
844
|
2
|
|
|
|
|
7
|
_pushErrors("Unknown option: --$tmp[0]"); |
|
845
|
2
|
|
|
|
|
4
|
$rv = 0; |
|
846
|
|
|
|
|
|
|
} |
|
847
|
|
|
|
|
|
|
|
|
848
|
|
|
|
|
|
|
} else { |
|
849
|
|
|
|
|
|
|
|
|
850
|
|
|
|
|
|
|
# Unknown option-looking thingy |
|
851
|
0
|
|
|
|
|
0
|
_pushErrors("Unknown option thingy: $arg"); |
|
852
|
0
|
|
|
|
|
0
|
$rv = 0; |
|
853
|
|
|
|
|
|
|
} |
|
854
|
|
|
|
|
|
|
|
|
855
|
|
|
|
|
|
|
} else { |
|
856
|
|
|
|
|
|
|
|
|
857
|
|
|
|
|
|
|
# Everything else is payload |
|
858
|
7
|
100
|
|
|
|
15
|
$$oref{PAYLOAD} = [] unless exists $$oref{PAYLOAD}; |
|
859
|
7
|
|
|
|
|
7
|
push @{ $$oref{PAYLOAD} }, $arg; |
|
|
7
|
|
|
|
|
12
|
|
|
860
|
|
|
|
|
|
|
} |
|
861
|
|
|
|
|
|
|
} |
|
862
|
|
|
|
|
|
|
} |
|
863
|
|
|
|
|
|
|
|
|
864
|
|
|
|
|
|
|
# Make a list of all the arguments that was used |
|
865
|
14
|
|
|
|
|
21
|
@tmp = (); |
|
866
|
14
|
|
|
|
|
18
|
foreach ( _optionsKeys() ) { |
|
867
|
203
|
100
|
|
|
|
195
|
push @tmp, $_ if ${ _getOption($_) }{Count}; |
|
|
203
|
|
|
|
|
224
|
|
|
868
|
|
|
|
|
|
|
} |
|
869
|
|
|
|
|
|
|
|
|
870
|
|
|
|
|
|
|
# Final sanity check |
|
871
|
14
|
|
|
|
|
46
|
foreach ( sort @tmp ) { |
|
872
|
44
|
|
|
|
|
55
|
$tref = _getOption($_); |
|
873
|
|
|
|
|
|
|
|
|
874
|
|
|
|
|
|
|
# Make sure nothing was called that is exclusive of |
|
875
|
|
|
|
|
|
|
# other called options |
|
876
|
44
|
100
|
|
|
|
46
|
if ( @{ $$tref{ExclusiveOf} } ) { |
|
|
44
|
|
|
|
|
64
|
|
|
877
|
2
|
|
|
|
|
3
|
$regex = '(?:' . join( '|', @{ $$tref{ExclusiveOf} } ) . ')'; |
|
|
2
|
|
|
|
|
5
|
|
|
878
|
2
|
50
|
|
|
|
31
|
if ( grep /^$regex$/sm, @tmp ) { |
|
879
|
|
|
|
|
|
|
_pushErrors( |
|
880
|
|
|
|
|
|
|
"$$tref{Name} cannot be called with the following options: " |
|
881
|
|
|
|
|
|
|
. join ', ', |
|
882
|
2
|
|
|
|
|
5
|
@{ $$tref{ExclusiveOf} } ); |
|
|
2
|
|
|
|
|
7
|
|
|
883
|
2
|
|
|
|
|
4
|
$rv = 0; |
|
884
|
|
|
|
|
|
|
} |
|
885
|
|
|
|
|
|
|
} |
|
886
|
|
|
|
|
|
|
|
|
887
|
|
|
|
|
|
|
# Make sure the option was called in conjunction with others |
|
888
|
44
|
|
|
|
|
78
|
foreach $regex ( @{ $$tref{AccompaniedBy} } ) { |
|
|
44
|
|
|
|
|
87
|
|
|
889
|
14
|
100
|
|
|
|
158
|
unless ( grep /^\Q$regex\E$/sm, @tmp ) { |
|
890
|
|
|
|
|
|
|
_pushErrors( |
|
891
|
|
|
|
|
|
|
"$$tref{Name} must be called with the following options: " |
|
892
|
|
|
|
|
|
|
. join ', ', |
|
893
|
2
|
|
|
|
|
5
|
@{ $$tref{AccompaniedBy} } ); |
|
|
2
|
|
|
|
|
7
|
|
|
894
|
2
|
|
|
|
|
3
|
$rv = 0; |
|
895
|
|
|
|
|
|
|
} |
|
896
|
|
|
|
|
|
|
} |
|
897
|
|
|
|
|
|
|
|
|
898
|
|
|
|
|
|
|
# Copy the values into %$oref |
|
899
|
44
|
|
|
|
|
82
|
$$oref{$_} = $$tref{Value}; |
|
900
|
|
|
|
|
|
|
} |
|
901
|
|
|
|
|
|
|
|
|
902
|
14
|
|
|
|
|
30
|
subPostamble( PDLEVEL1, '$', $rv ); |
|
903
|
|
|
|
|
|
|
|
|
904
|
14
|
|
|
|
|
60
|
return $rv; |
|
905
|
|
|
|
|
|
|
} |
|
906
|
|
|
|
|
|
|
|
|
907
|
|
|
|
|
|
|
1; |
|
908
|
|
|
|
|
|
|
|
|
909
|
|
|
|
|
|
|
__END__ |