File Coverage

blib/lib/Getopt/ArgvFile.pm
Criterion Covered Total %
statement 101 101 100.0
branch 68 82 82.9
condition 36 54 66.6
subroutine 9 9 100.0
pod 1 1 100.0
total 215 247 87.0


line stmt bran cond sub pod time code
1              
2             # = HISTORY SECTION =====================================================================
3              
4             # ---------------------------------------------------------------------------------------
5             # version | date | author | changes
6             # ---------------------------------------------------------------------------------------
7             # 1.11 |17.04.07| JSTENZEL | renamed fileOptions2prefixes() into _fileOptions2prefixes(),
8             # | | | in order to avoid POD documentation because it is an
9             # | | | internal helper function;
10             # | | JSTENZEL | slight adaptations after complaints of perlcritic;
11             # | | JSTENZEL | added POD hints that GetOptions() is imported from
12             # | | | Getopt::Long and not defined in Getopt::ArgvFile;
13             # | | JSTENZEL | POD: bugfix in GetOptions() calls, %options hash needs to
14             # | | | be passed in as reference;
15             # |21.04.07| JSTENZEL | POD: bugfix in -fileOption example;
16             # 1.10 |05.01.05| JSTENZEL | added options resolveRelativePathes and resolveEnvVars;
17             # 1.09 |19.10.04| JSTENZEL | option -startupFilename now accepts array references both
18             # | | | directly set up and supplied by a callback;
19             # |20.10.04| JSTENZEL | new option -fileOption allows to use a user defined option
20             # | | | instead of an option file prefix like "@" (-options options
21             # | | | instead of @options);
22             # 1.08 |30.04.04| JSTENZEL | new import() switch "justload";
23             # 1.07 |29.04.04| JSTENZEL | import() implemented directly: emulating the old behaviour
24             # | | | of Exporter::import() when necessary, it alternatively
25             # | | | allows to invoke argvFile() via use();
26             # 1.06 |03.05.02| JSTENZEL | the startup filename scheme is now configurable by the
27             # | | | new option "startupFilename";
28             # 1.05 |30.04.02| JSTENZEL | cosmetics: hash access without quotes;
29             # | | JSTENZEL | corrected and improved inline doc;
30             # | | JSTENZEL | using File::Spec::Functions to build filenames,
31             # | | | for improved portability;
32             # | | JSTENZEL | using Cwd::abs_path() to check if files were read already;
33             # | | JSTENZEL | added support for default files in *current* directory;
34             # 1.04 |29.10.00| JSTENZEL | bugfix: options were read twice if both default and home
35             # | | | startup options were read and the script was installed in
36             # | | | the users homedirectory;
37             # 1.03 |25.03.00| JSTENZEL | new parameter "prefix";
38             # | | JSTENZEL | POD in option files is now supported;
39             # | | JSTENZEL | using Test in test suite now;
40             # 1.02 |27.02.00| JSTENZEL | new parameter "array";
41             # | | JSTENZEL | slight POD adaptions;
42             # 1.01 |23.03.99| JSTENZEL | README update only;
43             # 1.00 |16.03.99| JSTENZEL | first CPAN version.
44             # ---------------------------------------------------------------------------------------
45              
46             # = POD SECTION =========================================================================
47              
48             =head1 NAME
49              
50             Getopt::ArgvFile - interpolates script options from files into @ARGV or another array
51              
52             =head1 VERSION
53              
54             This manual describes version B<1.11>.
55              
56             =head1 SYNOPSIS
57              
58             One line invocation - option hints are processed while the module is loaded:
59              
60             # load module and process option file hints in @ARGV
61             use Getopt::ArgvFile default=>1;
62            
63             # load another module to evaluate the options, e.g.:
64             use Getopt::Long;
65             ...
66              
67             # evaluate options, e.g. this common way:
68             GetOptions(\%options, 'any'); # this function is defined in Getopt::Long
69              
70             Or suppress option hint processing when the module is loaded, to
71             perform it later on:
72              
73             # load module, do *not* process option file hints
74             use Getopt::ArgvFile justload=>1;
75            
76             # load another module to evaluate the options, e.g.:
77             use Getopt::Long;
78             ...
79              
80             # *now*, solve option file hints
81             Getopt::ArgvFile::argvFile(default=>1);
82              
83             # evaluate options, e.g. this common way:
84             GetOptions(\%options, 'any'); # this function is defined in Getopt::Long
85              
86             Or use the traditional two step invocation of module loading with
87             I and I option file handling:
88              
89             # Load the module and import the &argvFile symbol
90             # - this will *not* process option hints.
91             # Use *this* syntax to do so, *exactly*.
92             use Getopt::ArgvFile qw(argvFile);
93              
94             # load another module to evaluate the options, e.g.:
95             use Getopt::Long;
96             ...
97              
98             # *now*, solve option file hints
99             argvFile(default=>1);
100              
101             # evaluate options, e.g. this common way:
102             GetOptions(\%options, 'any'); # this function is defined in Getopt::Long
103              
104              
105             If options should be processed into another array, this can be done this way:
106              
107             # prepare target array
108             my @options=('@options1', '@options2', '@options3');
109              
110             ...
111              
112             # replace file hints by the options stored in the files
113             argvFile(array=>\@options);
114              
115             In case you do not like the "@" prefix it is possible to define an option to
116             be used instead:
117              
118             # prepare target array
119             my @options=('-options', 'options1', '-options', 'options2');
120              
121             ...
122              
123             # replace file hints by the options stored in the files
124             argvFile(fileOption=>'options', array=>\@options);
125              
126              
127             =head1 DESCRIPTION
128              
129             This module simply interpolates option file hints in @ARGV
130             by the contents of the pointed files. This enables option
131             reading from I instead of or additional to the usual
132             reading from the command line.
133              
134             Alternatively, you can process any array instead of @ARGV
135             which is used by default and mentioned mostly in this manual.
136              
137             The interpolated @ARGV could be subsequently processed by
138             the usual option handling, e.g. by a Getopt::xxx module.
139             Getopt::ArgvFile does I perform any option handling itself,
140             it only prepares the array @ARGV.
141              
142             Option files can significantly simplify the call of a script.
143             Imagine the following:
144              
145             =over 4
146              
147             =item Breaking command line limits
148              
149             A script may offer a lot of options, with possibly a few of them
150             even taking parameters. If these options and their parameters
151             are passed onto the program call directly, the number of characters
152             accepted by your shells command line may be exceeded.
153              
154             Perl itself does I limit the number of characters passed to a
155             script by parameters, but the shell or command interpreter often
156             I a limit here. The same problem may occur if you want to
157             store a long call in a system file like crontab.
158              
159             If such a limit restricts you, options and parameters may be moved into
160             option files, which will result in a shorter command line call.
161              
162             =item Script calls prepared by scripts
163              
164             Sometimes a script calls another script. The options passed onto the
165             nested script could depend on variable situations, such as a users
166             input or the detected environment. In such a case, it I be easier
167             to generate an intermediate option file which is then passed to
168             the nested script.
169              
170             Or imagine two cron jobs one preparing the other: the first may generate
171             an option file which is then used by the second.
172              
173             =item Simple access to typical calling scenarios
174              
175             If several options need to be set, but in certain circumstances
176             are always the same, it could become sligthly nerveracking to type
177             them in again and again. With an option file, they can be stored
178             I and recalled easily as often as necessary.
179              
180             Further more, option files may be used to group options. Several
181             settings may set up one certain behaviour of the program, while others
182             influence another. Or a certain set of options may be useful in one
183             typical situation, while another one should be used elsewhere. Or there
184             is a common set of options which has to be used in every call,
185             while other options are added depending on the current needs. Or there
186             are a few user groups with different but typical ways to call your script.
187             In all these cases, option files may collect options belonging together,
188             and may be combined by the script users to set up a certain call.
189             In conjunction with the possiblity to I such collections, this is
190             perhaps the most powerful feature provided by this method.
191              
192             =item Individual and installationwide default options
193              
194             The module allows the programmer to enable user setups of default options;
195             for both individual users or generally I callers of a script.
196             This is especially useful for administrators who can configure the
197             I behaviour of a script by setting up its installationwide
198             startup option file. All script users are free then to completely
199             forget every already configured setup option. And if one of them regularly
200             adds certain options to every call, he could store them in his I
201             startup option file.
202              
203             For example, I use this feature to make my scripts both flexible I
204             usable. I have several scripts accessing a database via DBI. The database
205             account parameters as well as the DBI startup settings should not be coded
206             inside the scripts because this is not very flexible, so I implemented
207             them by options. But on the other hand, there should be no need for a normal
208             user to pass all these settings to every script call. My solution for this
209             is to use I option files set up and maintained by an administrator.
210             This is very transparent, most of the users know nothing of these
211             (documented ;-) configuration settings ... and if anything changes, only the
212             option files have to be adapted.
213              
214             =back
215              
216             =cut
217              
218             # PACKAGE SECTION ###############################################
219              
220             # declare namespace
221             package Getopt::ArgvFile;
222              
223             # declare your revision (and use it to avoid a warning)
224             $VERSION=1.11;
225             $VERSION=$VERSION;
226              
227             # force Perl version
228             require 5.003;
229              
230             =pod
231              
232             =head1 EXPORTS
233              
234             No symbol is exported by default, but you may explicitly import
235             the "argvFile()" function I:
236              
237             use Getopt::ArgvFile qw(argvFile);
238              
239             Please note that this interface is provided for backwards compatibility with
240             versions up to 1.06. By loading the module this way, the traditional import
241             mechanisms take affect and I is not called implicitly>.
242              
243             This means that while option file hints are usually processed implicitly when
244             C is loaded, the syntax
245              
246             use Getopt::ArgvFile qw(argvFile);
247              
248             requires an I call of I to process option files.
249              
250             =cut
251              
252             # export something (Exporter is not made a base module because we implement import() ourselves,
253             # which *can* call Exporter::import() (if needed for backwards compatibility) - see import())
254             require Exporter;
255             @EXPORT_OK=qw(argvFile);
256              
257             # CODE SECTION ##################################################
258              
259             # set pragmas
260 8     8   222545 use strict;
  8         17  
  8         316  
