File Coverage

blib/lib/Config/Param.pm
Criterion Covered Total %
statement 906 1126 80.4
branch 490 782 62.6
condition 127 216 58.8
subroutine 53 56 94.6
pod 22 43 51.1
total 1598 2223 71.8


line stmt bran cond sub pod time code
1             # This has been a simple routine for command line and config file parsing.
2             # Now it deals with differing styles (grades of laziness) of command line parameters,
3             # has funky operators on them, and is a tool box to work with other program's config files.
4              
5             # It also carries a badge with the inscript "NIH syndrome".
6             # On the backside, you can read "But still better than anything that came before!".
7              
8             # current modus operandi:
9             # 1. parse command line args into temporary storage
10             # 2. parse config files (that may have been set on command line)
11             # 3. merge settings (overwrite config file settings)
12             # 4. finalize with help/error message
13              
14             # TODO: I got sections now. A next step could be sub-commands, presented as sections
15             # in help output and also defined like/with those. Needs some namespacing, though.
16             # Maybe just sub-instances of Config::Param.
17              
18             # TODO: I should restructure the the internal data. It's too many hashes now
19             # with the same key. Nested hash or better array with named indices (to avoid typos and
20             # less wasteful storage)?
21              
22             # TODO: --config with append mode, by config option
23              
24             package Config::Param;
25              
26 12     12   1551267 use strict;
  12         26  
  12         599  
27 12     12   108 use warnings;
  12         25  
  12         698  
28              
29 12     12   77 use Carp;
  12         20  
  12         1033  
30 12     12   256 use 5.008;
  12         57  
31             # major.minor.bugfix, the latter two with 3 digits each
32             # or major.minor_alpha
33             our $VERSION = '4.000006';
34             $VERSION = eval $VERSION;
35             our %features = qw(array 1 hash 1);
36              
37             our $verbose = 0; # overriding config
38              
39             # parameter flags
40             our $count = 1;
41             our $arg = 2;
42             our $switch = 4;
43             our $append = 8;
44             our $nonempty = 16;
45              
46             # using exit values from sysexists.h which make sense
47             # for configuration parsing
48             my $ex_usage = 64;
49             my $ex_config = 78;
50             my $ex_software = 70;
51              
52 12     12   5963 use Sys::Hostname;
  12         16440  
  12         860  
53 12     12   6507 use FindBin qw($Bin);
  12         16183  
  12         1801  
54 12     12   83 use File::Spec;
  12         20  
  12         247  
55 12     12   63 use File::Basename;
  12         23  
  12         94723  
