| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package CmdArguments; | 
| 2 |  |  |  |  |  |  |  | 
| 3 | 1 |  |  | 1 |  | 161552 | use strict; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 41 |  | 
| 4 |  |  |  |  |  |  |  | 
| 5 | 1 |  |  | 1 |  | 5 | use vars qw($VERSION); | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 75 |  | 
| 6 |  |  |  |  |  |  |  | 
| 7 |  |  |  |  |  |  | $VERSION = '1.00'; | 
| 8 |  |  |  |  |  |  |  | 
| 9 |  |  |  |  |  |  | =head1 NAME | 
| 10 |  |  |  |  |  |  |  | 
| 11 |  |  |  |  |  |  | CmdArguments - Module to process arguments passed on command line | 
| 12 |  |  |  |  |  |  |  | 
| 13 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 14 |  |  |  |  |  |  |  | 
| 15 |  |  |  |  |  |  | # program name args.pl | 
| 16 |  |  |  |  |  |  | use CmdArguments; | 
| 17 |  |  |  |  |  |  |  | 
| 18 |  |  |  |  |  |  | my $var1 = 10;          # initialize variable | 
| 19 |  |  |  |  |  |  | my $var2 = 0;           # with default values. | 
| 20 |  |  |  |  |  |  | my @var3 = ( 1, 2, 3);  # well, if you like to. | 
| 21 |  |  |  |  |  |  | my @var4;               # but, not necessary | 
| 22 |  |  |  |  |  |  |  | 
| 23 |  |  |  |  |  |  | my $parse_ref = [ | 
| 24 |  |  |  |  |  |  | [ "arg1", \$var1 ], # argTypeScalar is assumed | 
| 25 |  |  |  |  |  |  | [ "arg2", \$var2, | 
| 26 |  |  |  |  |  |  | {TYPE => argTypeSwitch}], # explicit argTypeSwitch | 
| 27 |  |  |  |  |  |  | [ "arg3", \@var3 ], # argTypeArray assumed | 
| 28 |  |  |  |  |  |  | [ "arg4", \@var4, | 
| 29 |  |  |  |  |  |  | {UNIQUE => 1}], # argTypeArray assumed | 
| 30 |  |  |  |  |  |  | ]; | 
| 31 |  |  |  |  |  |  |  | 
| 32 |  |  |  |  |  |  | CmdArguments::parse(@ARGV, $parse_ref); | 
| 33 |  |  |  |  |  |  |  | 
| 34 |  |  |  |  |  |  | print "var1 = $var1\n"; | 
| 35 |  |  |  |  |  |  | print "var2 = $var2\n"; | 
| 36 |  |  |  |  |  |  | print "var3 = @var3\n"; | 
| 37 |  |  |  |  |  |  | print "var4 = @var4\n"; | 
| 38 |  |  |  |  |  |  |  | 
| 39 |  |  |  |  |  |  | exit 0; | 
| 40 |  |  |  |  |  |  |  | 
| 41 |  |  |  |  |  |  | test command ... | 
| 42 |  |  |  |  |  |  |  | 
| 43 |  |  |  |  |  |  | args.pl -arg1 23 -arg2 -arg3 2 4 3 2 5 -arg4 2 4 3 2 4 | 
| 44 |  |  |  |  |  |  |  | 
| 45 |  |  |  |  |  |  | should generate following output... | 
| 46 |  |  |  |  |  |  |  | 
| 47 |  |  |  |  |  |  | var1 = 23 | 
| 48 |  |  |  |  |  |  | var2 = 1 | 
| 49 |  |  |  |  |  |  | var3 = 2 4 3 2 5 | 
| 50 |  |  |  |  |  |  | var4 = 2 4 3 | 
| 51 |  |  |  |  |  |  |  | 
| 52 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 53 |  |  |  |  |  |  |  | 
| 54 |  |  |  |  |  |  | This module provides some handy functions to process | 
| 55 |  |  |  |  |  |  | command line options. | 
| 56 |  |  |  |  |  |  |  | 
| 57 |  |  |  |  |  |  | When this module is included it introduces following | 
| 58 |  |  |  |  |  |  | constants in the calling program namespace... | 
| 59 |  |  |  |  |  |  |  | 
| 60 |  |  |  |  |  |  | argTypeScalar = 0 | 
| 61 |  |  |  |  |  |  | argTypeArray  = 1 | 
| 62 |  |  |  |  |  |  | argTypeSwitch = 2 | 
| 63 |  |  |  |  |  |  |  | 
| 64 |  |  |  |  |  |  | =cut | 
| 65 |  |  |  |  |  |  |  | 
| 66 |  |  |  |  |  |  | sub BEGIN { | 
| 67 | 1 |  |  | 1 |  | 6 | use constant argTypeScalar => 0; | 
|  | 1 |  |  |  |  | 6 |  | 
|  | 1 |  |  |  |  | 79 |  | 
| 68 | 1 |  |  | 1 |  | 4 | use constant argTypeArray  => 1; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 45 |  | 
| 69 | 1 |  |  | 1 |  | 4 | use constant argTypeSwitch => 2; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 35 |  | 
| 70 | 1 |  |  | 1 |  | 3 | use constant argTypeHash   => 3; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 35 |  | 
| 71 |  |  |  |  |  |  |  | 
| 72 | 1 |  |  | 1 |  | 3 | my $pkg = caller; | 
| 73 | 1 |  |  | 1 |  | 9 | no strict 'refs'; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 155 |  | 
| 74 | 1 |  |  |  |  | 1 | *{"${pkg}::argTypeScalar"} = sub () { argTypeScalar }; | 
|  | 1 |  |  |  |  | 5 |  | 
| 75 | 1 |  |  |  |  | 2 | *{"${pkg}::argTypeArray"}  = sub () { argTypeArray }; | 
|  | 1 |  |  |  |  | 4 |  | 
| 76 | 1 |  |  |  |  | 3 | *{"${pkg}::argTypeSwitch"} = sub () { argTypeSwitch }; | 
|  | 1 |  |  |  |  | 4 |  | 
| 77 | 1 |  |  |  |  | 1 | *{"${pkg}::argTypeHash"}   = sub () { argTypeHash }; | 
|  | 1 |  |  |  |  | 72 |  | 
| 78 |  |  |  |  |  |  | } | 
| 79 |  |  |  |  |  |  |  | 
| 80 |  |  |  |  |  |  | =over 1 | 
| 81 |  |  |  |  |  |  |  | 
| 82 |  |  |  |  |  |  | =item B | 
| 83 |  |  |  |  |  |  |  | 
| 84 |  |  |  |  |  |  | Simplest way to use this program is to call B (static function). | 
| 85 |  |  |  |  |  |  |  | 
| 86 |  |  |  |  |  |  | Calling syntax is... | 
| 87 |  |  |  |  |  |  |  | 
| 88 |  |  |  |  |  |  | I, L<$array_ref|$array_ref>, | 
| 89 |  |  |  |  |  |  | I>, I>)> | 
| 90 |  |  |  |  |  |  |  | 
| 91 |  |  |  |  |  |  | =over 2 | 
| 92 |  |  |  |  |  |  |  | 
| 93 |  |  |  |  |  |  | =item I<@arguments> | 
| 94 |  |  |  |  |  |  |  | 
| 95 |  |  |  |  |  |  | array of command line arguments. So, @ARGV could be passed instead. | 
| 96 |  |  |  |  |  |  |  | 
| 97 |  |  |  |  |  |  | =item I<$array_ref> | 
| 98 |  |  |  |  |  |  |  | 
| 99 |  |  |  |  |  |  | reference to an array containing information about how to | 
| 100 |  |  |  |  |  |  | parse data in @arguments. | 
| 101 |  |  |  |  |  |  |  | 
| 102 |  |  |  |  |  |  | basic structure of $array_ref is... | 
| 103 |  |  |  |  |  |  |  | 
| 104 |  |  |  |  |  |  | $array_ref = [ I<$array_ref_for_individual_tag>, ...]; | 
| 105 |  |  |  |  |  |  |  | 
| 106 |  |  |  |  |  |  | $array_ref_for_individual_tag = [I> | 
| 107 |  |  |  |  |  |  | , I>, | 
| 108 |  |  |  |  |  |  | I>]; # $hash_ref is optional | 
| 109 |  |  |  |  |  |  |  | 
| 110 |  |  |  |  |  |  | =over 3 | 
| 111 |  |  |  |  |  |  |  | 
| 112 |  |  |  |  |  |  | =item I<$hash_ref> | 
| 113 |  |  |  |  |  |  |  | 
| 114 |  |  |  |  |  |  | reference to a hash containing supplementary information about $option_tag | 
| 115 |  |  |  |  |  |  |  | 
| 116 |  |  |  |  |  |  | $hash_ref = { | 
| 117 |  |  |  |  |  |  | TYPE   => argType..., # argTypeSwitch | 
| 118 |  |  |  |  |  |  | # argTypeArray or argTypeScalar | 
| 119 |  |  |  |  |  |  |  | 
| 120 |  |  |  |  |  |  | UNIQUE => 1,          # 1 or 0 | 
| 121 |  |  |  |  |  |  |  | 
| 122 |  |  |  |  |  |  | USAGE  => "help information", # try giving -h or -help | 
| 123 |  |  |  |  |  |  | # on command line | 
| 124 |  |  |  |  |  |  |  | 
| 125 |  |  |  |  |  |  | FUNC   => sub { eval $_[0] } | 
| 126 |  |  |  |  |  |  | }; | 
| 127 |  |  |  |  |  |  |  | 
| 128 |  |  |  |  |  |  | =over 4 | 
| 129 |  |  |  |  |  |  |  | 
| 130 |  |  |  |  |  |  | =item TYPE | 
| 131 |  |  |  |  |  |  |  | 
| 132 |  |  |  |  |  |  | this specifies what kind of variable reference is passed in | 
| 133 |  |  |  |  |  |  | $ref_of_variable. If TYPE is argTypeScalar or argTypeSwitch | 
| 134 |  |  |  |  |  |  | it assumes reference to a scalar. If TYPE is argTypeArray it | 
| 135 |  |  |  |  |  |  | assumes reference to an array. | 
| 136 |  |  |  |  |  |  |  | 
| 137 |  |  |  |  |  |  | if TYPE tag is not provided then ... | 
| 138 |  |  |  |  |  |  |  | 
| 139 |  |  |  |  |  |  | 1. I is assumed if $ref_of_variable is a scalar reference | 
| 140 |  |  |  |  |  |  |  | 
| 141 |  |  |  |  |  |  | 2. I is assumed if $ref_of_variable is an array reference | 
| 142 |  |  |  |  |  |  |  | 
| 143 |  |  |  |  |  |  | =over 5 | 
| 144 |  |  |  |  |  |  |  | 
| 145 |  |  |  |  |  |  | =item What is argType...? | 
| 146 |  |  |  |  |  |  |  | 
| 147 |  |  |  |  |  |  | =over 6 | 
| 148 |  |  |  |  |  |  |  | 
| 149 |  |  |  |  |  |  | =item argTypeSwitch | 
| 150 |  |  |  |  |  |  |  | 
| 151 |  |  |  |  |  |  | on command line you can not provide value for an option. | 
| 152 |  |  |  |  |  |  |  | 
| 153 |  |  |  |  |  |  | =item argTypeScalar | 
| 154 |  |  |  |  |  |  |  | 
| 155 |  |  |  |  |  |  | on command line you must provide one and only one value | 
| 156 |  |  |  |  |  |  |  | 
| 157 |  |  |  |  |  |  | =item argTypeArray | 
| 158 |  |  |  |  |  |  |  | 
| 159 |  |  |  |  |  |  | on command line you can provide zero or more values | 
| 160 |  |  |  |  |  |  |  | 
| 161 |  |  |  |  |  |  | =back 6 | 
| 162 |  |  |  |  |  |  |  | 
| 163 |  |  |  |  |  |  | =back 5 | 
| 164 |  |  |  |  |  |  |  | 
| 165 |  |  |  |  |  |  | =item UNIQUE | 
| 166 |  |  |  |  |  |  |  | 
| 167 |  |  |  |  |  |  | this tag is applicable for option type I only. | 
| 168 |  |  |  |  |  |  | it can be 0 or 1. 1 means make unique array. So, if an | 
| 169 |  |  |  |  |  |  | option is defined as UNIQUE then on command line if you | 
| 170 |  |  |  |  |  |  | give say 2 3 4 5 3 4 6 7 then array will hold 2 3 4 5 6 7. | 
| 171 |  |  |  |  |  |  | If it was not unique then it will hold 2 3 4 5 3 4 6 7. | 
| 172 |  |  |  |  |  |  |  | 
| 173 |  |  |  |  |  |  | =item FUNC | 
| 174 |  |  |  |  |  |  |  | 
| 175 |  |  |  |  |  |  | Holds a reference to a function. Function should take | 
| 176 |  |  |  |  |  |  | a scalar argument and return a scalar if option is | 
| 177 |  |  |  |  |  |  | argTypeScalar and return an array if option is | 
| 178 |  |  |  |  |  |  | argTypeArray. This is not used for option type argTypeSwitch. | 
| 179 |  |  |  |  |  |  |  | 
| 180 |  |  |  |  |  |  | Example: if option type is an argTypeArray. and function is | 
| 181 |  |  |  |  |  |  | defined like | 
| 182 |  |  |  |  |  |  |  | 
| 183 |  |  |  |  |  |  | FUNC => sub { eval $_[0] } | 
| 184 |  |  |  |  |  |  |  | 
| 185 |  |  |  |  |  |  | and if on the command line something like 1..3 or 1,2,3 | 
| 186 |  |  |  |  |  |  | is passed then it will generate an array having values 1 2 3. | 
| 187 |  |  |  |  |  |  |  | 
| 188 |  |  |  |  |  |  | =back 4 | 
| 189 |  |  |  |  |  |  |  | 
| 190 |  |  |  |  |  |  | =item I<$ref_of_variable> | 
| 191 |  |  |  |  |  |  |  | 
| 192 |  |  |  |  |  |  | Can pass reference of a scalar or an array variable | 
| 193 |  |  |  |  |  |  | depending on what require from command line. | 
| 194 |  |  |  |  |  |  |  | 
| 195 |  |  |  |  |  |  | =item I<$option_tag> | 
| 196 |  |  |  |  |  |  |  | 
| 197 |  |  |  |  |  |  | It is the name of the option tag. if option tag is I then | 
| 198 |  |  |  |  |  |  | on command line you have to specify option like I<-opt>. | 
| 199 |  |  |  |  |  |  |  | 
| 200 |  |  |  |  |  |  | =back 3 | 
| 201 |  |  |  |  |  |  |  | 
| 202 |  |  |  |  |  |  | =item $text_or_func1 | 
| 203 |  |  |  |  |  |  |  | 
| 204 |  |  |  |  |  |  | =item $text_or_func2 | 
| 205 |  |  |  |  |  |  |  | 
| 206 |  |  |  |  |  |  | pass text or reference to a function. If function is passed | 
| 207 |  |  |  |  |  |  | it should return text or should itself print message on | 
| 208 |  |  |  |  |  |  | STDERR. Try experimenting by passing -h or -help in the argument. | 
| 209 |  |  |  |  |  |  | $text_or_func1 is printed after the help text is printed and | 
| 210 |  |  |  |  |  |  | $text_or_func1 is used before printing helptext. | 
| 211 |  |  |  |  |  |  |  | 
| 212 |  |  |  |  |  |  | =back 2 | 
| 213 |  |  |  |  |  |  |  | 
| 214 |  |  |  |  |  |  | =back 1 | 
| 215 |  |  |  |  |  |  |  | 
| 216 |  |  |  |  |  |  | =cut | 
| 217 |  |  |  |  |  |  |  | 
| 218 |  |  |  |  |  |  | sub parse (\@@) { | 
| 219 | 1 |  |  | 1 | 1 | 101 | my ($arg_ref, $process, $postusage, $preusage) = @_; | 
| 220 |  |  |  |  |  |  |  | 
| 221 | 1 |  |  | 1 |  | 5 | use constant argTagField  => 0; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 48 |  | 
| 222 | 1 |  |  | 1 |  | 5 | use constant argVarField  => 1; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 47 |  | 
| 223 | 1 |  |  | 1 |  | 4 | use constant argHashField => 2; | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 2335 |  | 
| 224 |  |  |  |  |  |  |  | 
| 225 | 1 |  |  |  |  | 9 | my %functions = (argTypeScalar+0 => "argScalar", | 
| 226 |  |  |  |  |  |  | argTypeArray+0  => "argArray", | 
| 227 |  |  |  |  |  |  | argTypeHash+0  => "argHash", | 
| 228 |  |  |  |  |  |  | argTypeSwitch+0 => "argSwitch"); | 
| 229 |  |  |  |  |  |  |  | 
| 230 | 1 |  |  |  |  | 9 | my $args = CmdArguments->beginArg(@$arg_ref); | 
| 231 | 1 |  |  |  |  | 3 | foreach my $argsyntax (@$process) { | 
| 232 | 4 | 100 |  |  |  | 11 | my $typehash = (defined $argsyntax->[argHashField] | 
| 233 |  |  |  |  |  |  | ? $argsyntax->[argHashField] : {}); | 
| 234 |  |  |  |  |  |  |  | 
| 235 | 4 |  |  |  |  | 7 | my $tag     = $argsyntax->[argTagField]; | 
| 236 | 4 |  |  |  |  | 5 | my $var     = $argsyntax->[argVarField]; | 
| 237 | 4 |  |  |  |  | 13 | my $type    = _value($typehash->{TYPE}); | 
| 238 | 4 |  |  |  |  | 14 | my $sub     = _value($typehash->{FUNC}); | 
| 239 | 4 |  |  |  |  | 12 | my $unique  = _value($typehash->{UNIQUE}); | 
| 240 | 4 |  |  |  |  | 11 | my $usage   = _value($typehash->{USAGE}); | 
| 241 | 4 |  |  |  |  | 12 | my $dispOpt = _value($typehash->{DISPOPTION}); | 
| 242 | 4 |  |  |  |  | 11 | my $params  = _value($typehash->{PARAMS}); | 
| 243 |  |  |  |  |  |  |  | 
| 244 | 4 | 100 |  |  |  | 33 | unless (defined $type) { | 
| 245 | 3 | 100 |  |  |  | 11 | $type = argTypeScalar if ref($var) eq 'SCALAR'; | 
| 246 | 3 | 100 |  |  |  | 9 | $type = argTypeArray  if ref($var) eq 'ARRAY'; | 
| 247 | 3 | 50 |  |  |  | 7 | $type = argTypeHash   if ref($var) eq 'HASH'; | 
| 248 | 3 | 50 |  |  |  | 8 | unless (defined $type) { | 
| 249 | 0 |  |  |  |  | 0 | die "ERROR: option ($tag) - variable should be a reference\n"; | 
| 250 |  |  |  |  |  |  | } | 
| 251 |  |  |  |  |  |  | } | 
| 252 |  |  |  |  |  |  |  | 
| 253 | 4 |  |  |  |  | 13 | my @arguments = ($tag => $var, usage => $usage, | 
| 254 |  |  |  |  |  |  | dispOption => $dispOpt, | 
| 255 |  |  |  |  |  |  | func => $sub, unique => $unique, params => $params); | 
| 256 |  |  |  |  |  |  |  | 
| 257 | 4 | 50 |  |  |  | 9 | if (exists $functions{$type}) { | 
| 258 | 4 |  |  |  |  | 6 | my $function = $functions{$type}; | 
| 259 | 4 |  |  |  |  | 22 | $args->$function(@arguments); | 
| 260 |  |  |  |  |  |  | } else { | 
| 261 | 0 |  |  |  |  | 0 | die "Please check type ($type)\n"; | 
| 262 |  |  |  |  |  |  | } | 
| 263 |  |  |  |  |  |  | } | 
| 264 |  |  |  |  |  |  |  | 
| 265 | 1 |  |  |  |  | 3 | my @return = (); | 
| 266 | 1 | 50 |  |  |  | 4 | if (wantarray) { | 
| 267 | 0 |  |  |  |  | 0 | @return = $args->endArg; | 
| 268 |  |  |  |  |  |  | } else { | 
| 269 | 1 |  |  |  |  | 5 | $args->endArg; | 
| 270 |  |  |  |  |  |  | } | 
| 271 | 1 |  |  |  |  | 8 | $args->usage($preusage, $postusage); | 
| 272 | 1 |  |  |  |  | 18 | return @return; | 
| 273 |  |  |  |  |  |  | } | 
| 274 |  |  |  |  |  |  |  | 
| 275 |  |  |  |  |  |  | # Start Argument processing | 
| 276 |  |  |  |  |  |  | # usage: my $arg = CmdArguments->beginArg(@ARGV); | 
| 277 |  |  |  |  |  |  | sub beginArg { | 
| 278 | 1 |  |  | 1 | 0 | 8 | my ($class, @argv) = @_; | 
| 279 |  |  |  |  |  |  |  | 
| 280 | 1 |  |  |  |  | 2 | my $self = {}; | 
| 281 | 1 |  |  |  |  | 3 | bless $self, $class; | 
| 282 |  |  |  |  |  |  |  | 
| 283 |  |  |  |  |  |  | # trap the arguments | 
| 284 | 1 | 50 |  |  |  | 11 | $self->{ARGS} = @argv ? [@argv] : \@ARGV; | 
| 285 |  |  |  |  |  |  | # usage string in case of help or error | 
| 286 | 1 |  |  |  |  | 3 | $self->{USAGE} = ""; | 
| 287 |  |  |  |  |  |  | # required for generating variable names | 
| 288 | 1 |  |  |  |  | 3 | $self->{_TMPNUM} = 0; | 
| 289 |  |  |  |  |  |  |  | 
| 290 |  |  |  |  |  |  | # trap the original accumulator; | 
| 291 | 1 |  |  |  |  | 4 | $self->{_ACCUMULATOR} = $^A; | 
| 292 |  |  |  |  |  |  |  | 
| 293 |  |  |  |  |  |  | # temporay variable | 
| 294 |  |  |  |  |  |  | # to store help status | 
| 295 | 1 |  |  |  |  | 2 | my $tmpHelpVar = 0; | 
| 296 | 1 |  |  |  |  | 2 | $self->{_HELPSAT} = \$tmpHelpVar; | 
| 297 |  |  |  |  |  |  |  | 
| 298 |  |  |  |  |  |  | # hash where reference user supplied | 
| 299 |  |  |  |  |  |  | # variables are stored | 
| 300 | 1 |  |  |  |  | 3 | $self->{_VARIABLES} = {}; | 
| 301 |  |  |  |  |  |  | # hash where user defined functions are stored | 
| 302 | 1 |  |  |  |  | 3 | $self->{_FUNCTIONS} = {}; | 
| 303 |  |  |  |  |  |  |  | 
| 304 |  |  |  |  |  |  | # used in case wrong option is given | 
| 305 | 1 |  |  |  |  | 3 | $self->{_UNKNOWN_OPTIONS} = []; | 
| 306 |  |  |  |  |  |  |  | 
| 307 |  |  |  |  |  |  | # begin generating main loop | 
| 308 | 1 |  |  |  |  | 3 | $self->{LOOP_STRING} = <<'BEGINARG'; | 
| 309 |  |  |  |  |  |  | while (@{$self->{ARGS}}) { | 
| 310 |  |  |  |  |  |  | $_ = shift @{$self->{ARGS}}; | 
| 311 |  |  |  |  |  |  | BEGINARG | 
| 312 |  |  |  |  |  |  |  | 
| 313 | 1 |  |  |  |  | 4 | return $self; | 
| 314 |  |  |  |  |  |  | } | 
| 315 |  |  |  |  |  |  |  | 
| 316 |  |  |  |  |  |  | # process scalar argument | 
| 317 |  |  |  |  |  |  | # usage: $arg->argScalar(option => \$scalar_variable, | 
| 318 |  |  |  |  |  |  | #                        usage => "description", | 
| 319 |  |  |  |  |  |  | #                        func => sub { return $_[0] }); | 
| 320 |  |  |  |  |  |  | sub argScalar { | 
| 321 | 1 |  |  | 1 | 0 | 2 | my $self   = shift; | 
| 322 |  |  |  |  |  |  |  | 
| 323 |  |  |  |  |  |  | # get user supplied argument and variable (where | 
| 324 |  |  |  |  |  |  | # value is to be stored) and other options | 
| 325 | 1 |  |  |  |  | 5 | my ($arg, $variable, %options) = _makeOptions(@_); | 
| 326 |  |  |  |  |  |  |  | 
| 327 |  |  |  |  |  |  | # store user supplied function and variable | 
| 328 | 1 |  | 50 |  |  | 12 | my ($varName, $funName) = $self->_getVarAndFuncName($variable, | 
| 329 |  |  |  |  |  |  | $options{func} | 
| 330 |  |  |  |  |  |  | || undef); | 
| 331 |  |  |  |  |  |  | # generate code to handle scalar option | 
| 332 | 1 |  |  |  |  | 10 | $self->{LOOP_STRING} .= < | 
| 333 |  |  |  |  |  |  | \/^-($arg)\$\/ && ( do { my \$value = shift(\@{\$self->{ARGS}}); | 
| 334 |  |  |  |  |  |  | \${\$self->{_VARIABLES}{$varName}} | 
| 335 |  |  |  |  |  |  | = \$self->{_FUNCTIONS}{$funName}->(\$value); | 
| 336 |  |  |  |  |  |  | }, next | 
| 337 |  |  |  |  |  |  | ); | 
| 338 |  |  |  |  |  |  | OPRIONARG | 
| 339 |  |  |  |  |  |  |  | 
| 340 |  |  |  |  |  |  | # make usage | 
| 341 | 1 |  |  |  |  | 5 | $self->_makeUsage($arg, %options); | 
| 342 |  |  |  |  |  |  | } | 
| 343 |  |  |  |  |  |  |  | 
| 344 |  |  |  |  |  |  | # process switch argument | 
| 345 |  |  |  |  |  |  | # passed variable will be turned on or off | 
| 346 |  |  |  |  |  |  | # usage: $arg->argScalar(option => \$switch_variable, | 
| 347 |  |  |  |  |  |  | #                        usage => "description"); | 
| 348 |  |  |  |  |  |  | sub argSwitch { | 
| 349 | 2 |  |  | 2 | 0 | 3 | my $self = shift; | 
| 350 |  |  |  |  |  |  |  | 
| 351 |  |  |  |  |  |  | # get user supplied argument and variable (where | 
| 352 |  |  |  |  |  |  | # value is to be stored) and other options | 
| 353 | 2 |  |  |  |  | 5 | my ($arg, $variable, %options) = _makeOptions(@_); | 
| 354 |  |  |  |  |  |  |  | 
| 355 |  |  |  |  |  |  | # store user supplied function and variable | 
| 356 | 2 |  | 50 |  |  | 16 | my ($varName, $funName) = $self->_getVarAndFuncName($variable, | 
| 357 |  |  |  |  |  |  | $options{func} | 
| 358 |  |  |  |  |  |  | || undef); | 
| 359 |  |  |  |  |  |  |  | 
| 360 |  |  |  |  |  |  | # generate code to handle switch option | 
| 361 | 2 |  |  |  |  | 10 | $self->{LOOP_STRING} .= < | 
| 362 |  |  |  |  |  |  | \/^-($arg)\$\/ && ( \${\$self->{_VARIABLES}{$varName}} | 
| 363 |  |  |  |  |  |  | = \!\${\$self->{_VARIABLES}{$varName}}+0 , next); | 
| 364 |  |  |  |  |  |  | OPRIONARG | 
| 365 |  |  |  |  |  |  |  | 
| 366 |  |  |  |  |  |  | # make usage | 
| 367 | 2 |  |  |  |  | 9 | $self->_makeUsage($arg, %options); | 
| 368 |  |  |  |  |  |  | } | 
| 369 |  |  |  |  |  |  |  | 
| 370 |  |  |  |  |  |  | # process array argument | 
| 371 |  |  |  |  |  |  | # usage: $arg->argArray(option => \@array_variable, | 
| 372 |  |  |  |  |  |  | #                       usage => "description", | 
| 373 |  |  |  |  |  |  | #                       unique => 1, | 
| 374 |  |  |  |  |  |  | #                       func => sub { return @_ }); | 
| 375 |  |  |  |  |  |  | sub argArray { | 
| 376 | 2 |  |  | 2 | 0 | 3 | my $self = shift; | 
| 377 |  |  |  |  |  |  |  | 
| 378 |  |  |  |  |  |  | # get user supplied argument and variable (where | 
| 379 |  |  |  |  |  |  | # value is to be stored) and other options | 
| 380 | 2 |  |  |  |  | 5 | my ($arg, $variable, %options) = _makeOptions(@_); | 
| 381 |  |  |  |  |  |  |  | 
| 382 |  |  |  |  |  |  | # uniqe list required (default: yes) | 
| 383 | 2 | 50 | 100 |  |  | 15 | my $unique = exists $options{unique} ? ($options{unique} || 0) : 1; | 
| 384 |  |  |  |  |  |  |  | 
| 385 |  |  |  |  |  |  | # store user supplied function and variable | 
| 386 | 2 |  | 50 |  |  | 13 | my ($varName, $funName) = $self->_getVarAndFuncName($variable, | 
| 387 |  |  |  |  |  |  | $options{func} | 
| 388 |  |  |  |  |  |  | || undef); | 
| 389 | 2 |  |  |  |  | 3 | my $param = $options{params}; | 
| 390 | 2 | 50 |  |  |  | 7 | $param = 'undef' unless defined $param; | 
| 391 | 2 |  |  |  |  | 5 | $self->{_PARAMS}{$varName} = $param; | 
| 392 |  |  |  |  |  |  |  | 
| 393 |  |  |  |  |  |  | # generate code to handle array option | 
| 394 | 2 |  |  |  |  | 16 | $self->{LOOP_STRING} .= < | 
| 395 |  |  |  |  |  |  | \/^-($arg)\$\/ && | 
| 396 |  |  |  |  |  |  | (do { my \%tmp = map { (\$_, 1) | 
| 397 |  |  |  |  |  |  | } \@{\$self->{_VARIABLES}{$varName}}; | 
| 398 |  |  |  |  |  |  | while (\@{\$self->{ARGS}} and \$self->{ARGS}[0] !~ /^-/) { | 
| 399 |  |  |  |  |  |  | my \$value = shift \@{\$self->{ARGS}}; | 
| 400 |  |  |  |  |  |  | my \@values | 
| 401 |  |  |  |  |  |  | = \$self->{_FUNCTIONS} | 
| 402 |  |  |  |  |  |  | {$funName}->(\$value, | 
| 403 |  |  |  |  |  |  | \$self->{_PARAMS}{$varName}); | 
| 404 |  |  |  |  |  |  | if ($unique) { | 
| 405 |  |  |  |  |  |  | \@values = grep { my \$stat = exists \$tmp{\$_}; | 
| 406 |  |  |  |  |  |  | \$stat ||= 0; | 
| 407 |  |  |  |  |  |  | \$tmp{\$_} = 1 unless \$stat; | 
| 408 |  |  |  |  |  |  | !\$stat | 
| 409 |  |  |  |  |  |  | } \@values; | 
| 410 |  |  |  |  |  |  | } | 
| 411 |  |  |  |  |  |  | push(\@{\$self->{_VARIABLES}{$varName}}, \@values) | 
| 412 |  |  |  |  |  |  | if \@values; | 
| 413 |  |  |  |  |  |  | }}, next | 
| 414 |  |  |  |  |  |  | ); | 
| 415 |  |  |  |  |  |  | OPRIONARG | 
| 416 |  |  |  |  |  |  |  | 
| 417 |  |  |  |  |  |  | # make usage | 
| 418 | 2 |  |  |  |  | 9 | $self->_makeUsage($arg, %options); | 
| 419 |  |  |  |  |  |  | } | 
| 420 |  |  |  |  |  |  |  | 
| 421 |  |  |  |  |  |  | # process hash argument | 
| 422 |  |  |  |  |  |  | # usage: $arg->argHash(option => \%hash_variable, | 
| 423 |  |  |  |  |  |  | #                      usage => "description", | 
| 424 |  |  |  |  |  |  | #                      func => sub { ... }); | 
| 425 |  |  |  |  |  |  | sub argHash { | 
| 426 | 0 |  |  | 0 | 0 | 0 | my $self = shift; | 
| 427 |  |  |  |  |  |  |  | 
| 428 |  |  |  |  |  |  | # get user supplied argument and variable (where | 
| 429 |  |  |  |  |  |  | # value is to be stored) and other options | 
| 430 | 0 |  |  |  |  | 0 | my ($arg, $variable, %options) = _makeOptions(@_); | 
| 431 |  |  |  |  |  |  |  | 
| 432 |  |  |  |  |  |  | # uniqe list required (default: yes) | 
| 433 | 0 | 0 | 0 |  |  | 0 | my $unique = exists $options{unique} ? ($options{unique} || 0) : 1; | 
| 434 |  |  |  |  |  |  |  | 
| 435 |  |  |  |  |  |  | # store user supplied function and variable | 
| 436 | 0 |  | 0 |  |  | 0 | my ($varName, $funName) = $self->_getVarAndFuncName($variable, | 
| 437 |  |  |  |  |  |  | $options{func} | 
| 438 |  |  |  |  |  |  | || undef); | 
| 439 | 0 |  |  |  |  | 0 | my $param = $options{params}; | 
| 440 | 0 | 0 |  |  |  | 0 | $param = 'undef' unless defined $param; | 
| 441 | 0 |  |  |  |  | 0 | $self->{_PARAMS}{$varName} = $param; | 
| 442 |  |  |  |  |  |  |  | 
| 443 |  |  |  |  |  |  | # generate code to handle hash option | 
| 444 | 0 |  |  |  |  | 0 | $self->{LOOP_STRING} .= < | 
| 445 |  |  |  |  |  |  | \/^-($arg)\$\/ && | 
| 446 |  |  |  |  |  |  | (do { while (\@{\$self->{ARGS}} and \$self->{ARGS}[0] !~ /^-/) { | 
| 447 |  |  |  |  |  |  | my \$value = shift \@{\$self->{ARGS}}; | 
| 448 |  |  |  |  |  |  | my \$values | 
| 449 |  |  |  |  |  |  | = \$self->{_FUNCTIONS} | 
| 450 |  |  |  |  |  |  | {$funName}->(\$value, | 
| 451 |  |  |  |  |  |  | \$self->{_PARAMS}{$varName}); | 
| 452 |  |  |  |  |  |  | my \$ref = ref(\$values); | 
| 453 |  |  |  |  |  |  | unless (\$ref) { | 
| 454 |  |  |  |  |  |  | \$self->{_VARIABLES}{$varName}{\$values} = 1; | 
| 455 |  |  |  |  |  |  | } elsif ( \$ref eq 'HASH') { | 
| 456 |  |  |  |  |  |  | foreach my \$key (keys \%\$values) { | 
| 457 |  |  |  |  |  |  | \$self->{_VARIABLES}{$varName}{\$key} | 
| 458 |  |  |  |  |  |  | = \$values->{\$key}; | 
| 459 |  |  |  |  |  |  | } | 
| 460 |  |  |  |  |  |  | } | 
| 461 |  |  |  |  |  |  | }}, next | 
| 462 |  |  |  |  |  |  | ); | 
| 463 |  |  |  |  |  |  | OPRIONARG | 
| 464 |  |  |  |  |  |  |  | 
| 465 |  |  |  |  |  |  | # make usage | 
| 466 | 0 |  |  |  |  | 0 | $self->_makeUsage($arg, %options); | 
| 467 |  |  |  |  |  |  | } | 
| 468 |  |  |  |  |  |  |  | 
| 469 |  |  |  |  |  |  | # finish the main loop | 
| 470 |  |  |  |  |  |  | # usage: $arg->endArg; | 
| 471 |  |  |  |  |  |  | sub endArg { | 
| 472 | 1 |  |  | 1 | 0 | 3 | my $self = shift; | 
| 473 |  |  |  |  |  |  |  | 
| 474 |  |  |  |  |  |  | # generate code to provide help | 
| 475 | 1 |  |  |  |  | 5 | $self->argSwitch("h|help" => $self->{_HELPSAT}, | 
| 476 |  |  |  |  |  |  | usage => < "      "); | 
| 477 |  |  |  |  |  |  | show this help. | 
| 478 |  |  |  |  |  |  | HELP | 
| 479 |  |  |  |  |  |  |  | 
| 480 | 1 |  |  |  |  | 2 | my @return = (); | 
| 481 |  |  |  |  |  |  |  | 
| 482 |  |  |  |  |  |  |  | 
| 483 | 1 |  | 50 |  |  | 7 | my $wantarray = wantarray || 0; | 
| 484 |  |  |  |  |  |  |  | 
| 485 |  |  |  |  |  |  | # end the main loop | 
| 486 |  |  |  |  |  |  | # and push unhandled options | 
| 487 | 1 |  |  |  |  | 2 | $self->{LOOP_STRING} .= < | 
| 488 |  |  |  |  |  |  | if (\$wantarray && \$_ !~ /^-/) { | 
| 489 |  |  |  |  |  |  | push \@return, \$_; | 
| 490 |  |  |  |  |  |  | } else { | 
| 491 |  |  |  |  |  |  | push \@{\$self->{_UNKNOWN_OPTIONS}}, \$_; | 
| 492 |  |  |  |  |  |  | } | 
| 493 |  |  |  |  |  |  | } | 
| 494 |  |  |  |  |  |  | ENDLOOP | 
| 495 |  |  |  |  |  |  |  | 
| 496 |  |  |  |  |  |  | # run the main loop | 
| 497 | 1 |  |  |  |  | 683 | eval "$self->{LOOP_STRING}"; | 
| 498 | 1 | 50 |  |  |  | 8 | if ($@) { | 
| 499 | 0 |  |  |  |  | 0 | print STDERR "OPS: $@ \n"; | 
| 500 | 0 |  |  |  |  | 0 | my @array = split "\n", $self->{LOOP_STRING}; | 
| 501 | 0 |  |  |  |  | 0 | my $i = 1; | 
| 502 | 0 |  |  |  |  | 0 | print STDERR map { sprintf("%3d: %s\n", $i++, $_) } @array; | 
|  | 0 |  |  |  |  | 0 |  | 
| 503 | 0 |  |  |  |  | 0 | exit 1; | 
| 504 |  |  |  |  |  |  | } | 
| 505 |  |  |  |  |  |  |  | 
| 506 |  |  |  |  |  |  | # reset format accumulator | 
| 507 | 1 |  |  |  |  | 2 | $^A = $self->{_ACCUMULATOR}; | 
| 508 |  |  |  |  |  |  |  | 
| 509 | 1 |  |  |  |  | 2 | return @return; | 
| 510 |  |  |  |  |  |  | } | 
| 511 |  |  |  |  |  |  |  | 
| 512 |  |  |  |  |  |  | # display usage if require | 
| 513 |  |  |  |  |  |  | # usage: $arg->usage($pre, $post); | 
| 514 |  |  |  |  |  |  | # $pre: string or function reference | 
| 515 |  |  |  |  |  |  | # $post: string or function reference | 
| 516 |  |  |  |  |  |  | # NOTE: if not used help will not be generated | 
| 517 |  |  |  |  |  |  | sub usage { | 
| 518 | 1 |  |  | 1 | 0 | 2 | my ($self, $pre, $pst) = @_; | 
| 519 |  |  |  |  |  |  |  | 
| 520 |  |  |  |  |  |  | # generate string for unknown options | 
| 521 | 1 | 50 |  |  |  | 18 | my $unknown_options = (@{$self->{_UNKNOWN_OPTIONS}} | 
|  | 1 |  |  |  |  | 6 |  | 
| 522 | 0 |  |  |  |  | 0 | ? "(@{$self->{_UNKNOWN_OPTIONS}})" : ""); | 
| 523 | 1 | 50 |  |  |  | 4 | $unknown_options = "$0: Unknown options $unknown_options\n" | 
| 524 |  |  |  |  |  |  | if $unknown_options; | 
| 525 |  |  |  |  |  |  |  | 
| 526 |  |  |  |  |  |  | # handle error or simply help... | 
| 527 | 1 | 50 | 33 |  |  | 1 | if (${$self->{_HELPSAT}} || $unknown_options) { | 
|  | 1 |  |  |  |  | 8 |  | 
| 528 | 0 | 0 |  | 0 |  | 0 | my $prefunc = ref($pre) eq 'CODE' ? $pre : sub { $pre || "" }; | 
|  | 0 | 0 |  |  |  | 0 |  | 
| 529 | 0 | 0 |  | 0 |  | 0 | my $pstfunc = ref($pst) eq 'CODE' ? $pst : sub { $pst || "" }; | 
|  | 0 | 0 |  |  |  | 0 |  | 
| 530 |  |  |  |  |  |  |  | 
| 531 | 0 |  |  |  |  | 0 | print STDERR $unknown_options; | 
| 532 | 0 |  | 0 |  |  | 0 | print STDERR &$prefunc || ""; | 
| 533 | 0 |  |  |  |  | 0 | print STDERR $self->{USAGE}; | 
| 534 | 0 |  | 0 |  |  | 0 | print STDERR &$pstfunc || ""; | 
| 535 | 0 | 0 |  |  |  | 0 | $unknown_options ? exit 100 : exit 0; | 
| 536 |  |  |  |  |  |  | } | 
| 537 |  |  |  |  |  |  | } | 
| 538 |  |  |  |  |  |  |  | 
| 539 |  |  |  |  |  |  | # core code for formatting help | 
| 540 |  |  |  |  |  |  | sub _makeUsage { | 
| 541 | 5 |  |  | 5 |  | 16 | my ($self, $option, %desc) = @_; | 
| 542 |  |  |  |  |  |  |  | 
| 543 | 5 |  | 100 |  |  | 19 | my $description = $desc{usage} || "not ready yet!."; | 
| 544 | 5 |  | 100 |  |  | 16 | my $opts = $desc{dispOption} || "opts"; | 
| 545 |  |  |  |  |  |  |  | 
| 546 | 5 |  |  |  |  | 9 | my $olen = length($option.$opts) + 2; | 
| 547 | 5 |  |  |  |  | 6 | my $format = '@>>>>>>>>>>>>>>>>>>: '; | 
| 548 | 5 | 50 |  |  |  | 10 | if ($olen > 19) { | 
| 549 | 0 |  |  |  |  | 0 | $format = '@' . '>' x $olen . "\n" . " " x 19 . ": "; | 
| 550 |  |  |  |  |  |  | } | 
| 551 |  |  |  |  |  |  |  | 
| 552 | 5 |  |  |  |  | 5 | my $len = 60; | 
| 553 | 5 |  |  |  |  | 12 | my $dformat = '^' . '<' x $len . '~'; | 
| 554 | 5 |  |  |  |  | 6 | my $dlen = length($description); | 
| 555 | 5 |  |  |  |  | 9 | my $line = int($dlen / $len); | 
| 556 |  |  |  |  |  |  |  | 
| 557 | 5 |  |  |  |  | 5 | $line += 2; | 
| 558 | 5 |  |  |  |  | 11 | $format .= join "\n" . " " x 21, map {$dformat} 1..$line; | 
|  | 10 |  |  |  |  | 22 |  | 
| 559 | 5 |  |  |  |  | 15 | my $str = '$^A = ""; formline($format, "-" . $option . ' | 
| 560 |  |  |  |  |  |  | . '" $opts ", ' . ('$description, ' x $line) . '  ); $^A;'; | 
| 561 | 5 |  |  |  |  | 493 | $str = eval $str; | 
| 562 | 5 |  |  |  |  | 22 | chomp($str); | 
| 563 | 5 |  |  |  |  | 6 | $str .= "\n"; | 
| 564 | 5 |  |  |  |  | 70 | $self->{USAGE} .= $str; | 
| 565 |  |  |  |  |  |  | } | 
| 566 |  |  |  |  |  |  |  | 
| 567 |  |  |  |  |  |  | sub _getVariableName { | 
| 568 | 10 |  |  | 10 |  | 11 | my $self = shift; | 
| 569 |  |  |  |  |  |  |  | 
| 570 | 10 |  |  |  |  | 30 | return "VAR_" . (++$self->{_TMPNUM}); | 
| 571 |  |  |  |  |  |  | } | 
| 572 |  |  |  |  |  |  |  | 
| 573 |  |  |  |  |  |  | sub _makeOptions { | 
| 574 | 5 |  |  | 5 |  | 6 | my $option   = shift; | 
| 575 | 5 |  |  |  |  | 7 | my $variable = shift; | 
| 576 | 5 |  |  |  |  | 26 | return ($option, $variable, @_); | 
| 577 |  |  |  |  |  |  | } | 
| 578 |  |  |  |  |  |  |  | 
| 579 |  |  |  |  |  |  | sub _getVarAndFuncName { | 
| 580 | 5 |  |  | 5 |  | 8 | my ($self, $variable, $function) = @_; | 
| 581 |  |  |  |  |  |  |  | 
| 582 | 5 |  |  |  |  | 14 | my $varName = $self->_getVariableName; | 
| 583 | 5 |  |  |  |  | 12 | $self->{_VARIABLES}{$varName} = $variable; | 
| 584 | 5 |  |  |  |  | 11 | my $funName = $self->_getVariableName; | 
| 585 | 5 |  |  | 11 |  | 61 | $self->{_FUNCTIONS}{$funName} = sub { $_[0] }; | 
|  | 11 |  |  |  |  | 244 |  | 
| 586 | 5 | 50 |  |  |  | 13 | if ($function) { | 
| 587 | 0 | 0 |  |  |  | 0 | if (ref($function) eq 'CODE') { | 
| 588 | 0 |  |  |  |  | 0 | $self->{_FUNCTIONS}{$funName} = $function; | 
| 589 |  |  |  |  |  |  | } else { | 
| 590 | 0 |  |  |  |  | 0 | die "ERROR: func should be a reference to a function\n"; | 
| 591 |  |  |  |  |  |  | } | 
| 592 |  |  |  |  |  |  | } | 
| 593 |  |  |  |  |  |  |  | 
| 594 | 5 |  |  |  |  | 14 | return ($varName, $funName); | 
| 595 |  |  |  |  |  |  | } | 
| 596 |  |  |  |  |  |  |  | 
| 597 |  |  |  |  |  |  | sub _value { | 
| 598 | 24 |  |  | 24 |  | 33 | my $val = shift; | 
| 599 | 24 | 100 |  |  |  | 51 | return defined $val ? $val : undef; | 
| 600 |  |  |  |  |  |  | } | 
| 601 |  |  |  |  |  |  |  | 
| 602 |  |  |  |  |  |  | =head1 AUTHOR | 
| 603 |  |  |  |  |  |  |  | 
| 604 |  |  |  |  |  |  | Navneet Kumar, EFE | 
| 605 |  |  |  |  |  |  |  | 
| 606 |  |  |  |  |  |  | =cut | 
| 607 |  |  |  |  |  |  |  | 
| 608 |  |  |  |  |  |  | 1; |