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__ |