line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Package::Configure; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
40225
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
36
|
|
4
|
1
|
|
|
1
|
|
4
|
use Carp qw(confess); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
48
|
|
5
|
1
|
|
|
1
|
|
5
|
use Data::Dumper; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
107
|
|
6
|
1
|
|
|
1
|
|
1390
|
use Getopt::Long; |
|
1
|
|
|
|
|
12492
|
|
|
1
|
|
|
|
|
8
|
|
7
|
1
|
|
|
1
|
|
2999
|
use SelfLoader; |
|
1
|
|
|
|
|
10954
|
|
|
1
|
|
|
|
|
54
|
|
8
|
1
|
|
|
1
|
|
1226
|
use Term::ANSIColor; |
|
1
|
|
|
|
|
11002
|
|
|
1
|
|
|
|
|
114
|
|
9
|
1
|
|
|
1
|
|
1192
|
use Text::ParseWords; |
|
1
|
|
|
|
|
1398
|
|
|
1
|
|
|
|
|
70
|
|
10
|
1
|
|
|
1
|
|
10506
|
use Text::Wrap; |
|
1
|
|
|
|
|
9323
|
|
|
1
|
|
|
|
|
72
|
|
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
#can't use it here b/c it may not be installed when Package-Tools is |
13
|
|
|
|
|
|
|
#installed, so we require it later. |
14
|
|
|
|
|
|
|
#use Config::IniFiles; |
15
|
|
|
|
|
|
|
|
16
|
1
|
|
|
1
|
|
9
|
use vars qw($AUTOLOAD); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
37
|
|
17
|
|
|
|
|
|
|
|
18
|
1
|
|
|
1
|
|
15
|
use constant CACHE => 'pkg_config.cache'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
63
|
|
19
|
1
|
|
|
1
|
|
4
|
use constant TEMPLATE => 'pkg_config.in'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
337
|
|
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
=head1 SYNOPSIS |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
my $config = Package::Configure->new(); |
24
|
|
|
|
|
|
|
my $value1 = $config->setting1(); #get |
25
|
|
|
|
|
|
|
$config->setting1('a new value for setting 1'); #set |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
=head1 DESCRIPTION |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
Package::Configure - Access package configuration values |
30
|
|
|
|
|
|
|
from command-line options (Getopt::Long style), previously specified |
31
|
|
|
|
|
|
|
cached settings, or default values. This package is a kindred spirit to |
32
|
|
|
|
|
|
|
the GNU automake and autoconf tools. |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
When a Package::Configure object is instantiated, the following |
35
|
|
|
|
|
|
|
happens: |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
1. A. If F exists, load it into L accessor as a |
38
|
|
|
|
|
|
|
Config::IniFiles object. |
39
|
|
|
|
|
|
|
B. Otherwise, if F exists, load that. |
40
|
|
|
|
|
|
|
C. Otherwise, load nothing. |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
2. If a configuration file was loaded, process commandline arguments |
43
|
|
|
|
|
|
|
Using Getopt::Long, overriding configuration setings with those provided |
44
|
|
|
|
|
|
|
from Getopt::Long. |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
3. A. If C<--help> was given as a Makefile.PL argument, render the configuration |
47
|
|
|
|
|
|
|
as a usage document to STDOUT and exit(0). |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
-otherwise- |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
B. If a configuration file was loaded, and C<--interactive> was given as a |
52
|
|
|
|
|
|
|
Makefile.PL argument, query the user on STDOUT/STDIN for new configuration |
53
|
|
|
|
|
|
|
values. |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
4. Variable values may also be accessed using C<$config-Emy_setting_name()> |
56
|
|
|
|
|
|
|
to get the current value, or C<$config-Emy_setting_name('a new value')> to |
57
|
|
|
|
|
|
|
update the value of the variable. |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
5. When the object is destroyed (by falling out of scope, being undefined, etc), |
60
|
|
|
|
|
|
|
the current state of the object is written to F. |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=head1 CONFIGURATION FILES pkg_config.in AND pkg_config.cache |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
The configuration files are in INI format, and are parsed using Config::IniFiles. |
65
|
|
|
|
|
|
|
You should be familiar with the INI format and L. |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
=head2 RESERVED VARIABLES |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
These variables have a built-in function and are reserved for use by |
70
|
|
|
|
|
|
|
Package::Configure. |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
* help |
73
|
|
|
|
|
|
|
* interactive |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
Run C for a display of what parameters are available, and |
76
|
|
|
|
|
|
|
C for an interactive query for values of said |
77
|
|
|
|
|
|
|
parameters. |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
=head2 DECLARING CONFIGURATION VARIABLES |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
Package::Configure recognizes variables in the following INI sections: |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
for single value parameters: |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
* [option integer] |
86
|
|
|
|
|
|
|
* [option float] |
87
|
|
|
|
|
|
|
* [option string] |
88
|
|
|
|
|
|
|
* [option dir] |
89
|
|
|
|
|
|
|
* [option file] |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
for multi value parameters: |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
* [option integers] |
94
|
|
|
|
|
|
|
* [option floats] |
95
|
|
|
|
|
|
|
* [option strings] |
96
|
|
|
|
|
|
|
* [option dirs] |
97
|
|
|
|
|
|
|
* [option files] |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
Comments on sections/parameters are recognized and displayed when F is |
100
|
|
|
|
|
|
|
run with the C<--help> option. |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
Typechecking is performed on the integer, float, dir, and file sections, see |
103
|
|
|
|
|
|
|
L. |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
for scripts: |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
* [PL_FILES] |
108
|
|
|
|
|
|
|
* [EXE_FILES] |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
thes sections are special -- they are passed to ExtUtils::MakeMaker to |
111
|
|
|
|
|
|
|
determine which scripts are processed at make-time (PL_FILES), and which are installed |
112
|
|
|
|
|
|
|
(EXE_FILES). See L for details on how that system works. |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
=head2 SETTING VARIABLE VALUES |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
See L |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
Default values can be set in F, as well as collected from the |
119
|
|
|
|
|
|
|
command-line using Getopt::Long-style options, or with interactive question/answer. |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
The Getopt::Long parameters available are created dynamically from the variable names |
122
|
|
|
|
|
|
|
in F or F (preferred if present). |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
=head3 EDITING CONFIGURATION FILE |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
See L for a description of the configuration file format. |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
=head3 COMMAND-LINE OPTIONS |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
For a script called F, valid executions of the script might be: |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
C |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
C |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
Argument names are identical to those in F or F. |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
=head3 INTERACTIVE QUERY |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
A few runs of C might look like the following: |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
[14:38]aday@asti:~/cvsroot/Package-Tools> /usr/bin/perl ./script.pl --interactive |
143
|
|
|
|
|
|
|
color - what is your favorite color? (currently: "blue")? red |
144
|
|
|
|
|
|
|
number - what is your favorite number? (currently: "2")? 9 |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
[14:38]aday@asti:~/cvsroot/Package-Tools> /usr/bin/perl ./script.pl --interactive |
147
|
|
|
|
|
|
|
color - what is your favorite color? (currently: "red")? yellow |
148
|
|
|
|
|
|
|
number - what is your favorite number? (currently: "9")? 8 |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
[14:38]aday@asti:~/cvsroot/Package-Tools> /usr/bin/perl ./script.pl --interactive --color 6 --number orange |
151
|
|
|
|
|
|
|
Value "orange" invalid for option number (number expected) |
152
|
|
|
|
|
|
|
color - what is your favorite color? (currently: "6")? orange |
153
|
|
|
|
|
|
|
number - what is your favorite number? (currently: "8")? 6 |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
=head1 AUTHOR |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
Allen Day, Eallenday@ucla.eduE |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
=cut |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
=head1 METHODS |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
=cut |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
=head2 AUTOLOAD() |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
FIXME internal method, undocumented |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
=cut |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
sub AUTOLOAD { |
172
|
3
|
|
|
3
|
|
1155
|
my $self = shift; |
173
|
3
|
|
|
|
|
4
|
my $val = shift; |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
#return undef unless $self && $self->ini(); |
176
|
|
|
|
|
|
|
|
177
|
3
|
|
|
|
|
5
|
my $symbol = $AUTOLOAD; |
178
|
3
|
|
|
|
|
4
|
my $sub = $symbol; |
179
|
3
|
|
|
|
|
21
|
$sub =~ s/^.+::([\w]+?)$/$1/; |
180
|
|
|
|
|
|
|
|
181
|
3
|
|
|
|
|
6
|
my $sect = undef; |
182
|
3
|
|
|
|
|
4
|
my $i = 0; |
183
|
3
|
|
|
|
|
8
|
foreach my $section ($self->ini()->Sections){ |
184
|
33
|
100
|
|
|
|
84
|
if(grep {$_ eq $sub} $self->ini()->Parameters($section)){ |
|
36
|
|
|
|
|
539
|
|
185
|
3
|
|
|
|
|
4
|
$sect = $section; |
186
|
3
|
|
|
|
|
6
|
$i++; |
187
|
|
|
|
|
|
|
} |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
} |
190
|
|
|
|
|
|
|
|
191
|
3
|
50
|
|
|
|
11
|
if($i == 0){ |
|
|
50
|
|
|
|
|
|
192
|
0
|
|
|
|
|
0
|
die "no such parameter or method '$sub'"; |
193
|
|
|
|
|
|
|
} elsif($i == 1){ |
194
|
1
|
|
|
1
|
|
6
|
no strict 'refs'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
2605
|
|
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
*$symbol = sub { |
197
|
7
|
|
|
7
|
|
2076
|
my($self,@val) = @_; |
198
|
7
|
100
|
|
|
|
15
|
if(@val){ |
199
|
2
|
|
|
|
|
6
|
return $self->ini()->setval($sect,$sub,@val); |
200
|
|
|
|
|
|
|
} else { |
201
|
5
|
|
|
|
|
12
|
return $self->ini()->val($sect,$sub); |
202
|
|
|
|
|
|
|
} |
203
|
3
|
|
|
|
|
28
|
}; |
204
|
|
|
|
|
|
|
|
205
|
3
|
|
|
|
|
10
|
return $self->$sub(@_); |
206
|
|
|
|
|
|
|
} else { |
207
|
0
|
|
|
|
|
0
|
warn "parameters in multiple ($i) sections named $sub, use |
208
|
|
|
|
|
|
|
\$install->config->ini()->val('section',$sub) |
209
|
|
|
|
|
|
|
\$install->config->ini()->setval('section,$sub,\@newvals) |
210
|
|
|
|
|
|
|
for access"; |
211
|
0
|
|
|
|
|
0
|
return undef; |
212
|
|
|
|
|
|
|
} |
213
|
|
|
|
|
|
|
|
214
|
0
|
|
|
|
|
0
|
return undef; |
215
|
|
|
|
|
|
|
} |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
=head2 new() |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
Usage : $config = Package::Configure->new(); |
220
|
|
|
|
|
|
|
Function: constructs a new object, reads variables and their default/cached |
221
|
|
|
|
|
|
|
values from state files F and F. |
222
|
|
|
|
|
|
|
Also handles command-line arguments by delegating to Getopt::Long. |
223
|
|
|
|
|
|
|
Returns : a Package::Configure object |
224
|
|
|
|
|
|
|
Args : none. |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
=cut |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
sub new { |
229
|
1
|
|
|
1
|
1
|
15
|
my($class,%arg) = @_; |
230
|
|
|
|
|
|
|
|
231
|
1
|
|
|
|
|
4
|
my $self = bless {}, $class; |
232
|
|
|
|
|
|
|
|
233
|
1
|
|
|
|
|
2
|
my $ini; |
234
|
|
|
|
|
|
|
|
235
|
1
|
50
|
|
|
|
5
|
if(!$arg{bootstrap}){ |
236
|
1
|
|
|
|
|
1604
|
require Config::IniFiles; |
237
|
1
|
50
|
|
|
|
28697
|
if (-f CACHE) { |
|
|
0
|
|
|
|
|
|
238
|
1
|
|
|
|
|
13
|
$ini = Config::IniFiles->new( -file => CACHE ); |
239
|
1
|
|
|
|
|
6953
|
print STDERR colored("\rusing cached configuration values from ".CACHE,'cyan')."\n"; |
240
|
|
|
|
|
|
|
} elsif (-f TEMPLATE) { |
241
|
0
|
|
|
|
|
0
|
$ini = Config::IniFiles->new( -file => TEMPLATE ); |
242
|
0
|
|
|
|
|
0
|
print STDERR colored("\rusing default configuration values from ".TEMPLATE,'cyan')."\n"; |
243
|
|
|
|
|
|
|
} else { |
244
|
|
|
|
|
|
|
#no config file |
245
|
0
|
|
|
|
|
0
|
$ini = Config::IniFiles->new(); |
246
|
|
|
|
|
|
|
} |
247
|
|
|
|
|
|
|
|
248
|
1
|
50
|
|
|
|
201
|
if(!$ini){ |
249
|
0
|
|
|
|
|
0
|
print STDERR colored('config parse failed: '.join(' ',@Config::IniFiles::errors),'red')."\n"; |
250
|
0
|
|
|
|
|
0
|
exit(1); |
251
|
|
|
|
|
|
|
} |
252
|
|
|
|
|
|
|
|
253
|
1
|
|
|
|
|
7
|
$self->ini($ini); |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
#override defaults and cache with command-line args |
256
|
1
|
|
|
|
|
4
|
$self->process_options(); |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
#query user interactively |
259
|
1
|
50
|
|
|
|
6
|
$self->process_interactive() if $self->interactive(); |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
#validate parameters |
262
|
1
|
|
|
|
|
4
|
$self->validate_configuration(); |
263
|
|
|
|
|
|
|
} |
264
|
|
|
|
|
|
|
|
265
|
1
|
50
|
|
|
|
22
|
$self->ini()->WriteConfig(CACHE) if $self->ini(); |
266
|
|
|
|
|
|
|
|
267
|
1
|
|
|
|
|
1701
|
return $self; |
268
|
|
|
|
|
|
|
} |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
=head2 validate_type() |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
Usage : $obj->validate_type('type','thing_to_check'); |
273
|
|
|
|
|
|
|
Function: attempts to validate a value as a particular type |
274
|
|
|
|
|
|
|
valid values for argument 1 are: integer, float, string, dir, file. |
275
|
|
|
|
|
|
|
Returns : 1 on success |
276
|
|
|
|
|
|
|
Args : anonymous list: |
277
|
|
|
|
|
|
|
argument 1: type to validate against |
278
|
|
|
|
|
|
|
argument 2: value to validate |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
=cut |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
sub validate_type { |
283
|
0
|
|
|
0
|
1
|
0
|
my ($self,$type,$val) = @_; |
284
|
|
|
|
|
|
|
|
285
|
0
|
0
|
|
|
|
0
|
if($type eq 'integer') { return 1 if $val =~ /^-?\d+$/ } |
|
0
|
0
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
286
|
0
|
0
|
|
|
|
0
|
elsif($type eq 'float') { return 1 if $val =~ /^-?\d*\.?\d*$/ } |
287
|
0
|
|
|
|
|
0
|
elsif($type eq 'string') { return 1 } |
288
|
0
|
0
|
|
|
|
0
|
elsif($type eq 'dir') { return 1 if -d $val } |
289
|
0
|
0
|
|
|
|
0
|
elsif($type eq 'file') { return 1 if -f $val } |
290
|
|
|
|
|
|
|
|
291
|
0
|
|
|
|
|
0
|
return 0; |
292
|
|
|
|
|
|
|
} |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
=head2 validate_configuration() |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
Usage : $obj->validate_configuration(); |
298
|
|
|
|
|
|
|
Function: internal method. attempts to validate values |
299
|
|
|
|
|
|
|
from the configuration file by calling L |
300
|
|
|
|
|
|
|
on each. |
301
|
|
|
|
|
|
|
Returns : n/a |
302
|
|
|
|
|
|
|
Args : none |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
=cut |
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
sub validate_configuration { |
307
|
1
|
|
|
1
|
1
|
3
|
my ($self) = @_; |
308
|
|
|
|
|
|
|
|
309
|
1
|
|
|
|
|
3
|
my $cfg = $self->ini; |
310
|
|
|
|
|
|
|
|
311
|
1
|
|
|
|
|
5
|
foreach my $section ( $cfg->GroupMembers('option') ) { |
312
|
10
|
|
|
|
|
164
|
foreach my $param ($cfg->Parameters("option $section")){ |
313
|
0
|
|
|
|
|
0
|
my $die = 0; |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
#single |
316
|
0
|
0
|
|
|
|
0
|
if($section !~ /s$/){ |
317
|
0
|
|
|
|
|
0
|
my $val = val("option $section",$param); |
318
|
0
|
|
|
|
|
0
|
my $type = $section; |
319
|
0
|
|
|
|
|
0
|
$type =~ s/option //; |
320
|
0
|
0
|
|
|
|
0
|
$die++ unless $self->validate_type($type,$val); |
321
|
|
|
|
|
|
|
} |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
#plural |
324
|
|
|
|
|
|
|
else { |
325
|
0
|
|
|
|
|
0
|
my @val = val("option $section",$param); |
326
|
0
|
|
|
|
|
0
|
foreach my $val (@val){ |
327
|
0
|
|
|
|
|
0
|
my $type = $section; |
328
|
0
|
|
|
|
|
0
|
$type =~ s/option //; |
329
|
0
|
|
|
|
|
0
|
$type =~ s/s$//; |
330
|
0
|
0
|
|
|
|
0
|
$die++ unless $self->validate_type($type,$val); |
331
|
|
|
|
|
|
|
} |
332
|
|
|
|
|
|
|
} |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
#did the param(s) validate? |
335
|
0
|
0
|
|
|
|
0
|
if($die){ |
336
|
0
|
|
|
|
|
0
|
$section =~ s/option //; |
337
|
0
|
|
|
|
|
0
|
die "[option $section] $param: value is not a valid '$section'"; |
338
|
|
|
|
|
|
|
} |
339
|
|
|
|
|
|
|
} |
340
|
|
|
|
|
|
|
} |
341
|
|
|
|
|
|
|
} |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
=head2 process_interactive() |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
Usage : $obj->process_interactive(); |
346
|
|
|
|
|
|
|
Function: iterates over [option *] and [EXE_FILES] sections from |
347
|
|
|
|
|
|
|
configuration file and prompts user for new values. values |
348
|
|
|
|
|
|
|
are validated using L before being |
349
|
|
|
|
|
|
|
accepted. lists of values are accepted and split using |
350
|
|
|
|
|
|
|
L |
351
|
|
|
|
|
|
|
Returns : n/a |
352
|
|
|
|
|
|
|
Args : none |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
=cut |
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
sub process_interactive { |
357
|
0
|
|
|
0
|
1
|
0
|
my ($self) = @_; |
358
|
|
|
|
|
|
|
|
359
|
0
|
|
|
|
|
0
|
my $ask = qq(\r%s [%s] - %s (currently: "%s")? ); |
360
|
|
|
|
|
|
|
|
361
|
0
|
|
|
|
|
0
|
foreach my $section ( $self->ini()->Sections ){ |
362
|
0
|
0
|
|
|
|
0
|
next unless $section =~ /^option/; |
363
|
0
|
|
|
|
|
0
|
foreach my $param ( $self->ini()->Parameters($section) ){ |
364
|
0
|
|
|
|
|
0
|
my $type = $section; |
365
|
0
|
|
|
|
|
0
|
$type =~ s/^option //; |
366
|
|
|
|
|
|
|
|
367
|
0
|
|
|
|
|
0
|
my $comment = join('', map{s/^#//;$_} $self->ini()->GetParameterComment($section,$param)); |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
368
|
|
|
|
|
|
|
|
369
|
0
|
|
|
|
|
0
|
print sprintf($ask, |
370
|
|
|
|
|
|
|
$param, |
371
|
|
|
|
|
|
|
$type, |
372
|
|
|
|
|
|
|
$comment, |
373
|
|
|
|
|
|
|
$self->ini()->val($section,$param) |
374
|
|
|
|
|
|
|
); |
375
|
0
|
|
|
|
|
0
|
my $response = <>; |
376
|
0
|
|
|
|
|
0
|
chomp $response; |
377
|
|
|
|
|
|
|
|
378
|
0
|
0
|
|
|
|
0
|
if($response eq ''){ |
379
|
0
|
|
|
|
|
0
|
print colored("\ryou didn't respond, skipping. this may break the build",'red')."\n"; |
380
|
0
|
|
|
|
|
0
|
next; |
381
|
|
|
|
|
|
|
} |
382
|
|
|
|
|
|
|
|
383
|
0
|
|
|
|
|
0
|
my $valid = 1; |
384
|
|
|
|
|
|
|
#single |
385
|
0
|
0
|
|
|
|
0
|
if($type !~ /s$/){ |
386
|
0
|
0
|
|
|
|
0
|
if(!$self->validate_type($type,$response)){ |
387
|
0
|
|
|
|
|
0
|
$valid = 0; |
388
|
|
|
|
|
|
|
} else { |
389
|
|
|
|
|
|
|
#commit it |
390
|
0
|
|
|
|
|
0
|
$self->ini()->setval($section,$param,$response); |
391
|
|
|
|
|
|
|
} |
392
|
|
|
|
|
|
|
} |
393
|
|
|
|
|
|
|
#plural |
394
|
|
|
|
|
|
|
else { |
395
|
0
|
|
|
|
|
0
|
$type =~ s/s$//; |
396
|
0
|
|
|
|
|
0
|
my @response = shellwords($response); |
397
|
0
|
|
|
|
|
0
|
foreach my $response (@response) { |
398
|
0
|
0
|
|
|
|
0
|
if(!$self->validate_type($type,$response)){ |
399
|
0
|
|
|
|
|
0
|
$valid = 0; |
400
|
0
|
|
|
|
|
0
|
last; |
401
|
|
|
|
|
|
|
} else { |
402
|
0
|
|
|
|
|
0
|
$self->ini()->setval($section,$param,@response); |
403
|
|
|
|
|
|
|
} |
404
|
|
|
|
|
|
|
} |
405
|
0
|
0
|
|
|
|
0
|
if($valid == 1) { |
406
|
|
|
|
|
|
|
#commit it |
407
|
0
|
|
|
|
|
0
|
$self->ini()->setval($section,$param,@response); |
408
|
|
|
|
|
|
|
} |
409
|
|
|
|
|
|
|
} |
410
|
0
|
0
|
|
|
|
0
|
if(!$valid){ |
411
|
0
|
|
|
|
|
0
|
print colored("\rinvalid value(s), try again",'red')."\n"; |
412
|
0
|
|
|
|
|
0
|
redo; |
413
|
|
|
|
|
|
|
} |
414
|
|
|
|
|
|
|
} |
415
|
|
|
|
|
|
|
} |
416
|
|
|
|
|
|
|
|
417
|
0
|
|
|
|
|
0
|
$ask = qq(\rinstall %s - %s [Y/n]? ); |
418
|
|
|
|
|
|
|
|
419
|
0
|
|
|
|
|
0
|
foreach my $exe ( $self->ini()->Parameters('EXE_FILES') ){ |
420
|
0
|
|
|
|
|
0
|
my $target = $exe; |
421
|
|
|
|
|
|
|
|
422
|
0
|
|
|
|
|
0
|
$target =~ s/\.PLS?$//; |
423
|
|
|
|
|
|
|
|
424
|
0
|
|
|
|
|
0
|
my $comment = join('', map{s/^#//;$_} $self->ini()->GetParameterComment('EXE_FILES',$exe)); |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
425
|
|
|
|
|
|
|
|
426
|
0
|
|
|
|
|
0
|
print sprintf($ask, |
427
|
|
|
|
|
|
|
$target, |
428
|
|
|
|
|
|
|
$comment, |
429
|
|
|
|
|
|
|
$self->ini()->val('EXE_FILES',$exe) |
430
|
|
|
|
|
|
|
); |
431
|
0
|
|
|
|
|
0
|
my $response = <>; |
432
|
0
|
|
|
|
|
0
|
chomp $response; |
433
|
|
|
|
|
|
|
|
434
|
0
|
0
|
|
|
|
0
|
if($response !~ /^n/i){ |
435
|
0
|
|
|
|
|
0
|
$self->ini()->setval('EXE_FILES',$exe,'yes') |
436
|
|
|
|
|
|
|
} else { |
437
|
0
|
|
|
|
|
0
|
$self->ini()->setval('EXE_FILES',$exe,'no') |
438
|
|
|
|
|
|
|
} |
439
|
|
|
|
|
|
|
} |
440
|
|
|
|
|
|
|
} |
441
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
=head2 process_options() |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
Usage : $config->process_options(); |
446
|
|
|
|
|
|
|
Function: Internal method that processes command-line options. |
447
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
=cut |
449
|
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
sub process_options { |
451
|
1
|
|
|
1
|
1
|
3
|
my $self = shift; |
452
|
|
|
|
|
|
|
|
453
|
1
|
|
|
|
|
3
|
my $cfg = $self->ini(); |
454
|
|
|
|
|
|
|
|
455
|
1
|
|
|
|
|
4
|
my %slot = (); |
456
|
1
|
|
|
|
|
1
|
my %sect = (); |
457
|
1
|
|
|
|
|
2
|
my @protos = (); |
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
#hardcode in --help |
460
|
1
|
|
|
|
|
2
|
$slot{help} = undef; |
461
|
1
|
|
|
|
|
2
|
push @protos, 'help!'; |
462
|
1
|
|
|
|
|
20
|
$slot{interactive} = undef; |
463
|
1
|
|
|
|
|
3
|
push @protos, 'interactive!'; |
464
|
|
|
|
|
|
|
|
465
|
1
|
|
|
|
|
4
|
foreach my $section ($cfg->GroupMembers('option')) { |
466
|
10
|
|
|
|
|
42
|
foreach my $param ($cfg->Parameters($section)) { |
467
|
11
|
|
|
|
|
132
|
$sect{$param} = $section; |
468
|
11
|
|
|
|
|
22
|
$slot{$param} = undef; |
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
#single |
471
|
11
|
100
|
|
|
|
46
|
if($section eq 'option integer') { push @protos, "$param=i" } |
|
2
|
100
|
|
|
|
6
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
472
|
1
|
|
|
|
|
3
|
elsif($section eq 'option float') { push @protos, "$param=f" } |
473
|
1
|
|
|
|
|
3
|
elsif($section eq 'option file') { push @protos, "$param=s" } |
474
|
1
|
|
|
|
|
4
|
elsif($section eq 'option dir') { push @protos, "$param=s" } |
475
|
1
|
|
|
|
|
9
|
elsif($section eq 'option string') { push @protos, "$param=s" } |
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
#plural |
478
|
1
|
|
|
|
|
4
|
elsif($section eq 'option integers'){ push @protos, "$param=i@" } |
479
|
1
|
|
|
|
|
3
|
elsif($section eq 'option floats') { push @protos, "$param=f@" } |
480
|
1
|
|
|
|
|
4
|
elsif($section eq 'option files') { push @protos, "$param=s@" } |
481
|
1
|
|
|
|
|
3
|
elsif($section eq 'option dirs') { push @protos, "$param=s@" } |
482
|
1
|
|
|
|
|
4
|
elsif($section eq 'option strings') { push @protos, "$param=s@" } |
483
|
|
|
|
|
|
|
} |
484
|
|
|
|
|
|
|
} |
485
|
|
|
|
|
|
|
|
486
|
1
|
|
|
|
|
6
|
GetOptions(\%slot,@protos); |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
#if help requested, give it and bail out |
489
|
1
|
50
|
|
|
|
772
|
if($slot{help}){ |
490
|
0
|
|
|
|
|
0
|
$self->show_help(); |
491
|
0
|
|
|
|
|
0
|
exit 0; |
492
|
|
|
|
|
|
|
} |
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
#if interactive requested, set a flag to do a query later |
495
|
1
|
50
|
|
|
|
4
|
if($slot{interactive}){ |
496
|
0
|
|
|
|
|
0
|
$self->interactive(1); |
497
|
|
|
|
|
|
|
} |
498
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
#handle setteds |
500
|
1
|
|
|
|
|
4
|
foreach my $k (keys %slot){ |
501
|
13
|
50
|
|
|
|
25
|
next unless defined($slot{$k}); |
502
|
0
|
0
|
|
|
|
0
|
if(ref($slot{$k}) eq 'ARRAY'){ |
503
|
0
|
|
|
|
|
0
|
$cfg->setval($sect{$k},$k,@{ $slot{$k} }); |
|
0
|
|
|
|
|
0
|
|
504
|
|
|
|
|
|
|
} else { |
505
|
0
|
|
|
|
|
0
|
$cfg->setval($sect{$k},$k,$slot{$k}); |
506
|
|
|
|
|
|
|
} |
507
|
|
|
|
|
|
|
} |
508
|
|
|
|
|
|
|
} |
509
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
=head2 show_help() |
511
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
Usage : $obj->show_help(); |
513
|
|
|
|
|
|
|
Function: render configuration file sections/parameters with |
514
|
|
|
|
|
|
|
descriptions to STDOUT. program exits and call does |
515
|
|
|
|
|
|
|
not return. |
516
|
|
|
|
|
|
|
Returns : exit code on program termination |
517
|
|
|
|
|
|
|
Args : exits 0 (success) |
518
|
|
|
|
|
|
|
|
519
|
|
|
|
|
|
|
=cut |
520
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
sub show_help { |
522
|
0
|
|
|
0
|
1
|
0
|
my ($self) = @_; |
523
|
|
|
|
|
|
|
|
524
|
0
|
|
|
|
|
0
|
my $i = 4; |
525
|
|
|
|
|
|
|
|
526
|
0
|
|
|
|
|
0
|
print "Usage: $0 [options]\n"; |
527
|
0
|
|
|
|
|
0
|
print "Available options, organized by section:\n\n"; |
528
|
|
|
|
|
|
|
|
529
|
0
|
|
|
|
|
0
|
foreach my $section ($self->ini->Sections()){ |
530
|
0
|
0
|
|
|
|
0
|
next unless $section =~ /^option/; |
531
|
0
|
0
|
|
|
|
0
|
next unless $self->ini->Parameters($section); |
532
|
|
|
|
|
|
|
|
533
|
0
|
|
|
|
|
0
|
my $comment = join(' ', map {s/^#+//; $_} $self->ini->GetSectionComment($section)); |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
534
|
0
|
|
0
|
|
|
0
|
$comment ||= 'no description for this section'; |
535
|
0
|
|
|
|
|
0
|
print( (' ' x $i)."[$section] $comment\n" ); |
536
|
|
|
|
|
|
|
|
537
|
0
|
|
|
|
|
0
|
$i += 4; |
538
|
|
|
|
|
|
|
|
539
|
0
|
|
|
|
|
0
|
foreach my $param ($self->ini->Parameters($section)){ |
540
|
0
|
|
|
|
|
0
|
my $comment = join(' ', map {s/^#+//; $_} $self->ini->GetParameterComment($section,$param)); |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
541
|
0
|
|
0
|
|
|
0
|
$comment ||= 'no description for this parameter'; |
542
|
0
|
|
|
|
|
0
|
print( (' ' x $i).'--'.$param." : $comment\n" ); |
543
|
|
|
|
|
|
|
} |
544
|
|
|
|
|
|
|
|
545
|
0
|
|
|
|
|
0
|
$i -= 4; |
546
|
|
|
|
|
|
|
|
547
|
0
|
|
|
|
|
0
|
print "\n"; |
548
|
|
|
|
|
|
|
} |
549
|
|
|
|
|
|
|
} |
550
|
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
=head2 ini() |
552
|
|
|
|
|
|
|
|
553
|
|
|
|
|
|
|
Usage : $obj->ini($newval) |
554
|
|
|
|
|
|
|
Function: holds a Config::IniFiles instance |
555
|
|
|
|
|
|
|
Returns : value of ini (a scalar) |
556
|
|
|
|
|
|
|
Args : on set, new value (a scalar or undef, optional) |
557
|
|
|
|
|
|
|
|
558
|
|
|
|
|
|
|
|
559
|
|
|
|
|
|
|
=cut |
560
|
|
|
|
|
|
|
|
561
|
|
|
|
|
|
|
sub ini { |
562
|
50
|
|
|
50
|
1
|
59
|
my($self,$val) = @_; |
563
|
50
|
100
|
|
|
|
102
|
$self->{'ini'} = $val if defined($val); |
564
|
50
|
|
|
|
|
180
|
return $self->{'ini'}; |
565
|
|
|
|
|
|
|
} |
566
|
|
|
|
|
|
|
|
567
|
|
|
|
|
|
|
=head2 interactive() |
568
|
|
|
|
|
|
|
|
569
|
|
|
|
|
|
|
Usage : $obj->interactive($newval) |
570
|
|
|
|
|
|
|
Function: flag for whether or not the user should be interactively |
571
|
|
|
|
|
|
|
queried for configuration values. |
572
|
|
|
|
|
|
|
Returns : value of interactive (a scalar) |
573
|
|
|
|
|
|
|
Args : on set, new value (a scalar or undef, optional) |
574
|
|
|
|
|
|
|
|
575
|
|
|
|
|
|
|
|
576
|
|
|
|
|
|
|
=cut |
577
|
|
|
|
|
|
|
|
578
|
|
|
|
|
|
|
sub interactive { |
579
|
1
|
|
|
1
|
1
|
1
|
my($self,$val) = @_; |
580
|
1
|
50
|
|
|
|
5
|
$self->{'interactive'} = $val if defined($val); |
581
|
1
|
|
|
|
|
4
|
return $self->{'interactive'}; |
582
|
|
|
|
|
|
|
} |
583
|
|
|
|
|
|
|
|
584
|
|
|
|
|
|
|
=head2 DESTROY() |
585
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
called when the object is destroyed. writes object's variables' states |
587
|
|
|
|
|
|
|
to F to be read at next instantiation. |
588
|
|
|
|
|
|
|
|
589
|
|
|
|
|
|
|
=cut |
590
|
|
|
|
|
|
|
|
591
|
|
|
|
|
|
|
sub DESTROY { |
592
|
1
|
|
|
1
|
|
364
|
my $self = shift; |
593
|
1
|
50
|
|
|
|
2
|
$self->ini->WriteConfig(CACHE) if $self->ini(); |
594
|
|
|
|
|
|
|
} |
595
|
|
|
|
|
|
|
|
596
|
|
|
|
|
|
|
1; |