| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | #============================================================================ | 
| 2 |  |  |  |  |  |  | # | 
| 3 |  |  |  |  |  |  | # AppConfig::Getopt.pm | 
| 4 |  |  |  |  |  |  | # | 
| 5 |  |  |  |  |  |  | # Perl5 module to interface AppConfig::* to Johan Vromans' Getopt::Long | 
| 6 |  |  |  |  |  |  | # module.  Getopt::Long implements the POSIX standard for command line | 
| 7 |  |  |  |  |  |  | # options, with GNU extensions, and also traditional one-letter options. | 
| 8 |  |  |  |  |  |  | # AppConfig::Getopt constructs the necessary Getopt:::Long configuration | 
| 9 |  |  |  |  |  |  | # from the internal AppConfig::State and delegates the parsing of command | 
| 10 |  |  |  |  |  |  | # line arguments to it.  Internal variable values are updated by callback | 
| 11 |  |  |  |  |  |  | # from GetOptions(). | 
| 12 |  |  |  |  |  |  | # | 
| 13 |  |  |  |  |  |  | # Written by Andy Wardley | 
| 14 |  |  |  |  |  |  | # | 
| 15 |  |  |  |  |  |  | # Copyright (C) 1997-2007 Andy Wardley.  All Rights Reserved. | 
| 16 |  |  |  |  |  |  | # Copyright (C) 1997,1998 Canon Research Centre Europe Ltd. | 
| 17 |  |  |  |  |  |  | # | 
| 18 |  |  |  |  |  |  | #============================================================================ | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | package AppConfig::Getopt; | 
| 21 | 2 |  |  | 2 |  | 404 | use strict; | 
|  | 2 |  |  |  |  | 1 |  | 
|  | 2 |  |  |  |  | 535 |  | 
| 22 | 2 |  |  | 2 |  | 9 | use warnings; | 
|  | 2 |  |  |  |  | 2 |  | 
|  | 2 |  |  |  |  | 57 |  | 
| 23 | 2 |  |  | 2 |  | 7 | use AppConfig::State; | 
|  | 2 |  |  |  |  | 2 |  | 
|  | 2 |  |  |  |  | 39 |  | 
| 24 | 2 |  |  | 2 |  | 1351 | use Getopt::Long 2.17; | 
|  | 2 |  |  |  |  | 17146 |  | 
|  | 2 |  |  |  |  | 52 |  | 
| 25 |  |  |  |  |  |  | our $VERSION = '1.70'; | 
| 26 |  |  |  |  |  |  |  | 
| 27 |  |  |  |  |  |  |  | 
| 28 |  |  |  |  |  |  | #------------------------------------------------------------------------ | 
| 29 |  |  |  |  |  |  | # new($state, \@args) | 
| 30 |  |  |  |  |  |  | # | 
| 31 |  |  |  |  |  |  | # Module constructor.  The first, mandatory parameter should be a | 
| 32 |  |  |  |  |  |  | # reference to an AppConfig::State object to which all actions should | 
| 33 |  |  |  |  |  |  | # be applied.  The second parameter may be a reference to a list of | 
| 34 |  |  |  |  |  |  | # command line arguments.  This list reference is passed to parse() for | 
| 35 |  |  |  |  |  |  | # processing. | 
| 36 |  |  |  |  |  |  | # | 
| 37 |  |  |  |  |  |  | # Returns a reference to a newly created AppConfig::Getopt object. | 
| 38 |  |  |  |  |  |  | #------------------------------------------------------------------------ | 
| 39 |  |  |  |  |  |  |  | 
| 40 |  |  |  |  |  |  | sub new { | 
| 41 | 2 |  |  | 2 | 0 | 5 | my $class = shift; | 
| 42 | 2 |  |  |  |  | 3 | my $state = shift; | 
| 43 | 2 |  |  |  |  | 4 | my $self = { | 
| 44 |  |  |  |  |  |  | STATE => $state, | 
| 45 |  |  |  |  |  |  | }; | 
| 46 |  |  |  |  |  |  |  | 
| 47 | 2 |  |  |  |  | 4 | bless $self, $class; | 
| 48 |  |  |  |  |  |  |  | 
| 49 |  |  |  |  |  |  | # call parse() to parse any arg list passed | 
| 50 | 2 | 50 |  |  |  | 5 | $self->parse(@_) | 
| 51 |  |  |  |  |  |  | if @_; | 
| 52 |  |  |  |  |  |  |  | 
| 53 | 2 |  |  |  |  | 18 | return $self; | 
| 54 |  |  |  |  |  |  | } | 
| 55 |  |  |  |  |  |  |  | 
| 56 |  |  |  |  |  |  |  | 
| 57 |  |  |  |  |  |  | #------------------------------------------------------------------------ | 
| 58 |  |  |  |  |  |  | # parse(@$config, \@args) | 
| 59 |  |  |  |  |  |  | # | 
| 60 |  |  |  |  |  |  | # Constructs the appropriate configuration information and then delegates | 
| 61 |  |  |  |  |  |  | # the task of processing command line options to Getopt::Long. | 
| 62 |  |  |  |  |  |  | # | 
| 63 |  |  |  |  |  |  | # Returns 1 on success or 0 if one or more warnings were raised. | 
| 64 |  |  |  |  |  |  | #------------------------------------------------------------------------ | 
| 65 |  |  |  |  |  |  |  | 
| 66 |  |  |  |  |  |  | sub parse { | 
| 67 | 4 |  |  | 4 | 0 | 4 | my $self  = shift; | 
| 68 | 4 |  |  |  |  | 8 | my $state = $self->{ STATE }; | 
| 69 | 4 |  |  |  |  | 4 | my (@config, $args, $getopt); | 
| 70 |  |  |  |  |  |  |  | 
| 71 | 4 |  |  |  |  | 5 | local $" = ', '; | 
| 72 |  |  |  |  |  |  |  | 
| 73 |  |  |  |  |  |  | # we trap $SIG{__WARN__} errors and patch them into AppConfig::State | 
| 74 |  |  |  |  |  |  | local $SIG{__WARN__} = sub { | 
| 75 | 0 |  |  | 0 |  | 0 | my $msg = shift; | 
| 76 |  |  |  |  |  |  |  | 
| 77 |  |  |  |  |  |  | # AppConfig::State doesn't expect CR terminated error messages | 
| 78 |  |  |  |  |  |  | # and it uses printf, so we protect any embedded '%' chars | 
| 79 | 0 |  |  |  |  | 0 | chomp($msg); | 
| 80 | 0 |  |  |  |  | 0 | $state->_error("%s", $msg); | 
| 81 | 4 |  |  |  |  | 21 | }; | 
| 82 |  |  |  |  |  |  |  | 
| 83 |  |  |  |  |  |  | # slurp all config items into @config | 
| 84 | 4 |  | 100 |  |  | 57 | push(@config, shift) while defined $_[0] && ! ref($_[0]); | 
| 85 |  |  |  |  |  |  |  | 
| 86 |  |  |  |  |  |  | # add debug status if appropriate (hmm...can't decide about this) | 
| 87 |  |  |  |  |  |  | #    push(@config, 'debug') if $state->_debug(); | 
| 88 |  |  |  |  |  |  |  | 
| 89 |  |  |  |  |  |  | # next parameter may be a reference to a list of args | 
| 90 | 4 |  |  |  |  | 4 | $args = shift; | 
| 91 |  |  |  |  |  |  |  | 
| 92 |  |  |  |  |  |  | # copy any args explicitly specified into @ARGV | 
| 93 | 4 | 100 |  |  |  | 18 | @ARGV = @$args if defined $args; | 
| 94 |  |  |  |  |  |  |  | 
| 95 |  |  |  |  |  |  | # we enclose in an eval block because constructor may die() | 
| 96 | 4 |  |  |  |  | 4 | eval { | 
| 97 |  |  |  |  |  |  | # configure Getopt::Long | 
| 98 | 4 |  |  |  |  | 11 | Getopt::Long::Configure(@config); | 
| 99 |  |  |  |  |  |  |  | 
| 100 |  |  |  |  |  |  | # construct options list from AppConfig::State variables | 
| 101 | 4 |  |  |  |  | 107 | my @opts = $self->{ STATE   }->_getopt_state(); | 
| 102 |  |  |  |  |  |  |  | 
| 103 |  |  |  |  |  |  | # DEBUG | 
| 104 | 4 | 50 |  |  |  | 13 | if ($state->_debug()) { | 
| 105 | 0 |  |  |  |  | 0 | print STDERR "Calling GetOptions(@opts)\n"; | 
| 106 | 0 |  |  |  |  | 0 | print STDERR "\@ARGV = (@ARGV)\n"; | 
| 107 |  |  |  |  |  |  | }; | 
| 108 |  |  |  |  |  |  |  | 
| 109 |  |  |  |  |  |  | # call GetOptions() with specifications constructed from the state | 
| 110 | 4 |  |  |  |  | 12 | $getopt = GetOptions(@opts); | 
| 111 |  |  |  |  |  |  | }; | 
| 112 | 4 | 50 |  |  |  | 164 | if ($@) { | 
| 113 | 0 |  |  |  |  | 0 | chomp($@); | 
| 114 | 0 |  |  |  |  | 0 | $state->_error("%s", $@); | 
| 115 | 0 |  |  |  |  | 0 | return 0; | 
| 116 |  |  |  |  |  |  | } | 
| 117 |  |  |  |  |  |  |  | 
| 118 |  |  |  |  |  |  | # udpdate any args reference passed to include only that which is left | 
| 119 |  |  |  |  |  |  | # in @ARGV | 
| 120 | 4 | 100 |  |  |  | 12 | @$args = @ARGV if defined $args; | 
| 121 |  |  |  |  |  |  |  | 
| 122 | 4 |  |  |  |  | 31 | return $getopt; | 
| 123 |  |  |  |  |  |  | } | 
| 124 |  |  |  |  |  |  |  | 
| 125 |  |  |  |  |  |  |  | 
| 126 |  |  |  |  |  |  | #======================================================================== | 
| 127 |  |  |  |  |  |  | # AppConfig::State | 
| 128 |  |  |  |  |  |  | #======================================================================== | 
| 129 |  |  |  |  |  |  |  | 
| 130 |  |  |  |  |  |  | package AppConfig::State; | 
| 131 |  |  |  |  |  |  |  | 
| 132 |  |  |  |  |  |  | #------------------------------------------------------------------------ | 
| 133 |  |  |  |  |  |  | # _getopt_state() | 
| 134 |  |  |  |  |  |  | # | 
| 135 |  |  |  |  |  |  | # Constructs option specs in the Getopt::Long format for each variable | 
| 136 |  |  |  |  |  |  | # definition. | 
| 137 |  |  |  |  |  |  | # | 
| 138 |  |  |  |  |  |  | # Returns a list of specification strings. | 
| 139 |  |  |  |  |  |  | #------------------------------------------------------------------------ | 
| 140 |  |  |  |  |  |  |  | 
| 141 |  |  |  |  |  |  | sub _getopt_state { | 
| 142 | 4 |  |  | 4 |  | 5 | my $self = shift; | 
| 143 | 4 |  |  |  |  | 4 | my ($var, $spec, $args, $argcount, @specs); | 
| 144 |  |  |  |  |  |  |  | 
| 145 | 4 |  |  | 16 |  | 7 | my $linkage = sub { $self->set(@_) }; | 
|  | 16 |  |  |  |  | 2784 |  | 
| 146 |  |  |  |  |  |  |  | 
| 147 | 4 |  |  |  |  | 5 | foreach $var (keys %{ $self->{ VARIABLE } }) { | 
|  | 4 |  |  |  |  | 19 |  | 
| 148 | 18 | 100 |  |  |  | 15 | $spec  = join('|', $var, @{ $self->{ ALIASES }->{ $var } || [ ] }); | 
|  | 18 |  |  |  |  | 63 |  | 
| 149 |  |  |  |  |  |  |  | 
| 150 |  |  |  |  |  |  | # an ARGS value is used, if specified | 
| 151 | 18 | 100 |  |  |  | 33 | unless (defined ($args = $self->{ ARGS }->{ $var })) { | 
| 152 |  |  |  |  |  |  | # otherwise, construct a basic one from ARGCOUNT | 
| 153 |  |  |  |  |  |  | ARGCOUNT: { | 
| 154 | 8 |  |  |  |  | 7 | last ARGCOUNT unless | 
| 155 | 8 | 50 |  |  |  | 14 | defined ($argcount = $self->{ ARGCOUNT }->{ $var }); | 
| 156 |  |  |  |  |  |  |  | 
| 157 | 8 | 100 |  |  |  | 17 | $args = "=s",  last ARGCOUNT if $argcount eq ARGCOUNT_ONE; | 
| 158 | 4 | 100 |  |  |  | 12 | $args = "=s@", last ARGCOUNT if $argcount eq ARGCOUNT_LIST; | 
| 159 | 2 | 50 |  |  |  | 3 | $args = "=s%", last ARGCOUNT if $argcount eq ARGCOUNT_HASH; | 
| 160 | 2 |  |  |  |  | 8 | $args = "!"; | 
| 161 |  |  |  |  |  |  | } | 
| 162 |  |  |  |  |  |  | } | 
| 163 | 18 | 50 |  |  |  | 27 | $spec .= $args if defined $args; | 
| 164 |  |  |  |  |  |  |  | 
| 165 | 18 |  |  |  |  | 21 | push(@specs, $spec, $linkage); | 
| 166 |  |  |  |  |  |  | } | 
| 167 |  |  |  |  |  |  |  | 
| 168 | 4 |  |  |  |  | 16 | return @specs; | 
| 169 |  |  |  |  |  |  | } | 
| 170 |  |  |  |  |  |  |  | 
| 171 |  |  |  |  |  |  |  | 
| 172 |  |  |  |  |  |  |  | 
| 173 |  |  |  |  |  |  | 1; | 
| 174 |  |  |  |  |  |  |  | 
| 175 |  |  |  |  |  |  | __END__ |