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