261              
262             # load libraries
263 8     8   45 use Carp;
  8         16  
  8         753  
264 8     8   50 use File::Basename;
  8         15  
  8         859  
265 8     8   7712 use Text::ParseWords;
  8         12565  
  8         2235  
266 8     8   31164 use File::Spec::Functions;
  8         8210  
  8         803  
267 8     8   50 use Cwd qw(:DEFAULT abs_path chdir);
  8         15  
  8         18633  
268              
269             # module variables
270             my $optionPrefixPattern=qr/(-{1,2}|\+)/;
271              
272             # METHOD SECTION ################################################
273              
274             =pod
275              
276             =head1 FUNCTIONS
277              
278             There is only one function, I, which does all the work of
279             option file hint processing.
280              
281             Please note that with version 1.07 and above C is called
282             I when the module is loaded, except this is done in one of
283             the following ways:
284              
285             # the traditional interface - provided for
286             # backwards compatibility - this loads the
287             # module and imports the &argvFile symbol
288             use Getopt::ArgvFile qw(argvFile);
289              
290             --
291              
292             # option file processing is explicitly suppressed
293             use Getopt::ArgvFile justload=>1;
294              
295             Except for the traditional loading, the complete interface of C
296             is available via C, but in the typical C syntax without
297             parantheses.
298              
299             # implicit call of argvFile(default=>1, home=>1)
300             use Getopt::ArgvFile default=>1, home=>1;
301              
302             See I for further details.
303              
304              
305             =head2 argvFile()
306              
307             Scans the command line parameters (stored in @ARGV or an alternatively
308             passed array) for option file hints (see I below), reads the
309             pointed files and makes their contents part of the source array
310             (@ARGV by default) replacing the hints.
311              
312             Because the function was intentionally designed to work on @ARGV
313             and this is still the default behaviour, this manual mostly speaks about
314             @ARGV. Please note that it is possible to process I other array
315             as well.
316              
317             B
318              
319             An option file hint is simply the filename preceeded by (at least) one
320             "@" character:
321              
322             > script -optA argA -optB @optionFile -optC argC
323              
324             This will cause argvFile() to scan "optionFile" for options.
325             The element "@optionFile" will be removed from the @ARGV array and
326             will be replaced by the options found.
327              
328             Note: you can choose another prefix by using the "prefix" parameter,
329             see below.
330              
331             An option file which cannot be found is quietly skipped.
332              
333             Well, what is I an option file? It is intended to
334             store I which should be passed to the called
335             script. They can be stored exactly as they would be written in
336             the command line, but may be spread to multiple lines. To make the
337             file more readable, space and comment lines (starting with a "#")
338             are allowed additionally. POD comments are supported as well.
339             For example, the call
340              
341             > script -optA argA -optB -optC cArg par1 par2
342              
343             could be transformed into
344              
345             > script @scriptOptions par1 par2
346              
347             where the file "scriptOptions" may look like this:
348              
349             # option a
350             -optA argA
351              
352             C<>
353              
354             =pod
355             option b
356             =cut
357             -optB
358              
359             C<>
360              
361             # option c
362             -optC cArg
363              
364             B
365              
366             Option files can be nested. Recursion is avoided globally, that means
367             that every file will be opened only I (the first time argvFile() finds
368             a hint pointing to it). This is the simplest implementation, indeed, but
369             should be suitable. (Unfortunately, there are I.)
370              
371             By using this feature, you may combine groups of typical options into
372             a top level option file, e.g.:
373              
374             File ab:
375              
376             C<>
377              
378             # option a
379             -optA argA
380             # option b
381             -optB
382              
383             C<>
384              
385             File c:
386              
387             C<>
388              
389             # option c
390             -optC cArg
391              
392             C<>
393              
394             File abc:
395              
396             C<>
397              
398             # combine ab and c
399             @ab @c
400              
401             If anyone provides these files, a user can use a very short call:
402              
403             > script @abc
404              
405             and argvFile() will recursively move all the filed program parameters
406             into @ARGV.
407              
408              
409             B
410              
411             Pathes in option files might be relative, as in
412              
413             -file ../file @../../configs/nested
414              
415             If written with the (prepared) start directory in mind, that will work,
416             but it can fail when it was written relatively to the option file location
417             because by default those pathes will not be resolved when written from
418             an option file.
419              
420             Use parameter C to switch to path resolution:
421              
422             argvFile(resolveRelativePathes=>1);
423              
424             will cause C to expand those pathes, both in standard strings
425             and nested option files.
426              
427             With resolveRelativePathes, both pathes
428             will be resolved:
429              
430             -file ../file @../../configs/nested
431              
432             A path is resolved I it is found in.
433              
434              
435             B
436              
437             Similar to relative pathes, environment variables are handled differently
438             depending if the option is specified at the commandline or from an option
439             file, due to bypassed shell processing. By default, C does
440             not resolve environment variables. But if required it can be commanded
441             to do so via parameter C.
442              
443             argvFile(resolveEnvVars=>1);
444              
445             B
446              
447             By setting several named parameters, you can enable automatic processing
448             of I. There are three of them:
449              
450             The I is searched in the installation path
451             of the calling script, the I is searched in the
452             users home (evaluated via environment variable "HOME"), and the
453             I is searched in the current directory.
454              
455             By default, all startup option files are expected to be named like
456             the script, preceeded by a dot, but this can be adapted to individual
457             needs if preferred, see below.
458              
459             Examples:
460             If a script located in "/path/script" is invoked in directory
461             /the/current/dir by a user "user" whoms "HOME" variable points
462             to "/homes/user", the following happens:
463              
464             C<>
465              
466             argvFile() # ignores all startup option files;
467             argvFile(default=>1) # searches and expands "/path/.script",
468             # if available (the "default" settings);
469             argvFile(home=>1) # searches and expands "/homes/user/.script",
470             # if available (the "home" settings);
471             argvFile(current=>1) # searches and expands "/the/current/dir/.script",
472             # if available (the "current" settings);
473             argvFile(
474             default => 1,
475             home => 1,
476             current => 1
477             ) # tries to handle all startups.
478              
479             Any true value will activate the setting it is assigned to.
480              
481             In case the ".script" name rule does not meet your needs or does not fit
482             into a certain policy, the expected startup filenames can be set up by
483             an option C. The option value may be a scalar used as
484             the expected filename, or a reference to an array of accepted choices,
485             or a reference to code returning the name - plainly or as a reference to
486             an array of names. Such callback code will be called I and will
487             receive the name of the script.
488              
489             # use ".config"
490             argvFile(startupFilename => '.config');
491              
492             # use ".config" or "config"
493             argvFile(startupFilename => [qw(.config config)]);
494              
495             # emulate the default behaviour,
496             # but use an extra dot postfix
497             my $nameBuilder=sub {join('', '.', basename($_[0]), '.');};
498             argvFile(startupFilename => $nameBuilder);
499              
500             # use .(script)rc or .(script)/config
501             my $nameBuilder=sub
502             {
503             my $sname=basename($_[0]);
504             [".${sname}rc", ".${sname}/config"];
505             };
506             argvFile(startupFilename => $nameBuilder);
507              
508             Note that the list variants will use the first matching filename in each
509             possible startup-file path. For example if your array is C<['.scriptrc',
510             '.script.config']> and you have both a C<.scriptrc> and a C<.script.config>
511             file in (say) your current directory, only the C<.scriptrc> file will be
512             used, as it is the first found.
513              
514             The contents found in a startup file is placed I all explicitly
515             set command line arguments. This enables to overwrite a default setting
516             by an explicit option. If all startup files are read, I startup
517             files can overwrite I files which have preceedence over I
518             ones, so that the I startups are most common. In other words,
519             if the module would not support startup files, you could get the same
520             result with "script @/path/.script @/homes/user/.script @/the/current/dir/.script".
521              
522             Note: There is one certain case when overwriting will I work completely
523             because duplicates are sorted out: if all three types of startup files are
524             used and the script is started in the installation directory,
525             the default file will be identical to the current file. The default file is
526             processed, but the current file is skipped as a duplicate later on and will
527             I overwrite settings made caused by the intermediately processed home file.
528             If started in another directory, it I overwrite the home settings.
529             But the alternative seems to be even more confusing: the script would behave
530             differently if just started in its installation path. Because a user might
531             be more aware of configuration editing then of the current path, I choose
532             the current implementation, but this preceedence might become configurable
533             in a future version.
534              
535             If there is no I environment variable, the I setting takes no effect
536             to avoid trouble accessing the root directory.
537              
538             B
539              
540             The function supports multi-level (or so called I) option files.
541             If a filename in an option file hint starts with a "@" again, this complete
542             name is the resolution written back to @ARGV - assuming there will be
543             another utility reading option files.
544              
545             Examples:
546             @rfile rfile will be opened, its contents is
547             made part of @ARGV.
548             @@rfile cascade: "@rfile" is written back to
549             @ARGV assuming that there is a subsequent
550             tool called by the script to which this
551             hint will be passed to solve it by an own
552             call of argvFile().
553              
554             The number of cascaded hints is unlimited.
555              
556             B
557              
558             Although the function was designed to process @ARGV, it is possible to
559             process another array as well if you prefer. To do this, simply pass
560             a I to this array by parameter B.
561              
562             Examples:
563             argvFile() # processes @ARGV;
564             argvFile(array=>\@options); # processes @options;
565              
566             B
567              
568             By default, "@" is the prefix used to mark an option file. This can
569             be changed by using the optional parameter B:
570              
571             Examples:
572             argvFile(); # use "@";
573             argvFile(prefix=>'~'); # use "~";
574              
575             Note that the strings "#", "=", "-" and "+" are reserved and I
576             be chosen here because they are used to start plain or POD comments or
577             are typically option prefixes.
578              
579             B
580              
581             People not familiar with option files might be confused by file prefixes.
582             This can be avoided by offering an I
583             of a prefix, using the optional parameter B:
584              
585             # install a file option
586             # (all lines are equivalent)
587             argvFile(fileOption=>'options');
588             argvFile(fileOption=>'-options');
589             argvFile(fileOption=>'+options');
590             argvFile(fileOption=>'--options');
591              
592             The name of the option can be specified with or without the usual option
593             prefixes C<->, C<--> and C<+>.
594              
595             Once an option is declared, it I replace a prefix. (Prefixes remain
596             in action as well.)
597              
598             # with -options declared to be a file option,
599             # these sequences are equivalent
600             @file
601             -options file
602              
603             # five equivalent cascades
604             @@@@file
605             -options @@@file
606             -options -options @@file
607             -options -options -options @file
608             -options -options -options -options file
609              
610             Please note that prefixes are attached to the filename with no spaces
611             in between, while the option declared via -fileOption is separated from
612             the filename by whitespace, as for normal options.
613              
614              
615             =cut
616             sub argvFile
617             {
618             # declare function variables
619 22     22 1 55848 my ($maskString, $i, %rfiles, %startup, %seen)=("\0x07\0x06\0x07");
620              
621             # detect the host system (to prepare filename handling)
622 22         273 my $casesensitiveFilenames=$^O!~/^(?:dos|os2|MSWin32)/i;
623              
624             # check and get parameters
625 22 50       150 confess('[BUG] Getopt::ArgvFile::argvFile() uses named parameters, please provide name value pairs.') if @_ % 2;
626 22         124 my %switches=@_;
627              
628             # perform more parameter checks
629 22 50 33     222 confess('[BUG] The "array" parameter value is no array reference.') if exists $switches{array} and not (ref($switches{array}) and ref($switches{array}) eq 'ARRAY');
      66        
630 22 50 33     121 confess('[BUG] The "prefix" parameter value is no defined literal.') if exists $switches{prefix} and (not defined $switches{prefix} or ref($switches{prefix}));
      66        
631 22 50 66     118 confess('[BUG] Invalid "prefix" parameter $switches{"prefix"}.') if exists $switches{prefix} and $switches{prefix}=~/^[-#=+]$/;
632 22 50 100     188 confess('[BUG] The "startupFilename" parameter value is neither a scalar nor array or code reference.') if exists $switches{startupFilename} and ref($switches{startupFilename}) and ref($switches{startupFilename})!~/^(ARRAY|CODE)$/;
      66        
633 22 50 33     150 confess('[BUG] The "fileOption" parameter value is no defined literal.') if exists $switches{fileOption} and (not defined $switches{fileOption} or ref($switches{fileOption}));
      66        
634              
635             # check if further operations are suppressed (in case of a call via import())
636             {
637 22         37 my ($callerSub)=(caller(1))[3];
  22         74  
638 22 100 66     1774 return if defined $callerSub and $callerSub eq join('::', __PACKAGE__, 'import')
      100        
639             and exists $switches{justload};
640             }
641              
642             # set array reference
643 21 100       286 my $arrayRef=exists $switches{array} ? $switches{array} : \@ARGV;
644              
645             # set prefix
646 21 100       77 my $prefix=exists $switches{prefix} ? $switches{prefix} : '@';
647              
648             # set file option
649 21 100       70 my $fileOption=exists $switches{fileOption} ? $switches{fileOption} : '';
650 21         319 $fileOption=~s/^$optionPrefixPattern//;
651              
652             # set up startup filename list
653 21 100       1826 my $startupFilenames=exists $switches{startupFilename}
    100          
    100          
654             ? ref($switches{startupFilename})
655             ? ref($switches{startupFilename}) eq 'CODE'
656             ? $switches{startupFilename}->($0)
657             : $switches{startupFilename}
658             : [$switches{startupFilename}]
659             : [join('', '.', basename($0))];
660              
661             # check callback results
662 21 50 66     409 confess('[BUG] The filenames callback did not return a scalar or an array reference.')
663             if ref($startupFilenames) and ref($startupFilenames) ne 'ARRAY';
664              
665             # a callback might have returned a(n undefined) scalar instead of an array reference
666 21 50       144 $startupFilenames=[defined $startupFilenames ? $startupFilenames : ()]
    100          
667             unless ref($startupFilenames);
668              
669             # substitute file options by prefixes, if necessary
670 21 100       67 _fileOptions2prefixes($fileOption, $prefix, $arrayRef) if $fileOption;
671              
672             # init startup file paths
673             (
674 21 100       189672 $startup{default}{path},
675             $startup{home}{path},
676             $startup{current}{path},
677             )=(
678             dirname($0),
679             exists $ENV{HOME} ? $ENV{HOME} : 'no HOME variable, sorry',
680             cwd(),
681             );
682              
683             # ignore the "home" switch if there is no HOME environment variable, for reasons
684             # of security
685 21 100       544 delete $switches{home} unless exists $ENV{HOME};
686              
687             # If startup paths are *identical* (script installed in home directory) and
688             # both startup flags are set, we can delete one of them (to read the options only once).
689             # (Note that we could easily combine this with the subsequent loop, but an extra loop
690             # will make it easy to allow extra configuration for "first seen first processed" /
691             # "fix processing order" preferences (what if the current directory is the default
692             # one, but should overwrite the home settings?).)
693             # Also set the first-found startup files while we're finding them. This makes sure we
694             # only use *one* file per path.
695 21         172 my %startupFiles;
696 21         687 foreach my $type (qw(default home current))
697             {
698             # skip unused settings
699 63 100       404 next unless exists $switches{$type};
700              
701             # build filename (use the first existing file built according to the list of choices, if any)
702 19         255 my $cfg=(grep(-e, map {catfile(abs_path($startup{$type}{path}), $_)} @$startupFilenames))[0];
  21         2053  
703              
704             # remove this setting if the associated file
705             # was already seen before (each file should be read once)
706             # - or if there is no such file this call
707 19 50 33     396 delete $switches{$type}, next if not defined $cfg or exists $seen{$cfg};
708              
709             # buffer filename for subsequent use - no need to built it twice
710 19         142 $startupFiles{$type}=$cfg;
711              
712             # otherwise, note that we saw this file
713 19         273 $seen{$cfg}=1;
714             }
715              
716             # Check all possible startup files for usage - be careful to handle
717             # them in the following order (implemented by alphabetical order here!):
718             # FIRST, the DEFAULT startup should be read, THEN the HOME one and finally
719             # the CURRENT one - this way, all startup options are placed before command
720             # line ones, and the CURRENT settings can overwrite the HOME settings which
721             # can overwrite the DEFAULT ones - which are the most common.
722             # Note that to achieve this reading order, we have to build the array
723             # of filenames in reverse order (because we use unshift() for construction).
724 21         83 foreach my $type (qw(current home default))
725             {
726             # let's proceed this file first, if there is anything to do
727             # - this way, command line options can overwrite configuration
728             # settings (we already checked file existence above)
729 63 100       893 unshift @$arrayRef, join('', $prefix, $startupFiles{$type})
730             if exists $switches{$type};
731             }
732              
733             # nesting ...
734 21         816 while (grep(/^$prefix/, @$arrayRef))
735             {
736             # declare scope variables
737 38         76 my (%nr, @c, $c);
738              
739             # scan the array for option file hints
740 38 100       250 for ($i=0; $i<@$arrayRef; $i++)
  278         1452  
741             {$nr{$i}=1 if substr($arrayRef->[$i], 0, 1) eq $prefix;}
742              
743 38         193 for ($i=0; $i<@$arrayRef; $i++)
744             {
745 278 100       564 if ($nr{$i})
746             {
747             # an option file - handle it
748              
749             # remove the option hint
750 54         384 $arrayRef->[$i]=~s/$prefix//;
751              
752             # if there is still an option file hint in the name of the file,
753             # this is a cascaded hint - insert it with a special temporary
754             # hint (has to be different from $prefix to avoid a subsequent solution
755             # by this loop)
756 54 100       535 push(@c, $arrayRef->[$i]), next if $arrayRef->[$i]=~s/^$prefix/$maskString/;
757              
758             # skip nonexistent or recursively nested files
759 38 50 66     1616 next if !-e $arrayRef->[$i] || -d _ || $rfiles{$casesensitiveFilenames ? $arrayRef->[$i] : lc($arrayRef->[$i])};
    50 66        
760              
761             # store filename to avoid recursion
762 36 50       7480 $rfiles{$casesensitiveFilenames ? $arrayRef->[$i] : lc($arrayRef->[$i])}=1;
763              
764             # open file and read its contents
765 36         2111 open(OPT, $arrayRef->[$i]);
766             {
767             # scopy
768 36         82 my ($pod);
  36         131  
769              
770             # handle every line
771 36         802 while ()
772             {
773             # check for POD directives
774 608 100       1499 $pod=1 if /^=\w/;
775 608 100       1979 $pod=0, next if /^=cut/;
776              
777             # skip space and comment lines (including POD)
778 592 100 100     6189 next if /^\s*$/ || /^\s*\#/ || $pod;
      100        
779              
780             # remove newlines, leading and trailing spaces
781 200         2087 s/\s*\n?$//; s/^\s*//;
  200         708  
782              
783             # get "shellwords", double backslashes before Dollar characters
784             # as they would get lost otherwise (other backslash removals are welcome!)
785 200         732 s/\\\$/\\\\\$/g;
786 200         979 my (@shellwords)=shellwords($_);
787              
788             # replace environment variables, if necessary
789 200 100       18180 if (exists $switches{resolveEnvVars})
790             {
791             # get *quoted* strings
792 11         35 my (@quotedwords)=quotewords('\s+', 1, $_);
793              
794             # process all strings
795 11         1508 for (my $i=0; $i<@shellwords; ++$i)
796             {
797             # substitute environment variables, except in single quoted strings
798 31 100       89 unless ($quotedwords[$i]=~/^'.+'$/)
799             {
800             # named variables
801 29 100       73 $shellwords[$i]=~s/(?
  7         52  
802              
803             # symbolic variables
804 29 50       63 $shellwords[$i]=~s/(?
  5         39  
805              
806             # finally, remove the backslashes before Dollar characters we added above
807 29         95 $shellwords[$i]=~s/\\\$/\$/g;
808             }
809             }
810             }
811              
812             # resolve relative pathes, if requested
813 200 100       571 if (exists $switches{resolveRelativePathes})
814             {
815             # process all strings
816 10         39 foreach my $string (@shellwords)
817             {
818             # scopy
819 11         16 my @p;
820             # replace as necessary
821 11 100       293 @p=(defined($1) ? $1 : '', $2), $string=~s#^$p[0]$p[1]#join('', $p[0], abs_path(catfile(dirname($arrayRef->[$i]), $p[1])))#e
  5 100       1001  
822             if $string=~m#^($prefix)?([./]+)/#;
823             }
824             }
825              
826             # supply results
827 200         1561 push(@c, @shellwords);
828             }
829             }
830             }
831             else
832             {
833             # a normal option or parameter - handle it
834 224         966 push(@c, $arrayRef->[$i]);
835             }
836             }
837              
838             # substitute file options by prefixes, if necessary
839 38 100       161 _fileOptions2prefixes($fileOption, $prefix, \@c) if $fileOption;
840              
841             # replace original array by expanded array
842 38         1316 @$arrayRef=@c;
843             }
844              
845             # reset hint character in cascaded hints to $prefix
846 21         102 @$arrayRef=map {s/^$maskString/$prefix/; $_} @$arrayRef;
  334         879  
  334         3874  
847             }
848              
849              
850             # allow one line invokation via "use", but make sure to keep backwards compatibility to
851             # the traditional interface inherited from Exporter
852             sub import
853             {
854             # check if the caller intended to import symbols
855             # (till 1.06, import() was inherited from Exporter and the only symbol to import was argvFile())
856 8 100 66 8   144 if (@_==2 and $_[-1] eq "argvFile")
  6         16262  
857             {goto &Exporter::import;}
858             else
859             {
860             # shift away the module name
861 2         4 shift;
862              
863             # invoke argvFile(): now option files are processed while the module is loaded
864 2         32 argvFile(@_);
865             }
866             }
867              
868              
869              
870             # preprocess an array to convert the -fileOption string into a prefix
871             sub _fileOptions2prefixes
872             {
873             # get and check parameters
874 15     15   71 my ($fileOption, $prefix, $arrayRef)=@_;
875              
876             # anything to do?
877 15 50       41 if ($fileOption)
878             {
879             # make options a string and replace all file options by a prefix
880             # (to replace the file option and its successor by the prefixed successor)
881 15         117 my $options=join("\x01\x01\x01", @$arrayRef);
882 15         329 $options=~s/($optionPrefixPattern$fileOption\x01+)/$prefix/g;
883              
884             # replace original array
885 15         183 @$arrayRef=split(/\x01\x01\x01/, $options);;
886             }
887             }
888              
889              
890              
891             # flag this module was read successfully
892             1;
893              
894             # POD TRAILER ####################################################
895              
896             =pod
897              
898             =head1 ONE LINE INVOCATION
899              
900             The traditional two line sequence
901              
902             # load the module
903             use Getopt::ArgvFile qw(argvFile);
904              
905             ...
906              
907             # solve option files
908             argvFile(default=>1);
909              
910             can be reduced to one line - just pass the parameters of C
911             to C:
912              
913             # load module and process option file hints in @ARGV
914             use Getopt::ArgvFile default=>1;
915              
916             Please note that in this case option file hints are processed at compile
917             time. This means that if you want to process alternative arrays, these
918             arrays have to be prepared before, usually in a C block.
919              
920             In versions 1.07 and above, implicit option file handling is the I
921             and only suppressed for the traditional
922              
923             use Getopt::ArgvFile qw(argvFile);
924              
925             loading, for reasons of backwards compatibility. A simple loading like
926              
927             use Getopt::ArgvFile;
928              
929             I process option hints! If you want to suppress this, use the
930             B> switch:
931              
932             use Getopt::ArgvFile justload=>1;
933              
934             See I for additional informations.
935              
936             =head1 NOTES
937              
938             If a script calling C with the C switch is
939             invoked using a relative path, it is strongly recommended to
940             perform the call of C in the startup directory
941             because C then uses the I script path as
942             well.
943              
944              
945             =head1 LIMITS
946              
947             If an option file does not exist, argvFile() simply ignores it.
948             No message will be displayed, no special return code will be set.
949              
950             =head1 AUTHOR
951              
952             Jochen Stenzel Emailto:perl@jochen-stenzel.deE
953              
954             =head1 LICENSE
955              
956             Copyright (c) 1993-2007 Jochen Stenzel. All rights reserved.
957              
958             This program is free software, you can redistribute it and/or modify it
959             under the terms of the Artistic License distributed with Perl version
960             5.003 or (at your option) any later version. Please refer to the
961             Artistic License that came with your Perl distribution for more
962             details.
963              
964             =cut