56              
57             # The official API for simple use:
58              
59             # This is the procedural interface: Just call get() with your setup and get the pars.
60             sub get #(config, params)
61             {
62             # Handling of the differing API variants
63             # 1. just plain list of parameter definitions
64             # 2. config hash first, then parameter definitions
65             # 3. config hash, then array ref for definitions
66             # ... in that case, optional ref to argument array to parse
67 67 100   67 1 1009087 my $config = ref $_[0] eq 'HASH' ? shift : {};
68 67         141 my $pardef;
69 67         175 my $args = \@ARGV;
70 67         121 my $give_error;
71 67 100       190 if(ref $_[0] eq 'ARRAY')
72             {
73 66         152 $pardef = shift;
74 66 100       235 if(ref $_[0] eq 'ARRAY')
75             {
76 64         123 $args = shift;
77 64         126 $give_error = 1;
78             }
79             }
80 1         2 else{ $pardef = \@_; }
81              
82 67         401 my $pars = Config::Param->new($config, $pardef);
83             # Aborting on bad specification. Not sensible to continue.
84             # Match this with documentation in POD.
85 67   100     206 my $bad = not (
86             $pars->good()
87             and $pars->parse_args($args)
88             and $pars->use_config_files()
89             and $pars->apply_args()
90             and $pars->INT_value_check()
91             );
92 67         299 $pars->final_action($bad);
93              
94 67 100       285 $_[0] = $pars->{errors} if $give_error;
95 67         355 return $pars->{param};
96             }
97              
98             # Now the meat.
99              
100             # Codes for types of parameters. It's deliberate that simple scalars are false and others are true.
101             my $scalar = 0; # Undefined also counts as scalar.
102             my $array = 1;
103             my $hash = 2;
104             my @initval = (undef, [], {});
105             #This needs to be changed. Also for a hash, --hash is equivalent to --hash=1, which
106             #results in 1=>undef, not truth=>1
107             my @trueval = (1, [1], {truth=>1});
108             my @falseval = (0, [0], {truth=>0});
109             my @typename = ('scalar', 'array', 'hash');
110             my %typemap = (''=>$scalar, scalar=>$scalar, array=>$array, hash=>$hash);
111              
112             # A name is allowed to contain just about everything but "=", but shall not end with something that will be mistaken for an operator.
113             # The checks for valid names besides the generic regexes are stricter and should be employed in addition.
114              
115             # Parser regex elements.
116             # Generally, it's optinal operators before "=" or just operators for short parameters.
117             # The addition with /./ is for choosing an arbitrary array separator for the value.
118             # Since long names are not allowed to end with an operator, using "/" that way is
119             # no additional restriction.
120             # Context is needed to decide for /,/ and // with special function for arrays and hashes.
121             # The grammar is not context-free anymore. Meh.
122             # Well, treating it this way: // is a special operator for long names,
123             # // is parsed as /=/, then interpreted accordingly for arrays as //.
124             my $ops = '.+\-*\/'; # There's also <
125             my $sopex = '['.$ops.']?=|['.$ops.']=?';
126             my $lopex = '\/.\/['.$ops.']?=|['.$ops.']?=|\/\/|\/.\/';
127             my $noop = '[^+\-=.*\/\s<>]'; # a non-whitespace character that is unspecial
128             my $parname = $noop.'[^\s=\/<>]*'.$noop;
129              
130             # Regular expressions for parameter parsing.
131             # The two variants are crafted to yield matching back-references.
132             # -x -x=bla -xyz -xyz=bla
133             our $shortex_strict = qr/^(([-+])($noop+|($noop+)($sopex)(.*)))$/;
134             # -x -x=bla -xyz x x=bla xyz
135             our $shortex_lazy = qr/^(([-+]?)($noop+|($noop)($sopex)(.*)))$/;
136             # -xbla with x possibly arg-requiring option and bla an argument
137             our $shortarg = qr/^[-+]($noop)($sopex|)(.+)$/;
138             # --long --long=bla
139             our $longex_strict = qr/^(([-+]{2})($parname)(($lopex)(.*)|))$/;
140             # --long --long=bla -long=bla long=bla
141             our $longex_lazy = qr/^(([-+]{0,2})($parname)()($lopex)(.*)|(--|\+\+)($parname))$/;
142              
143             my %example =
144             (
145             'lazy' => '[-]s [-]xyz [-]s=value --long [-[-]]long=value - [files/stuff]'
146             ,'normal' => '-s -xyz -s=value --long --long=value [--] [files/stuff]'
147             );
148             my $lazyinfo = "The [ ] notation means that the enclosed - is optional, saving typing time for really lazy people. Note that \"xyz\" as well as \"-xyz\" mention three short options, opposed to the long option \"--long\". In trade for the shortage of \"-\", the separator for additional unnamed parameters is mandatory (supply as many \"-\" grouped together as you like;-).";
149              
150             my @morehelp =
151             (
152             'You mention the options to change parameters in any order or even multiple times.'
153             , ' They are processed in the oder given, later operations overriding/extending earlier settings.'
154             , ' Using the separator "--" stops option parsing'."\n"
155             ,'An only mentioned short/long name (no "=value") means setting to 1, which is true in the logical sense. Also, prepending + instead of the usual - negates this, setting the value to 0 (false).'."\n"
156             ,'Specifying "-s" and "--long" is the same as "-s=1" and "--long=1", while "+s" and "++long" is the sames as "-s=0" and "--long=0".'."\n"
157             ,"\n"
158             ,'There are also different operators than just "=" available, notably ".=", "+=", "-=", "*=" and "/=" for concatenation / appending array/hash elements and scalar arithmetic operations on the value. Arrays are appended to via "array.=element", hash elements are set via "hash.=name=value". You can also set more array/hash elements by specifying a separator after the long parameter line like this for comma separation:'."\n\n"
159             ,"\t--array/,/=1,2,3 --hash/,/=name=val,name2=val2"
160             );
161              
162             # check if long/short name is valid before use
163             sub valid_name
164             {
165 657     657 1 1612 my ($long, $short) = @_;
166             return
167             (
168 657   66     15535 (not defined $short or $short eq '' or $short =~ /^$noop$/o)
169             and defined $long
170             and $long =~ /^$parname/o
171             );
172             }
173              
174             sub valid_type
175             {
176 657     657 1 1578 my $type = lc(ref $_[0]);
177 657         1646 return $typemap{$type}; # undefined if invalid
178             }
179              
180             # A valid definition also means that the default value type
181             # must match a possibly specified type.
182             sub valid_def
183             {
184 657     657 1 1052 my $def = shift;
185             $_[0] = (defined $def->{type} and not defined $def->{value})
186             ? $def->{type}
187 657 50 33     2215 : valid_type($def->{value});
188             return
189             (
190             valid_name($def->{long}, $def->{short}) and defined $_[0]
191             and ( not defined $def->{type} or ($def->{type} ne $_[0]) )
192             and ( not defined $def->{regex} or ref $def->{regex} eq 'Regexp')
193 657   33     1662 and ( not defined $def->{call} or ref $def->{call} eq 'CODE' )
194             );
195             }
196              
197             sub hashdef
198             {
199 234     234 1 1443 my %h = ( long=>shift, value=>shift, short=>shift
200             , help=>shift, arg=>shift, flags=>shift
201             , addflags=>shift, level=>shift
202             , regex=>shift, call=>shift );
203 234 50       587 $h{short} = '' unless defined $h{short};
204 234 100       531 $h{flags} = 0 unless defined $h{flags};
205 234         467 return \%h;
206             }
207              
208             sub builtins
209             {
210 79     79 1 391369 my $config = shift;
211 79         370 my %bldi = (help=>1, h=>1, I=>1, config=>1);
212 79 50 33     400 $bldi{version} = 1 if(defined $config and defined $config->{version});
213 79         209 return \%bldi;
214             }
215              
216             # helper for below
217             sub INT_defchecker
218             {
219 259     259 0 435 my $def = shift;
220 259         391 my $name_there = shift;
221 259 100       653 my $short = defined $def->{short} ? $def->{short} : '';
222              
223             return ''
224 259 50       615 if defined $def->{section};
225 259 50       493 return "'".(defined $def->{long} ? $def->{long} : '')."' definition is not good"
    100          
226             unless valid_def($def);
227             return "'$def->{long}' ".(defined $def->{short} ? "/ $def->{short}" : '')." name already taken"
228 258 50 66     1263 if($name_there->{$def->{long}} or $name_there->{$short});
    100          
229             $name_there->{$def->{long}} = 1
230 257 50       810 if defined $def->{long};
231 257 100       756 $name_there->{$short} = 1 if $short ne '';
232              
233 257         552 return ''; # no problem
234             }
235              
236             # check if whole definition array is proper,
237             # modifying the argument to sanitize to canonical form
238             # That form is an array of definition hashes.
239             sub sane_pardef
240             {
241 70     70 1 126 my $config = shift;
242 70         203 my $name_there = builtins($config);
243 70         145 my $indef = $_[0];
244 70         150 $_[0] = []; # If an error comes, nothing is sane.
245 70 100       171 if(@{$indef})
  70         194  
246             {
247 69 100       211 if(ref $indef->[0] ne '')
248             {
249             # each element is a ref, check them all
250 33         55 for my $d (@{$indef})
  33         85  
251             {
252 86         156 my $t = ref $d;
253 86 50       190 return 'mix of array/hash and other stuff'
254             if($t eq '');
255 86 50 66     238 return 'strange refs, neither hash nor array'
256             if($t ne 'ARRAY' and $t ne 'HASH');
257              
258 86 100       169 my $def = $t eq 'ARRAY' ? hashdef(@{$d}) : $d;
  61         150  
259 86         218 my $problem = INT_defchecker($def, $name_there);
260 86         168 $d = $def;
261 86 50       245 return $problem if $problem;
262             }
263             }
264             else
265             {
266 36 50       56 return 'plain member count not multiple of 4' if(@{$indef} % 4);
  36         126  
267              
268 36         81 my @spars = ();
269 36         69 while(@{$indef})
  207         465  
270             {
271 173         257 my $sdef;
272 173         257 my $def = hashdef(splice(@{$indef}, 0, 4));
  173         516  
273 173         430 my $problem = INT_defchecker($def, $name_there);
274 173 100       452 return $problem if $problem;
275 171         364 push(@spars, $def);
276             }
277 34         82 $indef = \@spars;
278             }
279             }
280 68         164 $_[0] = $indef; # only after full success
281 68         297 return '';
282             }
283              
284             sub escape_pod
285             {
286 143 100   143 1 308 return undef unless defined $_[0];
287 141         331 my @text = split("\n", shift, -1);
288 141         287 for(@text)
289             {
290 173 100       447 next if m/^\s/; # indented stuff is verbatim
291 157         283 s/^=(\w)/=Z<>$1/;
292 157         348 s/([A-Z])
293             }
294 141         559 return join("\n", @text);
295             }
296              
297             # Following: The OO API for detailed work.
298              
299             sub new # strictly (\%config, \@pardef)
300             {
301 70     70 1 177939 my $class = shift;
302 70         152 my $self = {};
303 70         144 bless $self, $class;
304              
305 70         252 $self->{config} = shift;
306 70 100       699 $self->{config} = {} unless defined $self->{config};
307 70         185 my $pars = shift;
308 70 100       190 $pars = [] unless defined $pars;
309 70         218 $self->{files} = [];
310 70         200 $self->{errors} = [];
311              
312 70 100       2040 $self->{config}{program} = basename($0) unless defined $self->{config}{program};
313 70 100       322 $self->{config}{shortdefaults} = 1 unless exists $self->{config}{shortdefaults};
314 70         157 $self->{printconfig} = 0;
315 70         143 my $hh = 'Show the help message. Value 1..9: help level, par:'
316             . ' help for paramter par (long name) only.';
317 70         168 $self->{extrahelp} = 'Additional fun with negative values, optionally'
318             . ' followed by comma-separated list of parameter names:'."\n"
319             . '-1: list par names, -2: list one line per name,'
320             . ' -3: -2 without builtins, -10: dump values (Perl style),'
321             . ' -11: dump values (lines), -100: print POD.';
322 70         129 my $ih = 'Which configfile(s) to use (overriding automatic search'
323             . ' in likely paths);'."\n"
324             . 'special: just -I or --config causes printing a current config'
325             . ' file to STDOUT';
326              
327 70 50 66     259 if($self->{config}{lazy} and $self->{config}{posixhelp})
328             {
329 0         0 $self->INT_error("POSIX-style help texts and lazy parameter syntax are incompatible.");
330 0         0 $self->{config}{posixhelp} = 0;
331             }
332             # Put -- in front of long names in communication, in POSIX mode.
333 70 50       256 $self->{longprefix} = $self->{config}{posixhelp} ? '--' : '';
334             # Same for - and short names.
335 70 50       314 $self->{shortprefix} = $self->{config}{posixhelp} ? '-' : '';
336             # An array of sections, with {name=>foo, member=>[$long1, $long2, ...]}.
337             # If I opted for
338 70         162 $self->{section} = [];
339             # Start the default, nameless section. Maybe a name should be generated if there
340             # are other sections.
341             $self->define({ section=>'', level=>1, flags=>$self->{config}{flags}
342 70         648 , regex=>$self->{config}{regex}, call=>$self->{config}{call} });
343              
344             # Choosing kindof distributed storage of parmeter properties, for direct
345             # access. With more and more properties, the count of global hashes
346             # increases uncomfortably.
347 70         248 $self->{param} = {}; # parameter values
348 70         150 $self->{help} = {}; # help texts
349 70         245 $self->{long} = {}; # map short to long names
350 70         182 $self->{short} = {}; # map long to short names
351 70         170 $self->{arg} = {}; # argument name
352 70         169 $self->{type} = {}; # type code
353             # store default values, for even more detailed documentation
354 70         186 $self->{default} = {}; # default value
355 70         153 $self->{level} = {}; # parameter level for help output
356 70         166 $self->{length} = 0; # max length of long names
357 70         159 $self->{arglength} = 0; # max length of name=arg or name[=arg]
358             # Chain of config files being parsed, to be able to check for inclusion loops.
359 70         152 $self->{parse_chain} = [];
360             # TODO set from config hash
361 70 100       814 $self->define({ long=>'help', short=>$self->{config}{shortdefaults} ? 'h' : '', value=>0
362             , help=>\$hh, flags=>0, regex=>qr/./ });
363             $self->define(
364             {
365             long=>'config', short=>$self->{config}{shortdefaults} ? 'I' : '', value=>[]
366             , help=>\$ih, flags=>0, regex=>qr/./
367             , call=> sub
368             { # --config increments printconfig and does not add a config file.
369 1 50   1   3 unless(defined $_[2])
370             {
371 1         2 $self->{printconfig} += 1;
372 1         2 undef $_[0]; # Skip this operation.
373             }
374 1         2 return 0;
375             }
376 70 100       1129 });
377             $self->define({ long=>'version', value=>0, short=>''
378             , help=>\'print out the program version', arg=>''
379             , flags=>0, regex=>qr/./ })
380 70 50       345 if(defined $self->{config}{version});
381              
382             # deprecated v2 API
383             $self->INT_error("Update your program: ignorehelp is gone in favour of nofinals!")
384 70 50       198 if exists $self->{config}{ignorehelp};
385             $self->INT_error("Update your program: eval option not supported anymore.")
386 70 50       191 if exists $self->{config}{eval};
387              
388 70         217 my $problem = sane_pardef($self->{config}, $pars);
389 70 100       241 if($problem)
390             {
391 2         11 $self->INT_error("bad parameter specification: $problem");
392             } else
393             {
394 68         119 my $di = 0;
395 68         115 for my $def (@{$pars})
  68         168  
396             {
397 252         394 ++$di;
398             # definition failure here is an error in the module
399 252 50       610 $self->INT_error("Very unexpected failure to evaluate parameter definition $di.")
400             unless($self->define($def));
401             }
402 68         201 $self->find_config_files();
403             }
404 70         510 return $self;
405             }
406              
407             sub good
408             {
409 67     67 1 142 my $self = shift;
410 67         103 return @{$self->{errors}} == 0;
  67         387  
411             }
412              
413             # name[=arg] and variants
414             sub INT_namearg
415             {
416 398     398 0 662 my $self = shift;
417 398         657 my $name = shift;
418 398         864 my $flags = $self->{flags}{$name};
419 398         815 my $val= $self->{arg}{$name};
420 398 100       948 $val = 'val' unless defined $val;
421 398 50       1532 return $flags & $arg
    100          
422             ? $name.'='.$val # mandatory argument
423             : ( $val eq ''
424             ? $name # silent optional argument
425             : $name.'[='.$val.']' ) # named optional argument
426             }
427              
428             sub define
429             {
430 468     468 1 798 my $self = shift;
431 468         802 my $pd = shift;
432              
433             my $helpref = defined $pd->{help}
434             ? ( ref $pd->{help} ? $pd->{help} : \$pd->{help} )
435 468 100       1560 : \"";
    100          
436             # The section keyword defines a section instead of a parameter.
437 468 100       1294 if(exists $pd->{section})
438             {
439             # Silence runs with perl -W. Actually, I'm annoyed that 0+undef isn't
440             # doing this already. Still doing 0+ to catch idle strings, which are
441             # evildoing by the user program.
442 70 50       184 my $flags = defined $pd->{flags} ? 0+$pd->{flags} : 0;
443 70 50       202 my $level = defined $pd->{level} ? 0+$pd->{level} : 0;
444             # The first section is the default one, any further sections mean
445             # that you care about parameter order.
446             $self->{config}{ordered} = 1
447 70 50       116 if @{$self->{section}};
  70         229  
448 70         476 push(@{$self->{section}}, { section=>$pd->{section}
449             , help=>$helpref, level=>$level
450             , minlevel=>10 # will be lowered when parameters are added to it
451 70         124 , flags=>$flags, regex=>$pd->{regex}, call=>$pd->{call} });
452 70         192 return 1;
453             }
454              
455 398 50       596 unless(@{$self->{section}})
  398         1104  
456             {
457 0         0 $self->INT_error("Define the default section first!");
458 0         0 return 1;
459             }
460              
461 398         802 my $section = $self->{section}[$#{$self->{section}}];
  398         957  
462 398         791 my $name = $pd->{long};
463              
464 398 100       1013 $pd->{help} = \'' unless defined $pd->{help};
465 398 100       1549 $pd->{short} = '' unless defined $pd->{short};
466 398         606 my $type; # valid_def sets that
467 398 50       919 unless(valid_def($pd, $type))
468             {
469 0         0 $self->INT_error("Invalid definition for $name / $pd->{short}");
470 0         0 return 0;
471             }
472             my $flags = defined $pd->{flags}
473             ? $pd->{flags}
474 398 100       1223 : $section->{flags};
475             $flags |= $pd->{addflags}
476 398 50       942 if defined $pd->{addflags};
477             my $regex = defined $pd->{regex}
478             ? $pd->{regex}
479 398 100       956 : $section->{regex};
480             my $call = defined $pd->{call}
481             ? $pd->{call}
482 398 100       873 : $section->{call};
483 398 50 33     1114 if($flags & $switch and $flags & $arg)
484             {
485 0         0 $self->INT_error("Invalid flags (switch requiring argument) for $name / $pd->{short}");
486 0         0 return 0;
487             }
488 398 50 33     1889 unless(defined $self->{param}{$name} or defined $self->{long}{$pd->{short}})
489             {
490 398         1036 $self->{type}{$name} = $type;
491             # If the definition value is a reference, make a deep copy of it
492             # instead of copying the reference. This keeps the definition
493             # and default value unchanged, for reproducible multiple runs of
494             # the parser.
495 398 100       852 if(ref $pd->{value})
496             {
497 212         1460 require Storable; # Only require it if there is really the need.
498 212         8151 $self->{param}{$name} = Storable::dclone($pd->{value});
499 212         2959 $self->{default}{$name} = Storable::dclone($pd->{value});
500             }
501             else
502             {
503 186         433 $self->{param}{$name} = $pd->{value};
504 186         457 $self->{default}{$name} = $pd->{value};
505             }
506             $self->{long}{$pd->{short}} = $name
507 398 100       1689 if $pd->{short} ne '';
508 398         942 $self->{short}{$name} = $pd->{short};
509 398         862 $self->{help}{$name} = $helpref;
510 398         874 $self->{arg}{$name} = $pd->{arg};
511             my $lev = $self->{level}{$name} = 0+( defined $pd->{level}
512             ? $pd->{level}
513 398 50       1287 : $section->{level} );
514             # Store the minimum level needed to display at least one section member.
515             $section->{minlevel} = $lev
516 398 100       1058 if $lev < $section->{minlevel};
517 398         810 $self->{flags}{$name} = $flags;
518             $self->{arg}{$name} = ''
519 398 50       1046 if $self->{flags}{$name} & $switch;
520 398         643 push(@{$section->{member}}, $name);
  398         1152  
521 398         2689 $self->INT_verb_msg("define $name / $pd->{short} of type $typename[$type] flags $self->{flags}{$name}\n");
522             # Call INT_namearg after settling flags!
523             $self->{length} = length($name)
524 398 100       1279 if length($name) > $self->{length};
525 398         966 my $arglen = length($self->INT_namearg($name));
526             $self->{arglength} = $arglen
527 398 100       1130 if $arglen > $self->{arglength};
528 398 100       1125 $self->{regex}{$name} = $regex
529             if defined $regex;
530 398 100       1128 $self->{call}{$name} = $call
531             if defined $call;
532             }
533             else
534             {
535 0         0 $self->INT_error("Tried to redefine an option ($pd->{long} / $pd->{short}! Programmer: please check this!");
536 0         0 return 0;
537             }
538 398         1217 return 1;
539             }
540              
541             sub find_config_files
542             {
543 68     68 1 123 my $self = shift;
544              
545 68 50       260 if(defined $self->{config}{file})
546             {
547 0         0 @{$self->{param}{config}} = ref $self->{config}{file} eq 'ARRAY'
548 0         0 ? @{$self->{config}{file}}
549 0 0       0 : ($self->{config}{file});
550             }
551             #means: nofile[false,true], file[string], info, verbose[bool],
552             #config confusion
553             # as long as I was told not to use a config file or it has been already given
554 68 100 66     222 unless($self->{config}{nofile} or @{$self->{param}{config}})
  42         154  
555             {
556             # Default to reading program.conf and/or program.host.conf if found.
557 42         209 my $pconf = $self->INT_find_config($self->{config}{program}.'.conf');
558 42         241 my $hconf = $self->INT_find_config($self->{config}{program}.'.'.hostname().'.conf');
559 42         110 my @l;
560 42 100       113 push(@l, $pconf) if defined $pconf;
561 42 50       100 push(@l, $hconf) if defined $hconf;
562             # That list can be empty if none existing.
563 42         233 $self->INT_verb_msg("possible config files: @l\n");
564             # The last entry in the list has precedence.
565 42 50       128 unless($self->{config}{multi})
566             {
567 42 100       123 @l = ($l[$#l]) if @l; # Only the last element, if any, prevails.
568             }
569 42         77 @{$self->{param}{config}} = @l;
  42         178  
570             }
571             }
572              
573             # Parse abcd to the list of corresponding long names.
574             sub INT_long_names
575             {
576 65     65 0 112 my $self = shift;
577 65         120 my $sname = shift;
578 65         99 my @names;
579 65         232 for my $s (split(//,$sname))
580             {
581 69 50       233 if(defined (my $name = $self->{long}{$s}))
582             {
583 69         243 push(@names, $name);
584             }
585             else
586             {
587 0 0       0 if($self->{config}{fuzzy})
588             {
589 0         0 $self->INT_verb_msg("Unknown short option $s, assuming that this is data instead.\n");
590 0         0 @names = ();
591 0         0 last;
592             }
593             else
594             {
595 0 0 0     0 unless($self->{config}{ignore_unknown} and $self->{config}{ignore_unknown} > 1)
596             {
597             #$self->{param}{help} = 1;
598 0         0 $self->INT_error("unknown short parameter \"$s\" not in (".join('', sort keys %{$self->{long}}).")");
  0         0  
599             }
600             }
601             }
602             }
603 65         170 return \@names;
604             }
605              
606             # Works directly on last arguments to avoid passing things back and forth.
607             sub INT_settle_op # (lastoption, sign, name, op, val, args)
608             {
609 206     206 0 368 my $self = shift;
610 206         342 my $lastoption = shift;
611 206         335 my $sign = shift;
612 206         374 my $name = shift;
613             # op:$_[0] val:$_[1] args:$_[2]
614 206         536 my $flags = $self->{flags}{$name};
615             my $arrhash = defined $self->{type}{$name}
616 206 100       809 and grep {$_==$self->{type}{$name}} ($array, $hash);
  410         1023  
617              
618             # First settle a possibly enforced argument that has to follow.
619             # Then call the custom callback that could change things
620              
621 206 100 100     981 if(defined $_[0] and $arrhash)
    100 100        
622             {
623             # -a/,/=bla and -a/,/bla are equivalent, as is -a/,/ bla
624 158 100 100     517 if($_[0] eq '/' and $_[1] =~ m:(./)(=?)(.*):)
625             {
626 16         45 $_[0] .= $1.$2;
627 16 100 66     69 $_[1] = ($3 eq '' and $2 eq '') ? undef : $3;
628 16 100 100     80 $_[0] .= '='
629             if($2 eq '' and defined $_[1]);
630             }
631 158 100 66     472 if($_[0] =~ m:^/./$: and $flags & $arg)
632             {
633 8 50       13 unless(@{$_[2]})
  8         21  
634             {
635             $self->INT_error( "Array/hash missing explicit argument: $self->{longprefix}$name"
636 0 0       0 . ($self->{short}{$name} ne '' ? " ($self->{shortprefix}$self->{short}{$name})" : '') );
637 0         0 return;
638             }
639 8         18 $_[0] .= '=';
640 8         11 $_[1] = shift @{$_[2]};
  8         20  
641             }
642             } elsif(not defined $_[0] and $flags & $arg)
643             {
644 16 50 33     43 unless($lastoption and @{$_[2]})
  16         49  
645             {
646             $self->INT_error( "Parameter missing explicit argument: $self->{longprefix}$name"
647 0 0       0 . ($self->{short}{$name} ne '' ? " ($self->{shortprefix}$self->{short}{$name})" : '') );
648 0         0 return;
649             }
650 16         32 $_[0] = '=';
651 16         26 $_[1] = shift @{$_[2]};
  16         40  
652             }
653              
654             # Defined empty value with undefined operator is just confusing to the callback.
655 206 100       511 undef $_[1]
656             unless defined $_[0];
657              
658             # The callback that could modify things.
659              
660 206 100       550 if(defined $self->{call}{$name})
661             {
662 6         10 my $nname = $name;
663 6         28 my $ret = $self->{call}{$name}->($nname, $sign, $_[0], $_[1]);
664 6 100 66     53 if($ret or (not defined $nname or $nname ne $name))
      33        
665             {
666 1 50       2 $self->INT_error("Callback for $name returned an error: $ret")
667             if $ret; # otherwise intentional drop
668 1         1 undef $_[0];
669 1         2 return;
670             }
671             }
672              
673             # Final translation of operator.
674              
675 205 100       500 unless(defined $_[0])
676             {
677 30 50       70 if($flags & $count)
678             {
679 0 0       0 ($_[0], $_[1]) = $sign =~ /^-/ ? ('+=', 1) : ('=', 0);
680             }
681             else
682             {
683 30         60 $_[0] = '=';
684 30 50       104 $_[1] = $sign =~ /^-/ ? 1 : 0;
685             }
686             }
687 205 100       464 if($arrhash)
688             {
689             $_[0] =~ s:(^|[^\.])=$:$1.=:
690 204 100       953 if $self->{flags}{$name} & $append;
691             }
692             }
693              
694             # Record a operator and operand for given parameter.
695             # It is not checked if the operation makes sense.
696             sub INT_add_op
697             {
698 206     206 0 359 my $self = shift;
699 206         641 my ($name, $op, $val) = (shift, shift, shift);
700             $self->{ops}{$name} = []
701 206 100       712 unless defined $self->{ops}{$name};
702             return # undefined ops are intentionally dropped
703 206 100       478 unless defined $op;
704 205         811 $self->INT_verb_msg("name: $name op: $op (val: $val)\n");
705 205 100       365 push(@{$self->{ops}{$name}}, ($op =~ /=$/ ? $op : $op.'='), $val);
  205         1468  
706             }
707              
708             # Step 1: parse command line
709             sub parse_args
710             {
711 66     66 1 121 my $self = shift;
712 66         111 my $args = shift;
713              
714 66         115 my $olderrs = @{$self->{errors}};
  66         153  
715 66         232 $self->{ops} = {};
716 66         203 $self->{printconfig} = 0;
717              
718 66 50 33     218 $self->{param}{help} = 1 if($self->{config}{gimme} and not @{$args}); #giving help when no arguments
  0         0  
719              
720             #regexes for option parsing
721 66         124 my $shorts = $shortex_strict;
722 66         123 my $longex = $longex_strict;
723 66         121 my $separator = '^--$'; #exactly this string means "Stop the parsing!"
724              
725 66 100       192 if($self->{config}{lazy})
726             {
727 15         33 $shorts = $shortex_lazy;
728 15         27 $longex = $longex_lazy;
729 15         28 $separator = '^-+$'; # Lazy about separators, too ... Any number of consecutive "-".
730             }
731              
732             # The argument parser, long/short parameter evaluation is similar, but separate.
733 66         114 while(@{$args})
  273         707  
734             {
735 208         794 $self->INT_verb_msg("parsing $args->[0]\n");
736 208         600 my $e = index($args->[0], "\n");
737 208         357 my $begin;
738 208         328 my $end = "";
739 208         310 my $name;
740 208 50       508 if($e >=0)
741             {
742 0         0 $begin = substr($args->[0],0,$e);
743 0         0 $end = substr($args->[0],$e);
744             }
745             else
746             {
747 208         375 $begin = $args->[0];
748             }
749 208 50 66     3804 if($begin =~ /$separator/o)
    100 100        
    100          
    100          
750             {
751 0         0 $self->INT_verb_msg("separator\n");
752 0         0 shift(@{$args});
  0         0  
753 0         0 last;
754             }
755             elsif( $begin =~ $shortarg
756             and defined ($name = $self->{long}{$1})
757             and $self->{flags}{$name} & $arg )
758             {
759 46         151 $self->INT_verb_msg("short with value\n");
760 46 100       143 my $op = $2 ne '' ? $2 : '=';
761 46         151 my $val = $3.$end;
762 46         72 shift @{$args};
  46         108  
763 46         166 $self->INT_settle_op(1, '-', $name, $op, $val, $args);
764 46         135 $self->INT_add_op($name, $op, $val);
765             }
766             elsif($begin =~ /$shorts/o)
767             {
768 65         233 my $sign = $2;
769 65 100       176 $sign = '-' if $sign eq '';
770 65         133 my $op = $5;
771 65 100       213 my $sname = defined $op ? $4 : $3;
772 65 100       229 my $val = (defined $6 ? $6 : '').$end;
773 65         201 $self->INT_verb_msg("a (set of) short one(s)\n");
774             # First settle which parameters are mentioned.
775             # This returns an empty list if one invalid option is present.
776             # Also, the case of a single argument-requiring short option leading
777             # a value is handled by redefining the value and operator
778 65         199 my $names = $self->INT_long_names($sname, $op, $val);
779 65 50       114 last unless @{$names};
  65         171  
780 65         113 shift @{$args}; # It is settled now that this is options.
  65         130  
781              
782 65         114 while(@{$names})
  134         436  
783             {
784 69         133 my $olderr = @{$self->{errors}};
  69         141  
785 69         107 my $name = shift @{$names};
  69         164  
786 69         123 my $lastoption = not @{$names};
  69         143  
787             # Only the last one gets the specified operation.
788 69 100       162 my $kop = $lastoption ? $op : undef;
789 69 100       192 my $kval = $lastoption ? $val : undef;
790 69         223 $self->INT_settle_op($lastoption, $sign, $name, $kop, $kval, $args);
791             $self->INT_add_op($name, $kop, $kval)
792 69 50       110 if(@{$self->{errors}} == $olderr);
  69         323  
793             }
794             }
795             elsif($begin =~ $longex)
796             {
797             #yeah, long option
798 96         228 my $olderr = @{$self->{errors}};
  96         260  
799 96 50       395 my $sign = defined $7 ? $7 : $2;
800 96 100       258 $sign = '--' if $sign eq '';
801 96 50       287 my $name = defined $8 ? $8 : $3;
802 96         395 $self->INT_verb_msg("param $name\n");
803 96         236 my $op = $5;
804 96 100       416 my $val = (defined $6 ? $6 : '').$end;
805 96 50 66     312 unless(exists $self->{param}{$name} or $self->{config}{accept_unknown})
806             {
807 6 50       15 if($self->{config}{fuzzy})
808             {
809 0         0 $self->INT_verb_msg("Stopping option parsing at unkown one: $name");
810 0         0 last;
811             }
812             else
813             {
814 6 100 100     27 unless($self->{config}{ignore_unknown} and $self->{config}{ignore_unknown} > 1)
815             {
816 5         19 $self->INT_error("Unknown parameter (long option): $name");
817             }
818             }
819             }
820 96         153 shift @{$args};
  96         182  
821             # hack for operators, regex may swallow the . in .=
822 96 50       774 unless($name =~ /$noop$/o)
823             {
824 0         0 $op = substr($name,-1,1).$op;
825 0         0 $name = substr($name,0,length($name)-1);
826             }
827             # On any error, keep parsing for giving the user a full list of errors,
828             # but do not process anything erroneous.
829             $self->INT_settle_op(1, $sign, $name, $op, $val, $args)
830 96 100       152 if(@{$self->{errors}} == $olderr);
  96         436  
831             $self->INT_add_op($name, $op, $val)
832 96 100       185 if(@{$self->{errors}} == $olderr);
  96         863  
833             }
834             else
835             {
836 1         4 $self->INT_verb_msg("No parameter, end.\n");
837 1         3 last;
838             } #was no option... consider the switch part over
839             }
840 66         335 $self->{bad_command_line} = not (@{$self->{errors}} == $olderrs)
841 66 50       189 unless $self->{bad_command_line};
842 66         449 return not $self->{bad_command_line};
843             }
844              
845             # Step 2: Read in configuration files.
846             sub use_config_files
847             {
848 63     63 1 118 my $self = shift;
849 63         97 my $olderr = @{$self->{errors}};
  63         153  
850             # Do operations on config file parameter first.
851 63         255 $self->INT_apply_ops('config');
852 63         97 my $newerr = @{$self->{errors}};
  63         126  
853 63 50       188 if($olderr != $newerr)
854             {
855 0         0 $self->{bad_command_line} = 1;
856 0         0 return 0;
857             }
858             # Now parse config file(s).
859 63         216 return $self->INT_parse_files();
860             }
861              
862             # Step 3: Apply command line parameters.
863             # This is complicated by accept_unknown > 2.
864             # I need to wait until config files had the chance to define something properly.
865             sub apply_args
866             {
867 62     62 1 111 my $self = shift;
868 62         115 my $olderrs = @{$self->{errors}};
  62         132  
869 62         103 for my $key (keys %{$self->{ops}})
  62         241  
870             {
871 144 50 66     484 if( not exists $self->{param}{$key}
      33        
872             and defined $self->{config}{accept_unknown}
873             and $self->{config}{accept_unknown} > 1 )
874             {
875 0         0 $self->define({long=>$key});
876             }
877 144 100       371 if(exists $self->{param}{$key})
    50          
878             {
879 143         355 $self->INT_apply_ops($key);
880             }
881             elsif(not $self->{config}{ignore_unknown})
882             {
883 0         0 $self->INT_error("Unknown long parameter \"$self->{longprefix}$key\"");
884             }
885             }
886 62         212 $self->{bad_command_line} = not (@{$self->{errors}} == $olderrs)
887 62 50       203 unless $self->{bad_command_line};
888 62         365 return not $self->{bad_command_line};
889             }
890              
891             # Step 4: Take final action.
892             sub final_action
893             {
894 67     67 1 117 my $self = shift;
895 67         120 my $end = shift;
896 67 100       251 return if($self->{config}{nofinals});
897              
898 27         61 my $handle = $self->{config}{output};
899 27 100       81 $handle = \*STDOUT
900             unless defined $handle;
901 27         74 my $exitcode = @{$self->{errors}}
902             ? ( $self->{bad_command_line}
903             ? $ex_usage
904 27 0       63 : ($self->{bad_config_file} ? $ex_config : $ex_software)
    0          
    50          
905             )
906             : 0;
907              
908 27 50       78 if($end)
909             {
910 0 0       0 if(@{$self->{errors}})
  0         0  
911             {
912 0         0 $self->INT_error("There have been errors in parameter parsing. You should seek --help.");
913             }
914             exit($exitcode)
915 0 0       0 unless $self->{config}{noexit};
916 0         0 return;
917             }
918              
919             #give the help (info text + option help) and exit when -h or --help was given
920 27 100 33     138 if($self->{param}{help})
    50          
    100          
921             {
922 15         50 $self->help();
923             exit($exitcode)
924 15 50       62 unless $self->{config}{noexit};
925             }
926             elsif(defined $self->{config}{version} and $self->{param}{version})
927             {
928 0         0 print $handle "$self->{config}{program} $self->{config}{version}\n";
929             exit($exitcode)
930 0 0       0 unless $self->{config}{noexit};
931             }
932             elsif($self->{printconfig})
933             {
934 1         5 $self->print_file($handle, ($self->{printconfig} > 1));
935             exit($exitcode)
936 1 50       4 unless $self->{config}{noexit};
937             }
938             }
939              
940             # Helper functions...
941              
942             # Produce a string showing the value of a parameter, for the help.
943             sub par_content
944             {
945 71     71 1 127 my $self = shift;
946 71         109 my $k = shift; # The parameter name.
947 71         176 my $format = shift; # formatting choice
948 71         114 my $indent = shift; # indent value for dumper
949 71         115 my $mk = shift; # value selector: 'param' or 'default', usually
950 71 50       187 $mk = 'param'
951             unless defined $mk;
952 71 100 66     371 if(not defined $format or $format eq 'dump')
    50          
953             {
954 68 50       180 if(eval { require Data::Dumper })
  68         1292  
955             {
956 12     12   123 no warnings 'once'; # triggers when embedding the module
  12         26  
  12         157308  
957 68         10570 local $Data::Dumper::Terse = 1;
958 68         132 local $Data::Dumper::Deepcopy = 1;
959 68         118 local $Data::Dumper::Indent = $indent;
960 68 50       156 $Data::Dumper::Indent = 0 unless defined $Data::Dumper::Indent;
961 68         113 local $Data::Dumper::Sortkeys = 1;
962 68         110 local $Data::Dumper::Quotekeys = 0;
963 68         409 return Data::Dumper->Dump([$self->{$mk}{$k}]);
964             }
965 0         0 else{ return "$self->{$mk}{$k}"; }
966             }
967             elsif($format eq 'lines')
968             {
969 3 50       11 return "\n" unless(defined $self->{$mk}{$k});
970 3 100       13 if($self->{type}{$k} == $array)
    100          
971             {
972 1 50       2 return "" unless @{$self->{$mk}{$k}};
  1         5  
973 1         2 return join("\n", @{$self->{$mk}{$k}})."\n";
  1         10  
974             }
975             elsif($self->{type}{$k} == $hash)
976             {
977 1         3 my $ret = '';
978 1         3 for my $sk (sort keys %{$self->{$mk}{$k}})
  1         6  
979             {
980 2         8 $ret .= "$sk=$self->{$mk}{$k}{$sk}\n";
981             }
982 1         6 return $ret;
983             }
984 1         5 else{ return "$self->{$mk}{$k}\n"; }
985 0         0 } else{ $self->INT_error("unknown par_content format: $format"); }
986             }
987              
988             # Fill up with given symbol for pretty indent.
989             sub INT_indent_string
990             {
991 48     48 0 119 my ($indent, $prefill, $filler) = @_;
992 48 50       115 $filler = '.'
993             unless defined $filler;
994 48 100 66     327 return ($indent > $prefill)
    100          
995             ? ( ($prefill and ($indent-$prefill>2)) ? $filler : ' ')
996             x ($indent - $prefill - 1) . ' '
997             : '';
998             }
999              
1000             # simple formatting of some lines (breaking up with initial and subsequent indendation)
1001             sub INT_wrap_print
1002             {
1003 87     87 0 217 my ($handle, $itab, $stab, $length) = (shift, shift, shift, shift);
1004 87 50       217 return unless @_;
1005             # Wrap if given line length can possibly hold the input.
1006              
1007             # Probably I will make this more efficient in future, probably also
1008             # dropping Text::Wrap instead of fighting it. Or use some POD formatting?
1009 87         314 my @paragraphs = split("\n", join("", @_), -1);
1010             # Drop trailing empty lines. We do not wrap what.
1011 87   66     374 while(@paragraphs and $paragraphs[$#paragraphs] eq '')
1012             {
1013 6         24 pop @paragraphs;
1014             }
1015 87         144 my $first = 1;
1016 87         188 print $handle $itab;
1017 87 50       189 print $handle "\n"
1018             unless @paragraphs;
1019 87         152 my $line = undef;
1020 87         136 my $llen = length($itab);
1021 87         139 my $slen = length($stab);
1022 87   33     287 my $can_wrap = $length > $llen && $length > $slen;
1023 87         196 while(@paragraphs)
1024             {
1025 131         234 my $p = shift(@paragraphs);
1026             # Try to handle command line/code blocks by not messing with them.
1027 131 100       499 if($p =~ /^\t/)
    100          
    50          
1028             {
1029 3 0       11 print $handle (defined $line ? $line : '')."\n"
    50          
1030             if $llen;
1031 3         11 print $handle $stab.$p."\n";
1032 3         6 $line = '';
1033 3         10 $llen = 0;
1034             }
1035             elsif($p eq '')
1036             {
1037 33 100       87 print $handle (defined $line ? $line : '')."\n";
1038 33         54 $line = '';
1039 33         73 $llen = 0;
1040             }
1041             elsif($can_wrap)
1042             {
1043 95         458 my @words = split(/\s+/, $p);
1044 95   100     349 while($llen>$slen or @words)
1045             {
1046 1326         2244 my $w = shift(@words);
1047 1326         2198 my $l = length($w);
1048 1326 100 100     6977 if(not $l or $l+$llen >= $length)
1049             {
1050 220 50       631 print $handle (defined $line ? $line : '')."\n";
1051 220         322 $llen = 0;
1052 220         380 $line = '';
1053 220         318 $first = 0;
1054             }
1055 1326 100       2945 if($l)
1056             {
1057 1231 100       2570 unless(defined $line)
    100          
1058             {
1059 60         95 $line = '';
1060             }
1061 0         0 elsif($llen)
1062             {
1063 1011         1594 $line .= ' ';
1064 1011         1536 $llen += 1;
1065             }
1066             else
1067             {
1068 160         260 $line = $stab;
1069 160         254 $llen = $slen;
1070             }
1071 1231         1993 $line .= $w;
1072 1231         2878 $llen += $l;
1073             }
1074             }
1075 95         150 $line = '';
1076 95         500 $llen = 0;
1077             }
1078             else # wrapping makes no sense
1079             {
1080 0 0       0 print $handle (defined $line ? $line : '').$p."\n";
1081 0         0 $line = '';
1082 0         0 $llen = 0;
1083             }
1084             }
1085             }
1086              
1087             # Produce wrapped text from POD.
1088             sub INT_pod_print
1089             {
1090 0     0 0 0 my ($handle, $length) = (shift, shift);
1091 0         0 require Pod::Text;
1092 0         0 my $pod = Pod::Text->new(width=>$length);
1093 0         0 $pod->output_fh($handle);
1094 0         0 $pod->parse_string_document($_[0]);
1095             }
1096              
1097             # Produce POD output from text.
1098             sub print_pod
1099             {
1100 4     4 1 8 my $self = shift;
1101 4         9 my $handle = $self->{config}{output};
1102 4 50       14 $handle = \*STDOUT unless defined $handle;
1103              
1104 4         12 my $prog = escape_pod($self->{config}{program});
1105 4         14 my $tagline = escape_pod($self->{config}{tagline});
1106             # usage line is unescaped
1107 4         12 my $usage = $self->{config}{usage};
1108 4         9 my @desc = (); # usage might come from here
1109             @desc = split("\n", $self->{config}{info}, -1)
1110 4 100       21 if(defined $self->{config}{info});
1111              
1112 4 100 66     21 $tagline = escape_pod(shift @desc)
1113             unless(defined $tagline or not defined $prog);
1114              
1115 4   100     20 while(@desc and $desc[0] =~ /^\s*$/){ shift @desc; }
  1         7  
1116              
1117 4 100 100     19 unless(defined $usage or not @desc)
1118             {
1119 1 50       9 if(lc($desc[0]) =~ /^\s*usage:\s*(.*\S?)\s*$/)
1120             {
1121 1 50       5 $usage = $1 if $1 ne '';
1122 1         2 shift(@desc);
1123 1   33     9 while(@desc and $desc[0] =~ /^\s*$/){ shift @desc; }
  0         0  
1124              
1125             # if the real deal follows on a later line
1126 1 50 33     7 if(not defined $usage and @desc)
1127             {
1128 1         3 $usage = shift @desc;
1129 1         5 $usage =~ s/^\s*//;
1130 1         10 $usage =~ s/\s*$//;
1131 1   66     8 while(@desc and $desc[0] =~ /^\s*$/){ shift @desc; }
  1         6  
1132             }
1133             }
1134             }
1135 4 50       11 if(defined $prog)
1136             {
1137 4         17 print $handle "\n=head1 NAME\n\n$prog";
1138 4 50       14 print $handle " - $tagline" if defined $tagline;
1139 4         10 print $handle "\n";
1140             }
1141 4 100       11 if(defined $usage)
1142             {
1143 2         6 print $handle "\n=head1 SYNOPSIS\n\n";
1144 2         9 print $handle "\t$_\n" for(split("\n", $usage));
1145             }
1146 4 100 66     20 if(@desc or defined $self->{config}{infopod})
1147             {
1148 1         3 print $handle "\n=head1 DESCRIPTION\n\n";
1149 1 50       4 if(defined $self->{config}{infopod})
1150             {
1151 0         0 print $handle $self->{config}{infopod};
1152             } else
1153             {
1154 1         3 for(@desc){ print $handle escape_pod($_), "\n"; }
  1         3  
1155             }
1156             }
1157 4 50       12 my $nprog = defined $prog ? $prog : 'some_program';
1158              
1159 4         9 print $handle "\n=head1 PARAMETERS\n\n";
1160 4         10 print $handle "These are the general rules for specifying parameters to this program:\n";
1161 4         10 print $handle "\n\t$nprog ";
1162 4 50       10 if($self->{config}{lazy})
1163             {
1164 4         13 print $handle escape_pod($example{lazy}),"\n\n";
1165 4         13 print $handle escape_pod($lazyinfo),"\n";
1166             }
1167             else
1168             {
1169 0         0 print $handle escape_pod($example{normal}),"\n";
1170             }
1171 4         8 print $handle "\n";
1172 4         9 for(@morehelp)
1173             {
1174 32         63 print $handle escape_pod($_);
1175             }
1176 4         8 print $handle "\n\nThe available parameters are these, default values (in Perl-compatible syntax) at the time of generating this document following the long/short names:\n";
1177 4         7 print $handle "\n=over 2\n";
1178 4         8 for my $k (sort keys %{$self->{param}})
  4         31  
1179             {
1180             print $handle "\n=item B<".escape_pod($k).">".
1181 28 100       60 ($self->{short}{$k} ne '' ? ', B<'.escape_pod($self->{short}{$k}).'>' : '').
1182             " ($typename[$self->{type}{$k}])".
1183             "\n\n";
1184 28 100       95 my @content = $k eq 'help'
1185             ? 0
1186             : split("\n", $self->par_content($k, 'dump', 1));
1187 28         1449 print $handle "\t$_\n" for(@content);
1188 28         51 print $handle "\n".escape_pod(${$self->{help}{$k}})."\n";
  28         84  
1189 28 100       96 print $handle "\n".$self->{extrahelp}."\n" if($k eq 'help');
1190             }
1191 4         28 print $handle "\n=back\n";
1192              
1193             # closing with some simple sections
1194 4         9 my @podsections;
1195             # user-provided
1196 4         14 push(@podsections, @{$self->{config}{extrapod}})
1197 4 50       24 if(defined $self->{config}{extrapod});
1198              
1199             # standard
1200 4         17 for( ['BUGS','bugs'], ['AUTHOR', 'author'], ['LICENSE AND COPYRIGHT', 'copyright'] )
1201             {
1202             push(@podsections, {head=>$_->[0], body=>$self->{config}{$_->[1]}})
1203 12 100       55 if(defined $self->{config}{$_->[1]});
1204             }
1205              
1206 4         15 for my $ps (@podsections)
1207             {
1208 16         36 print $handle "\n=head1 $ps->{head}\n";
1209 16 100       54 print $handle "\n",$ps->{verbatim} ? $ps->{body} : escape_pod($ps->{body}),"\n";
1210             }
1211              
1212 4         21 print $handle "\n=cut\n";
1213             }
1214              
1215             sub _pm
1216             {
1217 0     0   0 my $self = shift;
1218 0         0 my $k = shift;
1219             return ( ($self->{type}{$k} == $scalar
1220             and ( $self->{flags}{$k} & $switch
1221             or (defined $self->{arg}{$k} and $self->{arg}{$k} eq '') ))
1222 0 0 0     0 and ($self->{default}{$k}) ) ? '+' : '-';
1223             }
1224              
1225             # Well, _the_ help.
1226             sub help
1227             {
1228 15     15 1 25 my $self = shift;
1229 15         35 my $handle = $self->{config}{output};
1230 15 50       66 $handle = \*STDOUT unless defined $handle;
1231             my $indent = $self->{config}{posixhelp}
1232             ? $self->{arglength} + 7 # -s, --name[=arg]
1233 15 50       89 : $self->{length} + 4; # longest long name + ", s " (s being the short name)
1234              
1235             # Trying to format it fitting the screen to ease eye navigation in large parameter lists.
1236 15         31 my $linewidth = 0;
1237 15 50       39 if(defined $self->{config}{linewidth})
    0          
    0          
1238             {
1239 15         36 $linewidth = $self->{config}{linewidth};
1240             }
1241 0         0 elsif(eval { require Term::ReadKey })
1242             {
1243             # This can die on me! So run it in eval.
1244 0         0 my @s = eval { Term::ReadKey::GetTerminalSize(); };
  0         0  
1245 0 0       0 $linewidth = $s[0] if @s;
1246             }
1247 0         0 elsif(eval { require IPC::Run })
1248             {
1249 0         0 my ($in, $err);
1250 0 0       0 if(eval { IPC::Run::run([qw(tput cols)], \$in, \$linewidth, \$err) })
  0         0  
1251             {
1252 0         0 chomp($linewidth);
1253 0         0 $linewidth += 0; # ensure a number;
1254             }
1255             }
1256 15 50       40 my $prosewidth = $linewidth > 80 ? 80 : $linewidth;
1257              
1258 15 100       82 if($self->{param}{help} =~ /^(-\d+),?(.*)$/)
1259             {
1260 9         30 my $code = $1;
1261 9         31 my @keys = split(',', $2);
1262 9         19 my $badkeys;
1263 9         24 for(@keys)
1264             {
1265 5 50       17 unless(exists $self->{param}{$_})
1266             {
1267 0         0 ++$badkeys;
1268 0         0 $self->INT_error("Parameter $_ is not defined!");
1269             }
1270             }
1271             return
1272 9 50       21 if $badkeys;
1273              
1274 9 100       93 if($code == -1)
    100          
    100          
    100          
    100          
    50          
1275             { # param list, wrapped to screen
1276             INT_wrap_print( $handle, '', "\t", $linewidth, "List of parameters: "
1277 1         4 , join(' ', sort keys %{$self->{param}}) );
  1         12  
1278             }
1279             elsif($code == -2)
1280             { # param list, one one each line
1281 1         4 print $handle join("\n", sort keys %{$self->{param}})."\n";
  1         12  
1282             }
1283             elsif($code == -3)
1284             { # param list, one one each line, without builtins
1285 1         5 my $builtin = builtins($self->{config});
1286 1         4 my @pars = sort grep {not $builtin->{$_}} keys %{$self->{param}};
  7         20  
  1         4  
1287 1 50       11 print $handle join("\n", @pars)."\n" if @pars;
1288             }
1289             elsif($code == -10)
1290             { # dump values, suitable to eval to a big array
1291 1         4 my $first = 1;
1292 1         3 for(@keys)
1293             {
1294 2 100       97 if($first){ $first=0; }
  1         3  
1295 1         3 else{ print $handle ", "; }
1296 2         8 print $handle $self->par_content($_, 'dump', 1);
1297             }
1298             }
1299             elsif($code == -11)
1300             { # line values
1301 1         4 for(@keys){ print $handle $self->par_content($_, 'lines'); }
  3         9  
1302             }
1303             elsif($code == -100)
1304             {
1305 4         14 $self->print_pod();
1306             }
1307             else
1308             {
1309 0         0 $self->INT_error("bogus help code $code");
1310 0         0 INT_wrap_print(\*STDERR, '', '', $linewidth, "\nHelp for help:\n", ${$self->{help}{help}});
  0         0  
1311 0         0 INT_wrap_print(\*STDERR, '','', $linewidth, $self->{extrahelp});
1312             }
1313 9         77 return;
1314             }
1315              
1316             # Anything with at least two characters could be a parameter name.
1317 6 50       20 if($self->{param}{help} =~ /../)
1318             {
1319 0         0 my $k = $self->{param}{help};
1320 0 0       0 if(exists $self->{param}{$k})
1321             {
1322 0         0 my $val = $self->{arg}{$k};
1323 0         0 my $s = $self->{short}{$k};
1324 0         0 my $type = $self->{type}{$k};
1325 0         0 my $flags = $self->{flags}{$k};
1326 0         0 my $pm = $self->_pm($k);
1327 0 0       0 $val = 'val' unless defined $val;
1328             print $handle $self->{config}{posixhelp}
1329 0 0       0 ? "Option:\n\t"
    0          
    0          
1330             . ($s ne '' ? "$pm$s, " : '')
1331             . $pm.$pm.$k."\n"
1332             : "Parameter:\n\t$k".($s ne '' ? ", $s" : '')."\n";
1333 0         0 my $c = $self->par_content($k, 'dump', 1);
1334 0         0 $c =~ s/\n$//;
1335 0         0 $c =~s/\n/\n\t/g;
1336 0         0 print $handle "\nValue:\n\t$c\n";
1337 0         0 my $dc = $self->par_content($k, 'dump', 1, 'default');
1338 0         0 $dc =~ s/\n$//;
1339 0         0 $dc =~s/\n/\n\t/g;
1340 0 0       0 print $handle "\nDefault value: "
1341             . ($c eq $dc ? "same" : "\n\t$dc")
1342             . "\n";
1343 0         0 print $handle "\nSyntax notes:\n";
1344 0         0 my $notes = '';
1345 0 0       0 if($type eq $scalar)
    0          
1346             {
1347 0         0 my @switchcount;
1348 0 0 0     0 push(@switchcount, "switch")
1349             if($flags & $switch or not $flags & $count);
1350 0 0 0     0 push(@switchcount, "counter")
1351             if($flags & $count or not $flags & $switch);
1352 0 0       0 $notes .= $flags & $arg
    0          
    0          
1353             ? "This is a scalar parameter that requires an explicit"
1354             . " argument value."
1355             . " You can choose the canonical form --$k=$val or let"
1356             . " the value follow like --$k $val"
1357             . ( $s ne ''
1358             ? " (short option only: both -$s $val and -$s$val are valid)"
1359             : '' )
1360             . '.'
1361             : $val ne ''
1362             ? "This is a scalar parameter with an optional argument"
1363             . " value than can only be provided by attaching it"
1364             . " with an equal sign or another operator,"
1365             . " e.g. --$k=$val."
1366             : "This is a parameter intended as a ".join(" or ", @switchcount)
1367             . ", providing an argument value is not required.";
1368 0 0       0 $notes .= " The value can be built"
1369             . " in multiple steps via operators for appending (--$k.=) or"
1370             . " arithmetic (--$k+= for addition, --$k-=, --$k*=, and --$k/= for"
1371             . " subtraction, multiplication, and division)."
1372             unless $flags & $switch;
1373 0 0 0     0 $notes .= "\n\nThe above applies to the short -$s, too, with the"
1374             . " addition that the equal sign can be dropped for"
1375             . " two-character operators, like -$s+3."
1376             if(not $flags & $switch and $s ne '');
1377 0 0       0 $notes .= $flags & $count
    0          
    0          
    0          
    0          
    0          
1378             ? "\n\nEach appearance of --$k "
1379             . ($s ne '' ? "and -$s " : '')
1380             . "increments the value by 1, while ++$k "
1381             . ($s ne '' ? "and +$s " : '')
1382             . "set it to zero (false)."
1383             : "\n\nJust --$k"
1384             . ($s ne '' ? " or -$s " : '')
1385             . "sets the value to 1 (engages the switch), while ++$k"
1386             . ($s ne '' ? " or +$s " : '')
1387             . "sets the value to 0 (disengages the switch)."
1388             unless($flags & $arg);
1389 0         0 } elsif(grep {$_ == $type} ($array, $hash))
1390             {
1391 0 0       0 $notes .= $type == $hash
1392             ? 'This is a hash (name-value store) parameter. An option argument'
1393             . ' consists of = to'
1394             . ' store the actual value with for given key.'
1395             : 'This is an array parameter.';
1396 0 0       0 $notes .= ' Assigned values are appended even if the append operator .='
1397             . ' is not used explicitly.'
1398             if $flags & $append;
1399 0 0       0 $notes .= $flags & $arg
1400             ? ' An explicit argument to the option is required.'
1401             . " It is equivalent to specify --$k=$val or --$k $val."
1402             . " A value is explcitly appended to the "
1403             . "$typename[$type] via --$k.=$val."
1404             : " An option argument can be given via --$k=$val or --$k.=$val to "
1405             . " explicitly append to the $typename[$self->{type}{$k}].";
1406 0 0       0 $notes .= ' For this parameter, the appending operator .= is implicit.'
1407             if $flags & $append;
1408 0 0       0 $notes .= "\n\nThe above applies also to the short option -$s"
    0          
1409             . ($flags & $arg
1410             ? ", with added possibility of directly attaching the argument via -$s$val."
1411             : ".")
1412             if $s ne '';
1413 0         0 $notes .= "\n\n";
1414 0         0 $notes .= "Multiple values can be provided with a single separator character"
1415             . " that is specified between slashes, like --$k/,/=a,b,c.";
1416             } else
1417             {
1418 0         0 $notes .= 'I do not know what kind of parameter that is.'
1419             }
1420             $notes .= "\n\n"
1421             . 'Lazy option syntax is active: you can drop one or both of the'
1422             . ' leading \'--\', also the \'-\' of the short form. Beware: just'
1423             . ' -'.$k.' is a group of short options, while -'.$k.'=foo would be'
1424             . ' an assignment to '.$k.'.'
1425 0 0       0 if $self->{config}{lazy};
1426 0         0 INT_wrap_print( $handle, "\t", "\t", $prosewidth, $notes);
1427 0         0 print $handle "\nHelp:";
1428 0 0       0 if(${$self->{help}{$k}} ne '')
  0         0  
1429             {
1430 0         0 print $handle "\n";
1431 0         0 INT_wrap_print($handle, "\t","\t", $prosewidth, ${$self->{help}{$k}});
  0         0  
1432             } else
1433             {
1434 0         0 print $handle " none";
1435             }
1436             INT_wrap_print($handle, "\t","\t", $prosewidth, $self->{extrahelp})
1437 0 0       0 if $k eq 'help';
1438 0         0 print "\n";
1439             } else
1440             {
1441 0         0 $self->INT_error("Parameter $k is not defined!");
1442             }
1443 0         0 return;
1444             }
1445              
1446 6 50       28 if($self->{param}{help} =~ /\D/)
1447             {
1448 0         0 $self->INT_error("You specified an invalid help level (parameter name needs two characters minimum).");
1449 0         0 return;
1450             }
1451              
1452 6 50       22 my $vst = (defined $self->{config}{version} ? "v$self->{config}{version} " : '');
1453 6 100       18 if(defined $self->{config}{tagline})
1454             {
1455 3         19 INT_wrap_print($handle, '', '', $prosewidth, "\n$self->{config}{program} ${vst}- ",$self->{config}{tagline});
1456 3 100       13 if(defined $self->{config}{usage})
1457             {
1458 1         3 print $handle "\nUsage:\n";
1459 1         5 INT_wrap_print($handle, "\t","\t", $prosewidth, $self->{config}{usage});
1460             }
1461 3 100       17 if(defined $self->{config}{info})
    50          
1462             {
1463 1         6 INT_wrap_print($handle, '', '', $prosewidth, "\n".$self->{config}{info});
1464             } elsif(defined $self->{config}{infopod})
1465             {
1466 0         0 print {$handle} "\n";
  0         0  
1467 0         0 INT_pod_print($handle, $prosewidth, $self->{config}{infopod});
1468             }
1469             INT_wrap_print($handle, '', '', $prosewidth, "\n$self->{config}{copyright}")
1470 3 50       20 if defined $self->{config}{copyright};
1471             }
1472             else
1473             {
1474 3 50       10 if(defined $self->{config}{info})
    0          
1475             {
1476             INT_wrap_print($handle, '', '', $prosewidth, "\n$self->{config}{program} ${vst}- ".$self->{config}{info})
1477 3         23 } elsif(defined $self->{config}{infopod})
1478             {
1479 0         0 print {$handle} "\n$self->{config}{program} ${vst}\n";
  0         0  
1480 0         0 INT_pod_print($handle, $prosewidth, $self->{config}{infopod});
1481             }
1482              
1483             INT_wrap_print($handle, '', '', $prosewidth, "\n$self->{config}{copyright}")
1484 3 50       20 if defined $self->{config}{copyright};
1485             }
1486              
1487 6         20 my $level = 0+$self->{param}{help};
1488 6         12 my $tablehead = '';
1489              
1490 6 50       27 if($self->{config}{posixhelp})
1491             {
1492 0         0 INT_wrap_print( $handle, '', '', $prosewidth
1493             , "\nShort options can be grouped and non-optional arguments"
1494             . " can follow without equal sign. Force options end with '--'."
1495             . " Switches on with -, off with +."
1496             . " See --help=par for details on possible advanced syntax with option"
1497             . " --par." );
1498             } else
1499             {
1500 6         13 my $preprint = "NAME, SHORT ";
1501 6 50       18 $indent = length($preprint)
1502             if length($preprint) > $indent;
1503 6         17 $tablehead = $preprint
1504             . INT_indent_string($indent, length($preprint))."VALUE [# DESCRIPTION]\n";
1505 6         20 INT_wrap_print( $handle, '', '', $prosewidth
1506             , "\nGeneric parameter example (list of real parameters follows):\n" );
1507 6         13 print $handle "\n";
1508 6 50       19 if($self->{config}{lazy})
1509             {
1510 6         29 print $handle "\t$self->{config}{program} $example{lazy}\n";
1511 6 100       19 if($level > 1)
1512             {
1513 2         7 INT_wrap_print($handle, '', '', $prosewidth, "\n", $lazyinfo);
1514             }
1515             }
1516             else
1517             {
1518 0         0 print $handle "\t$self->{config}{program} $example{normal}\n";
1519             }
1520 6         13 print $handle "\n";
1521 6 100       16 if($level > 1)
1522             {
1523 2         10 INT_wrap_print($handle, '', '', $prosewidth, @morehelp)
1524             } else
1525             { # Don't waste so many lines by default.
1526 4         11 INT_wrap_print($handle, '', '', $prosewidth
1527             , "Just mentioning -s equals -s=1 (true), while +s equals -s=0 (false)."
1528             , " The separator \"--\" stops option parsing."
1529             )
1530             }
1531 6         20 INT_wrap_print($handle, '', '', $prosewidth, "\nRecognized parameters:");
1532             }
1533 6         15 my @hidden_nonshort;
1534             my @hidden_level;
1535 6 50       20 if($self->{config}{ordered})
1536             {
1537 0         0 foreach my $s (@{$self->{section}})
  0         0  
1538             {
1539 0 0       0 if($level >= $s->{minlevel})
1540             {
1541             INT_wrap_print( $handle, '', '', $prosewidth, "\n".$s->{section} )
1542 0 0       0 if($s->{section} ne '');
1543 0         0 INT_wrap_print( $handle, '', '', $prosewidth, ${$s->{help}} )
1544 0 0       0 if(${$s->{help}} ne '');
  0         0  
1545 0         0 print $handle "\n".$tablehead;
1546             }
1547             # Go through the parameters at least to count the hidden ones.
1548 0         0 for my $k (@{$s->{member}})
  0         0  
1549             {
1550 0         0 $self->INT_param_help( $handle, $k, $level, $prosewidth, $indent
1551             , \@hidden_nonshort, \@hidden_level );
1552             }
1553             }
1554             } else
1555             {
1556 6         17 print $handle "\n".$tablehead;
1557 6         13 for my $k ( sort keys %{$self->{param}} )
  6         53  
1558             {
1559 42         162 $self->INT_param_help( $handle, $k, $level, $prosewidth, $indent
1560             , \@hidden_nonshort, \@hidden_level );
1561             }
1562             }
1563 6 50       27 if(@hidden_nonshort)
1564             {
1565 0         0 print $handle "\n";
1566 0 0       0 if($level> 1)
1567             {
1568 0         0 INT_wrap_print( $handle, '', '', $prosewidth,
1569             "Hidden parameters intended primarily for config files:" );
1570 0         0 INT_wrap_print( $handle, "\t", "\t", $prosewidth, "@hidden_nonshort" );
1571             } else
1572             {
1573 0 0       0 INT_wrap_print( $handle, '', '', $prosewidth, 'There'
1574             . ( @hidden_nonshort == 1
1575             ? 'is one hidden config file parameter'
1576             : 'are '.(0+@hidden_nonshort).' hidden config file parameters' ) );
1577             }
1578             }
1579 6 50       20 if(@hidden_level)
1580             {
1581 0         0 print $handle "\n";
1582 0 0       0 if($level > 1)
1583             {
1584 0         0 INT_wrap_print( $handle, '', "\t", $prosewidth
1585             , "Parameters explained at higher help levels: @hidden_level" );
1586             } else
1587             {
1588 0 0       0 INT_wrap_print( $handle, '', '', $prosewidth, "There "
1589             . ( @hidden_level == 1
1590             ? 'is one parameter'
1591             : 'are '.(0+@hidden_level).' parameters' )
1592             . ' explained at higher help levels.' );
1593             }
1594             }
1595 6         25 print $handle "\n";
1596             }
1597              
1598             sub INT_param_help
1599             {
1600 42     42 0 67 my $self = shift;
1601 42         112 my ($handle, $k, $level, $linewidth, $indent, $hidden_nonshort, $hidden_level) = @_;
1602              
1603             # Reasons to hide from current printout.
1604 42         73 my $hide = 0;
1605 42 0 33     133 if( $self->{config}{hidenonshort} and $self->{short}{$k} eq ''
      0        
      33        
1606             and not ($k eq 'version' and defined $self->{config}{version}) )
1607             {
1608 0         0 ++$hide;
1609 0         0 push(@{$hidden_nonshort}, $k);
  0         0  
1610             }
1611 42 50       112 if($level < $self->{level}{$k})
1612             {
1613 0         0 ++$hide;
1614 0         0 push(@{$hidden_level}, $k);
  0         0  
1615             }
1616             return
1617 42 50       115 if $hide;
1618              
1619 42 50       100 if($self->{config}{posixhelp})
1620             {
1621 0         0 $self->INT_param_help_posix($handle, $k, $linewidth, $indent);
1622             } else
1623             {
1624 42         101 $self->INT_param_help_table($handle, $k, $linewidth, $indent);
1625             }
1626             }
1627              
1628             sub INT_param_help_table
1629             {
1630 42     42 0 73 my $self = shift;
1631 42         91 my ($handle, $k, $linewidth, $indent) = @_;
1632            
1633             # This format will change, I presume.
1634             # This is the parameter syntax-agnostic print, where that
1635             # information is shown elsewhere. People are used to
1636             # -s, --long= Blablabla [default]
1637             # Let's go there.
1638             # long, s
1639 42         71 my $prefix = $k;
1640 42 100       159 $prefix .= ", $self->{short}{$k}" if($self->{short}{$k} ne '');
1641 42         86 $prefix .= ' ';
1642 42         115 my $content = $self->par_content($k, 'dump', 0);
1643 42         2338 my $stab = ' ' x $indent;
1644 42         69 my @help = split("\n", ${$self->{help}{$k}});
  42         152  
1645             push(@help, split("\n", $self->{extrahelp}))
1646             if( $k eq 'help' and $self->{param}{help} > 1
1647 42 100 100     159 and defined $self->{extrahelp} );
      66        
1648 42   33     220 $help[0] = $content.(@help and $help[0] ne '' ? " # $help[0]" : '');
1649 42         125 for(my $i=0; $i<@help; ++$i)
1650             {
1651 52 100       203 INT_wrap_print( $handle, ( $i==0
1652             ? $prefix.INT_indent_string($indent, length($prefix))
1653             : $stab ) , $stab, $linewidth, $help[$i] );
1654             }
1655             }
1656              
1657             sub INT_param_help_posix
1658             {
1659 0     0 0 0 my $self = shift;
1660 0         0 my ($handle, $k, $linewidth, $indent) = @_;
1661 0         0 my $stab = ' ' x $indent;
1662 0         0 my $prefix = '';
1663 0         0 my $pm = $self->_pm($k);
1664 0 0       0 $prefix = $self->{short}{$k} ne '' ? "$pm$self->{short}{$k}, " : ' ';
1665 0         0 $prefix .= $pm.$pm.$self->INT_namearg($k).' ';
1666 0         0 my @help = split("\n", ${$self->{help}{$k}});
  0         0  
1667             push(@help, split("\n", $self->{extrahelp}))
1668 0 0 0     0 if($k eq 'help' and $self->{param}{help} > 1);
1669             # Splitting the empty string does not give an array with one empty string,
1670             # but an empty array instead.
1671 0 0       0 push(@help, '')
1672             unless @help;
1673 0 0       0 $help[0] = 'disable: '.$help[0]
1674             if $pm eq '+';
1675 0         0 for(my $i=0; $i<@help; ++$i)
1676             {
1677 0 0       0 INT_wrap_print( $handle, ( $i==0
1678             ? $prefix.INT_indent_string($indent, length($prefix), ' ')
1679             : $stab ) , $stab, $linewidth, $help[$i] );
1680             }
1681             }
1682              
1683             # Have to cover two use cases:
1684             # 1. Have defined param space, just want values.
1685             # 2. Want to construct param space from file.
1686             # Parse configured config files.
1687             sub INT_parse_files
1688             {
1689 63     63 0 141 my $self = shift;
1690 63         113 my $construct = shift;
1691              
1692 63         107 for my $file (@{$self->{param}{config}})
  63         239  
1693             {
1694 10 100       42 return 0 unless $self->parse_file($file, $construct);
1695             }
1696 62         417 return 1;
1697             }
1698              
1699             # check if it's existing and not a directory
1700             # _not_ explicitly checking for files as that would exclude things that otherwise would work as files just fine
1701             sub INT_filelike
1702             {
1703 1302   66 1302 0 13717 return (-e $_[0] and not -d $_[0])
1704             }
1705              
1706             # Look for given config file name in configured directory or search for it in
1707             # the list of likely places. Appending the ending .conf is also tried.
1708             sub INT_find_config
1709             {
1710 101     101 0 601 my $self = shift;
1711 101         165 my $name = shift;
1712              
1713 101 100       921 return $name if File::Spec->file_name_is_absolute($name);
1714              
1715             # Let's special-case the current working directory. Do not want to spell it
1716             # out for the directory search loop.
1717             # But yes, it is a bit of duplication with the .conf addition. Sorry.
1718 86 100       236 return $name if(INT_filelike($name));
1719 84 50       318 return "$name.conf" if(INT_filelike("$name.conf"));
1720              
1721 84         196 my $path;
1722             my @dirs;
1723             #determine directory to search config files in
1724 84 50       270 if(defined $self->{config}{confdir})
1725             {
1726 0         0 @dirs = ($self->{config}{confdir});
1727             }
1728             else
1729             {
1730             @dirs = (
1731             File::Spec->catfile($ENV{HOME},'.'.$self->{config}{program})
1732             ,File::Spec->catfile($Bin,'..','etc',$self->{config}{program})
1733             ,File::Spec->catfile($Bin,'..','etc')
1734             ,File::Spec->catfile($Bin,'etc')
1735             ,$Bin
1736             ,File::Spec->catfile($ENV{HOME},'.config',$self->{config}{program})
1737 84         3778 ,File::Spec->catfile($ENV{HOME},'.config')
1738             );
1739             }
1740              
1741 84         467 for my $d (@dirs)
1742             {
1743 566         4452 my $f = File::Spec->catfile($d, $name);
1744 566 100       1650 $f .= '.conf' unless INT_filelike($f);
1745 566 100       1195 if(INT_filelike($f))
1746             {
1747 11         25 $path = $f;
1748 11         31 last;
1749             }
1750             }
1751              
1752 84 100       278 $self->INT_verb_msg("Found config: $path\n") if defined $path;
1753 84         306 return $path
1754             }
1755              
1756             # Parse one given file.
1757             sub parse_file
1758             {
1759 17     17 1 92 my $self = shift;
1760              
1761 17         35 my $confname = shift;
1762 17         32 my $construct = shift;
1763              
1764 17         31 my $lend = '(\012\015|\012|\015)';
1765 17         35 my $nlend = '[^\012\015]';
1766 17         26 my $olderrs = @{$self->{errors}};
  17         69  
1767 17         2199 require IO::File;
1768              
1769             # TODO: Support loading multiple occurences in order.
1770 17         33581 my $file = $self->INT_find_config($confname);
1771 17         121 my $cdat = new IO::File;
1772 17 50       669 if(not defined $file)
    50          
    50          
1773             {
1774 0 0       0 $self->INT_error("Couldn't find config file $confname!") unless $self->{config}{nocomplain};
1775             }
1776 5         24 elsif(grep {$_ eq $file} @{$self->{parse_chain}})
  17         86  
1777             {
1778 0         0 $self->INT_error("Trying to parse config file $file twice in one chain!");
1779             }
1780             elsif($cdat->open($file, '<'))
1781             {
1782 17         1362 push(@{$self->{parse_chain}}, $file);
  17         66  
1783 17         29 push(@{$self->{files}}, $file);
  17         48  
1784 17 50       75 if(defined $self->{config}{binmode})
1785             {
1786 0         0 binmode($cdat, $self->{config}{binmode});
1787             }
1788             #do we need or want binmode for newlines?
1789 17         34 my $multiline = '';
1790 17         31 my $mcollect = 0;
1791 17         34 my $ender = '';
1792 17         33 my $mkey ='';
1793 17         27 my $mop = '';
1794 17         33 my %curpar;
1795 17         48 my $ln = 0;
1796 17         375 while(<$cdat>)
1797             {
1798 298         505 ++$ln;
1799 298 100       520 unless($mcollect)
1800             {
1801 263 100 100     1958 next if ($_ =~ /^\s*#/ or $_ =~ /^\s*#?\s*$lend$/o);
1802              
1803 123 100       616 if($_ =~ /^=($nlend+)$lend*$/o)
1804             {
1805 39         108 my $meta = $1;
1806 39 100       93 if($construct)
1807             {
1808 13 100       65 if($meta =~ /^param file\s*(\(([^)]*)\)|)\s*for\s*(.+)$/)
    50          
    50          
    50          
1809             {
1810 1         6 $self->{config}{program} = $3;
1811 1         8 $self->INT_verb_msg("This file is for $self->{config}{program}.\n");
1812 1 50 33     6 if(defined $2 and $2 =~ /^(.+)$/)
1813             {
1814 0         0 for my $s (split(',', $1))
1815             {
1816 0         0 $self->INT_verb_msg("Activating option $s.\n");
1817 0 0       0 $self->INT_error("$file:$ln: eval option not supported anymore.") if($s eq 'eval');
1818 0         0 $self->{config}{$s} = 1;
1819             }
1820             }
1821             }
1822             elsif($meta =~ /^version\s*(.+)$/)
1823             {
1824 0         0 $self->{config}{version} = $1;
1825             }
1826             elsif($meta =~ /^info\s(.*)$/)
1827             {
1828 0         0 $self->{config}{info} .= $1."\n"; #dos, unix... whatever...
1829             }
1830             elsif($meta =~ /^infopod\s(.*)$/)
1831             {
1832 0         0 $self->{config}{infopod} .= $1."\n"; #dos, unix... whatever...
1833             }
1834             }
1835             # Groping for parameter description in any case.
1836 39 100       259 if($meta =~ /^(long|key)\s*(\S*)(\s*short\s*(\S)|)(\s*type\s*(\S+)|)/)
    100          
    100          
1837             {
1838 16 100       144 %curpar = (long=>$2, short=>defined $4 ? $4 : '', help=>'');
1839 16 50       49 my $type = defined $6 ? $6 : '';
1840 16 50       43 if(exists $typemap{$type})
1841             {
1842 16         47 $curpar{value} = $initval[$typemap{$type}];
1843 16         71 $self->INT_verb_msg("switching to key $curpar{long} / $curpar{short}\n");
1844             }
1845 0         0 else{ $self->INT_error("$file:$ln: unknown type $type"); %curpar = (); }
  0         0  
1846             }
1847             elsif($meta =~ /^(help|desc)\s(.*)$/)
1848             {
1849 16 50       113 $curpar{help} .= $curpar{help} ne '' ? "\n" : "" . $2;
1850             }
1851             elsif($meta =~ /^include\s*(.+)$/)
1852             {
1853 5         11 my $incfile = $1;
1854             # Avoid endless looping by making this path explicit.
1855             # Search for config file vicious if you tell it to load ../config and that also contains ../config ...
1856 5         19 $self->INT_verb_msg("including $incfile\n");
1857 5 50       72 unless(File::Spec->file_name_is_absolute($incfile))
1858             {
1859 5         243 my $dir = dirname($file);
1860 5         63 $dir = File::Spec->rel2abs($dir);
1861 5         51 $incfile = File::Spec->catfile($dir, $incfile);
1862 5 50       162 $incfile .= '.conf'
1863             unless -e $incfile;
1864             }
1865 5         33 $self->parse_file($incfile, $construct);
1866             }
1867             }
1868             else
1869             {
1870 84 100       2166 if($_ =~ /^\s*($parname)\s*($lopex)\s*($nlend*)$lend$/)
    50          
    50          
1871             {
1872 74         307 my ($par,$op,$val) = ($1,$2,$3);
1873             #remove trailing spaces
1874 74         383 $val =~ s/\s*$//;
1875             #remove quotes
1876 74         221 $val =~ s/^"(.*)"$/$1/;
1877 74         308 $self->INT_definery(\%curpar, $par, $construct);
1878 74 100       228 if(exists $self->{param}{$par})
1879             {
1880 71         294 $self->INT_verb_msg("Setting $par $op $val\n");
1881 71         195 $self->INT_apply_op($par, $op, $val, $file);
1882             }
1883             else
1884             {
1885 3 100       34 unless($self->{config}{ignore_unknown})
1886             {
1887 1 50       4 $self->{param}{help} = 1 if($self->{config}{nanny});
1888 1         7 $self->INT_error("$file:$ln: unknown parameter $par");
1889             }
1890             }
1891             }
1892             elsif($_ =~ /^\s*($parname)\s*$lend$/)
1893             {
1894 0         0 my $par = $1;
1895 0         0 $self->INT_definery(\%curpar, $par, $construct);
1896 0 0       0 if(exists $self->{param}{$par})
1897             {
1898 0         0 $self->INT_verb_msg("Setting $par so that it is true.\n");
1899 0         0 $self->{param}{$par} = $trueval[$self->{type}{$par}];
1900             }
1901             else
1902             {
1903 0 0       0 unless($self->{config}{ignore_unknown})
1904             {
1905 0 0       0 $self->{param}{help} = 1 if($self->{config}{nanny});
1906 0         0 $self->INT_error("$file:$ln: unknown parameter $par");
1907             }
1908             }
1909             }
1910             elsif($_ =~ /^\s*($parname)\s*([$ops]?)<<(.*)$/)
1911             {
1912 10         61 $ender = $3;
1913 10 100       41 $mop = $2 ne '' ? $2 : '=';
1914 10         22 $mkey = $1;
1915 10         13 $mcollect = 1;
1916 10 100       57 $mop .= '=' unless $mop =~ /=$/;
1917 10         46 $self->INT_verb_msg("Reading for $mkey...(till $ender)\n");
1918             }
1919             }
1920             }
1921             else
1922             {
1923 35         135 $self->INT_verb_msg("collect: $_");
1924 35 100       339 unless($_ =~ /^$ender$/)
1925             {
1926 25         237 s/(^|$nlend)$lend$/$1\n/o;
1927 25         90 $multiline .= $_;
1928             }
1929             else
1930             {
1931 10         18 $mcollect = 0;
1932             # remove last line end
1933 10         99 $multiline =~ s/(^|$nlend)$lend$/$1/o;
1934 10         42 $self->INT_definery(\%curpar, $mkey, $construct);
1935 10 50       26 if(exists $self->{param}{$mkey})
1936             {
1937             # apply the config file options first, with eval() when desired
1938 10         34 $self->INT_apply_op($mkey, $mop, $multiline, $file);
1939 10         30 $self->INT_verb_msg("set $mkey from $multiline\n");
1940             }
1941             else
1942             {
1943 0 0       0 unless($self->{config}{ignore_unknown})
1944             {
1945 0 0       0 if($self->{config}{nanny}){ $self->{param}{help} = 1; }
  0         0  
1946 0         0 $self->INT_error("$file:$ln: unknown parameter $mkey!");
1947             }
1948             }
1949              
1950 10         120 $multiline = '';
1951             }
1952             }
1953             }
1954 17         107 $cdat->close();
1955 17         325 $self->INT_verb_msg("... done parsing.\n");
1956 17         29 pop(@{$self->{parse_chain}});
  17         66  
1957             }
1958 0 0       0 else{ $self->INT_error("Couldn't open config file $file! ($!)") unless $self->{config}{nocomplain}; }
1959              
1960 17 100       36 if(@{$self->{errors}} == $olderrs)
  17         55  
1961             {
1962 16         154 return 1
1963             } else
1964             {
1965 1         3 $self->{bad_config_file} = 1;
1966 1         17 return 0;
1967             }
1968             }
1969              
1970             # Just helper for the above, not gerneral-purpose.
1971              
1972             # Define a parameter in construction mode or when needed to accept something unknown.
1973             sub INT_definery
1974             {
1975 84     84 0 225 my ($self, $curpar, $par, $construct) = @_;
1976 84 50 66     276 if(
      66        
1977             defined $curpar->{long}
1978             and (
1979             $construct
1980             or
1981             (
1982             $self->{config}{accept_unknown}
1983             and not exists $self->{param}{$par}
1984             and $curpar->{long} eq $par
1985             ))
1986 6         20 ){ $self->define($curpar); }
1987              
1988 84 50 33     287 $self->define({long=>$par}) if(not exists $self->{param}{$par} and ($construct or $self->{config}{accept_unknown}));
      66        
1989 84         149 %{$curpar} = ();
  84         215  
1990             }
1991              
1992             # Print out a config file.
1993             sub print_file
1994             {
1995 2     2 1 7 my ($self, $handle, $bare) = @_;
1996              
1997 2         7 my @omit = ('config','help');
1998 2 50       8 push(@omit,'version') if defined $self->{config}{version};
1999 2 50       6 push(@omit, @{$self->{config}{notinfile}}) if defined $self->{config}{notinfile};
  0         0  
2000 2 50       6 unless($bare)
2001             {
2002 2         12 print $handle <
2003             # Configuration file for $self->{config}{program}
2004             #
2005             # Syntax:
2006             #
2007             EOT
2008 2         5 print $handle <
2009             # name = value
2010             # or
2011             # name = "value"
2012             #
2013             # You can provide any number (including 0) of whitespaces before and after name and value. If you really want the whitespace in the value then use the second form and be happy;-)
2014             EOT
2015 2         13 print $handle <
2016             # It is also possible to set multiline strings with
2017             # name <
2018             # ...
2019             # ENDSTRING
2020             #
2021             # (just like in Perl but omitting the ;)
2022             # You can use .=, +=, /= and *= instead of = as operators for concatenation of strings or pushing to arrays/hashes, addition, substraction, division and multiplication, respectively.
2023             # The same holds likewise for .<<, +<<, /<< and *<< .
2024             #
2025             # The short names are just provided as a reference; they're only working as real command line parameters, not in this file!
2026             #
2027             # The lines starting with "=" are needed for parsers of the file (other than $self->{config}{program} itself) and are informative to you, too.
2028             # =param file (options) for program
2029             # says for whom the file is and possibly some hints (options)
2030             # =info INFO
2031             # is the general program info (multiple lines, normally)
2032             # =long NAME short S type TYPE
2033             # says that now comes stuff for the parameter NAME and its short form is S. Data TYPE can be scalar, array or hash.
2034             # =help SOME_TEXT
2035             # gives a description for the parameter.
2036             #
2037             # If you don't like/need all this bloated text, the you can strip all "#", "=" - started and empty lines and the result will still be a valid configuration file for $self->{config}{program}.
2038              
2039             EOT
2040             }
2041 2         6 print $handle '=param file ';
2042 2         3 my @opt = (); # There are no relevant options currently.
2043 2 50       7 print $handle '('.join(',',@opt).') ' if @opt;
2044 2         7 print $handle 'for '.$self->{config}{program}."\n";
2045 2 50       7 print $handle '=version '.$self->{config}{version}."\n" if defined $self->{config}{version};
2046 2         5 print $handle "\n";
2047 2 100 66     9 if(defined $self->{config}{info} and !$bare)
2048             {
2049 1         4 my @info = split("\n",$self->{config}{info});
2050 1         2 for(@info){ print $handle '=info '.$_."\n"; }
  1         3  
2051             }
2052 2 50 33     9 if(defined $self->{config}{infopod} and !$bare)
2053             {
2054 0         0 my @info = split("\n",$self->{config}{infopod});
2055 0         0 for(@info){ print $handle '=infopod '.$_."\n"; }
  0         0  
2056             }
2057 2         8 for my $k (sort keys %{$self->{param}})
  2         19  
2058             {
2059 15 100       227 unless(grep(/^$k$/, @omit))
2060             {
2061             #make line ending changeable...
2062             #or use proper system-independent line end
2063             #for now we just use \n - what may even work with active perl
2064             #
2065 11 50       29 unless($bare)
2066             {
2067             print $handle "\n=long $k"
2068 11 100       69 ,$self->{short}{$k} ne '' ? " short $self->{short}{$k}" : ''
2069             ," type $typename[$self->{type}{$k}]"
2070             ,"\n";
2071 11         15 my @help = split("\n",${$self->{help}{$k}});
  11         32  
2072 11         21 for(@help)
2073             {
2074 11         30 print $handle "=help $_\n";
2075             }
2076             }
2077 11 100       29 my $values = $self->{type}{$k} ? $self->{param}{$k} : [ $self->{param}{$k} ];
2078 11 100       32 if($self->{type}{$k} == $hash)
2079             {
2080 2         5 my @vals;
2081 2         3 for my $k (sort keys %{$values})
  2         9  
2082             {
2083 4 50       18 push(@vals, $k.(defined $values->{$k} ? '='.$values->{$k} : ''));
2084             }
2085 2         5 $values = \@vals;
2086             }
2087 11 50       20 $values = [ undef ] unless defined $values;
2088 11         16 my $first = 1;
2089 11 50       30 print $handle "\n" unless $bare;
2090 11         15 for my $v (@{$values})
  11         24  
2091             {
2092             my $preop = $self->{type}{$k}
2093             ? ( (not $first)
2094             ? '.'
2095 19 50       47 : ( (@{$values} > 1) ? ' ' : '' ) )
  4 100       30  
    100          
2096             : '';
2097 19 100       29 if(defined $v)
2098             {
2099 18 100       43 if($v =~ /[\012\015]/)
2100             {
2101 1         2 my $end = 'EOT';
2102 1         2 my $num = '';
2103 1         11 $v =~ s/[\012\015]*\z/\n/g; # that line end business needs testing
2104 1         24 while($v =~ /(^|\n)$end$num(\n|$)/){ ++$num; }
  1         14  
2105 1         4 print $handle "$k $preop<<$end$num\n$v$end$num\n";
2106             }
2107 17         33 else{ print $handle "$k $preop= \"$v\"\n"; }
2108             }
2109 1         3 else{ print $handle "# $k is undefined\n"; }
2110              
2111 19         43 $first = 0;
2112             }
2113             }
2114             }
2115             }
2116              
2117             sub INT_push_hash
2118             {
2119 75     75 0 135 my $self = shift;
2120 75         126 my $par = shift; for (@_)
  75         181  
2121             {
2122 104         346 my ($k, $v) = split('=',$_,2);
2123 104 50       276 if(defined $k)
2124             {
2125 104         399 $par->{$k} = $v;
2126             } else
2127             {
2128 0         0 $self->INT_error("Undefined key for hash $_[0]. Did you mean --$_[0]// to empty it?");
2129             }
2130             }
2131             }
2132              
2133             # The low-level worker for applying one parameter operation.
2134             sub INT_apply_op
2135             {
2136 280     280 0 508 my $self = shift; # (par, op, value, file||undef)
2137              
2138 280 50       753 return unless exists $self->{param}{$_[0]};
2139              
2140 280 100       1045 if($self->{type}{$_[0]} == $scalar)
    100          
    50          
2141             {
2142 12     12   164 no warnings 'numeric';
  12         29  
  12         15954  
2143 101         226 my $par = \$self->{param}{$_[0]}; # scalar ref
2144 101 100       294 if ($_[1] eq '='){ $$par = $_[2]; }
  69 100       295  
    100          
    100          
    50          
    0          
2145 6         15 elsif($_[1] eq '.='){ $$par .= $_[2]; }
2146 10         48 elsif($_[1] eq '+='){ $$par += $_[2]; }
2147 11         42 elsif($_[1] eq '-='){ $$par -= $_[2]; }
2148 5         25 elsif($_[1] eq '*='){ $$par *= $_[2]; }
2149 0         0 elsif($_[1] eq '/='){ $$par /= $_[2]; }
2150 0         0 else{ $self->INT_error("Operator '$_[1]' on '$_[0]' is invalid."); $self->{param}{help} = 1; }
  0         0  
2151             }
2152             elsif($self->{type}{$_[0]} == $array)
2153             {
2154 101         215 my $par = $self->{param}{$_[0]}; # array ref
2155 101         153 my $bad;
2156 101 100 66     420 if ($_[1] eq '='){ @{$par} = ( $_[2] ); }
  18 100 66     33  
  18 100       55  
    100          
2157 54         111 elsif($_[1] eq '.='){ push(@{$par}, $_[2]); }
  54         135  
2158 3         7 elsif($_[1] eq '//=' or ($_[1] eq '/=' and $_[2] eq '/')){ @{$par} = (); }
  3         11  
2159             elsif($_[1] =~ m:^/(.)/(.*)$:) # operator with specified array separator
2160             {
2161 25         56 my $sep = $1; # array separator
2162 25         49 my $op = $2; # actual operator
2163 25         240 my @values = split(/\Q$sep\E/, $_[2]);
2164 25 100       75 if ($op eq '='){ @{$par} = @values; }
  11 50       53  
  11         46  
2165 14         28 elsif($op eq '.='){ push(@{$par}, @values); }
  14         62  
2166 0         0 else{ $bad = 1; }
2167             }
2168 1         3 else{ $bad = 1 }
2169 101 100       368 if($bad)
2170             {
2171 1         5 $self->INT_error("Operator '$_[1]' is invalid for array '$_[0]'!");
2172             #$self->{param}{help} = 1;
2173             }
2174             }
2175             elsif($self->{type}{$_[0]} == $hash)
2176             {
2177 78         150 my $par = $self->{param}{$_[0]}; # hash ref
2178 78         125 my $bad;
2179              
2180 78 100 66     396 if($_[1] =~ m:^/(.)/(.*)$:) # operator with specified array separator
    100 66        
2181             {
2182 25         57 my $sep = $1; # array separator
2183 25         47 my $op = $2; # actual operator
2184 25         267 my @values = split(/\Q$sep\E/, $_[2]);
2185             # a sub just to avoid duplicating the name=value splitting and setting
2186 25 100       74 if ($op eq '='){ %{$par} = (); $self->INT_push_hash($par,@values); }
  11 50       20  
  11         32  
  11         32  
2187 14         36 elsif($op eq '.='){ $self->INT_push_hash($par,@values); }
2188 0         0 else{ $bad = 1; }
2189             }
2190             elsif($_[1] eq '//=' or ($_[1] eq '/=' and $_[2] eq '/'))
2191             {
2192 3         6 %{$par} = ();
  3         25  
2193             } else
2194             {
2195 50 100       168 if ($_[1] eq '='){ %{$par} = (); $self->INT_push_hash($par, $_[2]); }
  12 50       24  
  12         31  
  12         42  
2196 38         124 elsif($_[1] eq '.='){ $self->INT_push_hash($par, $_[2]); }
2197 0         0 else{ $bad = 1 }
2198             }
2199 78 50       292 if($bad)
2200             {
2201 0         0 $self->INT_error("Operator '$_[1]' is invalid for hash '$_[0]'!");
2202 0         0 $self->{param}{help} = 1;
2203             }
2204             }
2205             }
2206              
2207             sub INT_value_check
2208             {
2209 60     60 0 112 my $self = shift;
2210 60         575 my $p = $self->{param};
2211 60         162 my $olderr = @{$self->{errors}};
  60         142  
2212 60         108 for my $k (keys %{$self->{regex}})
  60         211  
2213             {
2214 140 100       419 if($self->{type}{$k} == $scalar)
    100          
    50          
2215             {
2216             $self->INT_error("Value of $k does not match regex: $p->{$k}")
2217 64 50       530 unless $p->{$k} =~ $self->{regex}{$k};
2218             } elsif($self->{type}{$k} == $array)
2219             {
2220 68         174 for(my $i=0; $i<@{$p->{$k}}; ++$i)
  83         258  
2221             {
2222             $self->INT_error("Element $i of $k does not match regex: $p->{$k}[$i]")
2223 15 100       137 unless $p->{$k}[$i] =~ $self->{regex}{$k};
2224             }
2225             } elsif($self->{type}{$k} == $hash)
2226             {
2227 8         12 for my $n (sort keys %{$p->{$k}})
  8         46  
2228             {
2229             $self->INT_error("Element $n of $k does not match regex: $p->{$k}{$n}")
2230 4 50       27 unless $p->{$k}{$n} =~ $self->{regex}{$k};
2231             }
2232             }
2233             }
2234 60         130 for my $k (keys %{$p})
  60         223  
2235             {
2236 12     12   107 no warnings 'uninitialized';
  12         24  
  12         12049  
2237             next
2238 337 100       873 unless ($self->{flags}{$k} & $nonempty);
2239 16 100 66     80 unless(
      100        
      100        
      100        
      100        
2240             ( $self->{type}{$k} == $scalar and $p->{$k} ne '' ) or
2241 8         35 ( $self->{type}{$k} == $array and @{$p->{$k}} ) or
2242 4         17 ( $self->{type}{$k} == $hash and %{$p->{$k}} )
2243             ){
2244 3         11 $self->INT_error("Parameter $k is empty but should not be.");
2245             }
2246             }
2247 60         135 return $olderr == @{$self->{errors}};
  60         295  
2248             }
2249              
2250             sub current_setup
2251             {
2252 3     3 1 29 require Storable;
2253 3         6 my $self = shift;
2254 3         107 my $config = Storable::dclone($self->{config});
2255 3         9 my @pardef;
2256 3         10 my $bin = builtins($self->{config});
2257 3         7 for my $p (sort keys %{$self->{param}})
  3         27  
2258             {
2259 24 100       51 next if $bin->{$p};
2260 18 100       142 my $val = ref($self->{param}{$p}) ? Storable::dclone($self->{param}{$p}) : $self->{param}{$p};
2261 18         32 push(@pardef, $p, $val, $self->{short}{$p}, ${$self->{help}{$p}});
  18         61  
2262             }
2263 3         20 return ($config, \@pardef);
2264             }
2265              
2266              
2267             # Little hepler for modifying the parameters.
2268             # Apply all collected operations to a specific parameter.
2269             sub INT_apply_ops
2270             {
2271 206     206 0 402 my $self = shift;
2272 206         340 my $key = shift;
2273 206 100       577 return unless defined $self->{ops}{$key};
2274 144         255 $self->INT_verb_msg("Param: applying (@{$self->{ops}{$key}}) to $key of type $self->{type}{$key}\n");
  144         886  
2275 144         264 while(@{$self->{ops}{$key}})
  343         1040  
2276             {
2277 199         298 my $op = shift(@{$self->{ops}{$key}});
  199         489  
2278 199         397 my $val = shift(@{$self->{ops}{$key}});
  199         434  
2279 199         583 $self->INT_apply_op($key, $op, $val);
2280             }
2281             }
2282              
2283             sub INT_verb_msg
2284             {
2285 1381     1381 0 2408 my $self = shift;
2286 1381 50 33     6512 return unless ($verbose or $self->{config}{verbose});
2287 0         0 print STDERR "[Config::Param] ", @_;
2288             }
2289              
2290             sub INT_error
2291             {
2292 14     14 0 28 my $self = shift;
2293             print STDERR "$self->{config}{program}: [Config::Param] Error: "
2294 14 50       44 , $_[0], "\n" unless $self->{config}{silenterr};
2295 14         20 push(@{$self->{errors}}, $_[0]);
  14         40  
2296 14         50 return 1;
2297             }
2298              
2299             1;
2300              
2301             __END__