1*0Sstevel@tonic-gatepackage Getopt::Std; 2*0Sstevel@tonic-gaterequire 5.000; 3*0Sstevel@tonic-gaterequire Exporter; 4*0Sstevel@tonic-gate 5*0Sstevel@tonic-gate=head1 NAME 6*0Sstevel@tonic-gate 7*0Sstevel@tonic-gategetopt, getopts - Process single-character switches with switch clustering 8*0Sstevel@tonic-gate 9*0Sstevel@tonic-gate=head1 SYNOPSIS 10*0Sstevel@tonic-gate 11*0Sstevel@tonic-gate use Getopt::Std; 12*0Sstevel@tonic-gate 13*0Sstevel@tonic-gate getopt('oDI'); # -o, -D & -I take arg. Sets $opt_* as a side effect. 14*0Sstevel@tonic-gate getopt('oDI', \%opts); # -o, -D & -I take arg. Values in %opts 15*0Sstevel@tonic-gate getopts('oif:'); # -o & -i are boolean flags, -f takes an argument 16*0Sstevel@tonic-gate # Sets $opt_* as a side effect. 17*0Sstevel@tonic-gate getopts('oif:', \%opts); # options as above. Values in %opts 18*0Sstevel@tonic-gate 19*0Sstevel@tonic-gate=head1 DESCRIPTION 20*0Sstevel@tonic-gate 21*0Sstevel@tonic-gateThe getopt() function processes single-character switches with switch 22*0Sstevel@tonic-gateclustering. Pass one argument which is a string containing all switches 23*0Sstevel@tonic-gatethat take an argument. For each switch found, sets $opt_x (where x is the 24*0Sstevel@tonic-gateswitch name) to the value of the argument if an argument is expected, 25*0Sstevel@tonic-gateor 1 otherwise. Switches which take an argument don't care whether 26*0Sstevel@tonic-gatethere is a space between the switch and the argument. 27*0Sstevel@tonic-gate 28*0Sstevel@tonic-gateThe getopts() function is similar, but you should pass to it the list of all 29*0Sstevel@tonic-gateswitches to be recognized. If unspecified switches are found on the 30*0Sstevel@tonic-gatecommand-line, the user will be warned that an unknown option was given. 31*0Sstevel@tonic-gate 32*0Sstevel@tonic-gateNote that, if your code is running under the recommended C<use strict 33*0Sstevel@tonic-gate'vars'> pragma, you will need to declare these package variables 34*0Sstevel@tonic-gatewith "our": 35*0Sstevel@tonic-gate 36*0Sstevel@tonic-gate our($opt_x, $opt_y); 37*0Sstevel@tonic-gate 38*0Sstevel@tonic-gateFor those of you who don't like additional global variables being created, getopt() 39*0Sstevel@tonic-gateand getopts() will also accept a hash reference as an optional second argument. 40*0Sstevel@tonic-gateHash keys will be x (where x is the switch name) with key values the value of 41*0Sstevel@tonic-gatethe argument or 1 if no argument is specified. 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gateTo allow programs to process arguments that look like switches, but aren't, 44*0Sstevel@tonic-gateboth functions will stop processing switches when they see the argument 45*0Sstevel@tonic-gateC<-->. The C<--> will be removed from @ARGV. 46*0Sstevel@tonic-gate 47*0Sstevel@tonic-gate=head1 C<--help> and C<--version> 48*0Sstevel@tonic-gate 49*0Sstevel@tonic-gateIf C<-> is not a recognized switch letter, getopts() supports arguments 50*0Sstevel@tonic-gateC<--help> and C<--version>. If C<main::HELP_MESSAGE()> and/or 51*0Sstevel@tonic-gateC<main::VERSION_MESSAGE()> are defined, they are called; the arguments are 52*0Sstevel@tonic-gatethe output file handle, the name of option-processing package, its version, 53*0Sstevel@tonic-gateand the switches string. If the subroutines are not defined, an attempt is 54*0Sstevel@tonic-gatemade to generate intelligent messages; for best results, define $main::VERSION. 55*0Sstevel@tonic-gate 56*0Sstevel@tonic-gateIf embedded documentation (in pod format, see L<perlpod>) is detected 57*0Sstevel@tonic-gatein the script, C<--help> will also show how to access the documentation. 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gateNote that due to excessive paranoia, if $Getopt::Std::STANDARD_HELP_VERSION 60*0Sstevel@tonic-gateisn't true (the default is false), then the messages are printed on STDERR, 61*0Sstevel@tonic-gateand the processing continues after the messages are printed. This being 62*0Sstevel@tonic-gatethe opposite of the standard-conforming behaviour, it is strongly recommended 63*0Sstevel@tonic-gateto set $Getopt::Std::STANDARD_HELP_VERSION to true. 64*0Sstevel@tonic-gate 65*0Sstevel@tonic-gateOne can change the output file handle of the messages by setting 66*0Sstevel@tonic-gate$Getopt::Std::OUTPUT_HELP_VERSION. One can print the messages of C<--help> 67*0Sstevel@tonic-gate(without the C<Usage:> line) and C<--version> by calling functions help_mess() 68*0Sstevel@tonic-gateand version_mess() with the switches string as an argument. 69*0Sstevel@tonic-gate 70*0Sstevel@tonic-gate=cut 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate@ISA = qw(Exporter); 73*0Sstevel@tonic-gate@EXPORT = qw(getopt getopts); 74*0Sstevel@tonic-gate$VERSION = '1.05'; 75*0Sstevel@tonic-gate# uncomment the next line to disable 1.03-backward compatibility paranoia 76*0Sstevel@tonic-gate# $STANDARD_HELP_VERSION = 1; 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate# Process single-character switches with switch clustering. Pass one argument 79*0Sstevel@tonic-gate# which is a string containing all switches that take an argument. For each 80*0Sstevel@tonic-gate# switch found, sets $opt_x (where x is the switch name) to the value of the 81*0Sstevel@tonic-gate# argument, or 1 if no argument. Switches which take an argument don't care 82*0Sstevel@tonic-gate# whether there is a space between the switch and the argument. 83*0Sstevel@tonic-gate 84*0Sstevel@tonic-gate# Usage: 85*0Sstevel@tonic-gate# getopt('oDI'); # -o, -D & -I take arg. Sets opt_* as a side effect. 86*0Sstevel@tonic-gate 87*0Sstevel@tonic-gatesub getopt (;$$) { 88*0Sstevel@tonic-gate my ($argumentative, $hash) = @_; 89*0Sstevel@tonic-gate $argumentative = '' if !defined $argumentative; 90*0Sstevel@tonic-gate my ($first,$rest); 91*0Sstevel@tonic-gate local $_; 92*0Sstevel@tonic-gate local @EXPORT; 93*0Sstevel@tonic-gate 94*0Sstevel@tonic-gate while (@ARGV && ($_ = $ARGV[0]) =~ /^-(.)(.*)/) { 95*0Sstevel@tonic-gate ($first,$rest) = ($1,$2); 96*0Sstevel@tonic-gate if (/^--$/) { # early exit if -- 97*0Sstevel@tonic-gate shift @ARGV; 98*0Sstevel@tonic-gate last; 99*0Sstevel@tonic-gate } 100*0Sstevel@tonic-gate if (index($argumentative,$first) >= 0) { 101*0Sstevel@tonic-gate if ($rest ne '') { 102*0Sstevel@tonic-gate shift(@ARGV); 103*0Sstevel@tonic-gate } 104*0Sstevel@tonic-gate else { 105*0Sstevel@tonic-gate shift(@ARGV); 106*0Sstevel@tonic-gate $rest = shift(@ARGV); 107*0Sstevel@tonic-gate } 108*0Sstevel@tonic-gate if (ref $hash) { 109*0Sstevel@tonic-gate $$hash{$first} = $rest; 110*0Sstevel@tonic-gate } 111*0Sstevel@tonic-gate else { 112*0Sstevel@tonic-gate ${"opt_$first"} = $rest; 113*0Sstevel@tonic-gate push( @EXPORT, "\$opt_$first" ); 114*0Sstevel@tonic-gate } 115*0Sstevel@tonic-gate } 116*0Sstevel@tonic-gate else { 117*0Sstevel@tonic-gate if (ref $hash) { 118*0Sstevel@tonic-gate $$hash{$first} = 1; 119*0Sstevel@tonic-gate } 120*0Sstevel@tonic-gate else { 121*0Sstevel@tonic-gate ${"opt_$first"} = 1; 122*0Sstevel@tonic-gate push( @EXPORT, "\$opt_$first" ); 123*0Sstevel@tonic-gate } 124*0Sstevel@tonic-gate if ($rest ne '') { 125*0Sstevel@tonic-gate $ARGV[0] = "-$rest"; 126*0Sstevel@tonic-gate } 127*0Sstevel@tonic-gate else { 128*0Sstevel@tonic-gate shift(@ARGV); 129*0Sstevel@tonic-gate } 130*0Sstevel@tonic-gate } 131*0Sstevel@tonic-gate } 132*0Sstevel@tonic-gate unless (ref $hash) { 133*0Sstevel@tonic-gate local $Exporter::ExportLevel = 1; 134*0Sstevel@tonic-gate import Getopt::Std; 135*0Sstevel@tonic-gate } 136*0Sstevel@tonic-gate} 137*0Sstevel@tonic-gate 138*0Sstevel@tonic-gatesub output_h () { 139*0Sstevel@tonic-gate return $OUTPUT_HELP_VERSION if defined $OUTPUT_HELP_VERSION; 140*0Sstevel@tonic-gate return \*STDOUT if $STANDARD_HELP_VERSION; 141*0Sstevel@tonic-gate return \*STDERR; 142*0Sstevel@tonic-gate} 143*0Sstevel@tonic-gate 144*0Sstevel@tonic-gatesub try_exit () { 145*0Sstevel@tonic-gate exit 0 if $STANDARD_HELP_VERSION; 146*0Sstevel@tonic-gate my $p = __PACKAGE__; 147*0Sstevel@tonic-gate print {output_h()} <<EOM; 148*0Sstevel@tonic-gate [Now continuing due to backward compatibility and excessive paranoia. 149*0Sstevel@tonic-gate See ``perldoc $p'' about \$$p\::STANDARD_HELP_VERSION.] 150*0Sstevel@tonic-gateEOM 151*0Sstevel@tonic-gate} 152*0Sstevel@tonic-gate 153*0Sstevel@tonic-gatesub version_mess ($;$) { 154*0Sstevel@tonic-gate my $args = shift; 155*0Sstevel@tonic-gate my $h = output_h; 156*0Sstevel@tonic-gate if (@_ and defined &main::VERSION_MESSAGE) { 157*0Sstevel@tonic-gate main::VERSION_MESSAGE($h, __PACKAGE__, $VERSION, $args); 158*0Sstevel@tonic-gate } else { 159*0Sstevel@tonic-gate my $v = $main::VERSION; 160*0Sstevel@tonic-gate $v = '[unknown]' unless defined $v; 161*0Sstevel@tonic-gate my $myv = $VERSION; 162*0Sstevel@tonic-gate $myv .= ' [paranoid]' unless $STANDARD_HELP_VERSION; 163*0Sstevel@tonic-gate my $perlv = $]; 164*0Sstevel@tonic-gate $perlv = sprintf "%vd", $^V if $] >= 5.006; 165*0Sstevel@tonic-gate print $h <<EOH; 166*0Sstevel@tonic-gate$0 version $v calling Getopt::Std::getopts (version $myv), 167*0Sstevel@tonic-gaterunning under Perl version $perlv. 168*0Sstevel@tonic-gateEOH 169*0Sstevel@tonic-gate } 170*0Sstevel@tonic-gate} 171*0Sstevel@tonic-gate 172*0Sstevel@tonic-gatesub help_mess ($;$) { 173*0Sstevel@tonic-gate my $args = shift; 174*0Sstevel@tonic-gate my $h = output_h; 175*0Sstevel@tonic-gate if (@_ and defined &main::HELP_MESSAGE) { 176*0Sstevel@tonic-gate main::HELP_MESSAGE($h, __PACKAGE__, $VERSION, $args); 177*0Sstevel@tonic-gate } else { 178*0Sstevel@tonic-gate my (@witharg) = ($args =~ /(\S)\s*:/g); 179*0Sstevel@tonic-gate my (@rest) = ($args =~ /([^\s:])(?!\s*:)/g); 180*0Sstevel@tonic-gate my ($help, $arg) = ('', ''); 181*0Sstevel@tonic-gate if (@witharg) { 182*0Sstevel@tonic-gate $help .= "\n\tWith arguments: -" . join " -", @witharg; 183*0Sstevel@tonic-gate $arg = "\nSpace is not required between options and their arguments."; 184*0Sstevel@tonic-gate } 185*0Sstevel@tonic-gate if (@rest) { 186*0Sstevel@tonic-gate $help .= "\n\tBoolean (without arguments): -" . join " -", @rest; 187*0Sstevel@tonic-gate } 188*0Sstevel@tonic-gate my ($scr) = ($0 =~ m,([^/\\]+)$,); 189*0Sstevel@tonic-gate print $h <<EOH if @_; # Let the script override this 190*0Sstevel@tonic-gate 191*0Sstevel@tonic-gateUsage: $scr [-OPTIONS [-MORE_OPTIONS]] [--] [PROGRAM_ARG1 ...] 192*0Sstevel@tonic-gateEOH 193*0Sstevel@tonic-gate print $h <<EOH; 194*0Sstevel@tonic-gate 195*0Sstevel@tonic-gateThe following single-character options are accepted:$help 196*0Sstevel@tonic-gate 197*0Sstevel@tonic-gateOptions may be merged together. -- stops processing of options.$arg 198*0Sstevel@tonic-gateEOH 199*0Sstevel@tonic-gate my $has_pod; 200*0Sstevel@tonic-gate if ( defined $0 and $0 ne '-e' and -f $0 and -r $0 201*0Sstevel@tonic-gate and open my $script, '<', $0 ) { 202*0Sstevel@tonic-gate while (<$script>) { 203*0Sstevel@tonic-gate $has_pod = 1, last if /^=(pod|head1)/; 204*0Sstevel@tonic-gate } 205*0Sstevel@tonic-gate } 206*0Sstevel@tonic-gate print $h <<EOH if $has_pod; 207*0Sstevel@tonic-gate 208*0Sstevel@tonic-gateFor more details run 209*0Sstevel@tonic-gate perldoc -F $0 210*0Sstevel@tonic-gateEOH 211*0Sstevel@tonic-gate } 212*0Sstevel@tonic-gate} 213*0Sstevel@tonic-gate 214*0Sstevel@tonic-gate# Usage: 215*0Sstevel@tonic-gate# getopts('a:bc'); # -a takes arg. -b & -c not. Sets opt_* as a 216*0Sstevel@tonic-gate# # side effect. 217*0Sstevel@tonic-gate 218*0Sstevel@tonic-gatesub getopts ($;$) { 219*0Sstevel@tonic-gate my ($argumentative, $hash) = @_; 220*0Sstevel@tonic-gate my (@args,$first,$rest,$exit); 221*0Sstevel@tonic-gate my $errs = 0; 222*0Sstevel@tonic-gate local $_; 223*0Sstevel@tonic-gate local @EXPORT; 224*0Sstevel@tonic-gate 225*0Sstevel@tonic-gate @args = split( / */, $argumentative ); 226*0Sstevel@tonic-gate while(@ARGV && ($_ = $ARGV[0]) =~ /^-(.)(.*)/s) { 227*0Sstevel@tonic-gate ($first,$rest) = ($1,$2); 228*0Sstevel@tonic-gate if (/^--$/) { # early exit if -- 229*0Sstevel@tonic-gate shift @ARGV; 230*0Sstevel@tonic-gate last; 231*0Sstevel@tonic-gate } 232*0Sstevel@tonic-gate my $pos = index($argumentative,$first); 233*0Sstevel@tonic-gate if ($pos >= 0) { 234*0Sstevel@tonic-gate if (defined($args[$pos+1]) and ($args[$pos+1] eq ':')) { 235*0Sstevel@tonic-gate shift(@ARGV); 236*0Sstevel@tonic-gate if ($rest eq '') { 237*0Sstevel@tonic-gate ++$errs unless @ARGV; 238*0Sstevel@tonic-gate $rest = shift(@ARGV); 239*0Sstevel@tonic-gate } 240*0Sstevel@tonic-gate if (ref $hash) { 241*0Sstevel@tonic-gate $$hash{$first} = $rest; 242*0Sstevel@tonic-gate } 243*0Sstevel@tonic-gate else { 244*0Sstevel@tonic-gate ${"opt_$first"} = $rest; 245*0Sstevel@tonic-gate push( @EXPORT, "\$opt_$first" ); 246*0Sstevel@tonic-gate } 247*0Sstevel@tonic-gate } 248*0Sstevel@tonic-gate else { 249*0Sstevel@tonic-gate if (ref $hash) { 250*0Sstevel@tonic-gate $$hash{$first} = 1; 251*0Sstevel@tonic-gate } 252*0Sstevel@tonic-gate else { 253*0Sstevel@tonic-gate ${"opt_$first"} = 1; 254*0Sstevel@tonic-gate push( @EXPORT, "\$opt_$first" ); 255*0Sstevel@tonic-gate } 256*0Sstevel@tonic-gate if ($rest eq '') { 257*0Sstevel@tonic-gate shift(@ARGV); 258*0Sstevel@tonic-gate } 259*0Sstevel@tonic-gate else { 260*0Sstevel@tonic-gate $ARGV[0] = "-$rest"; 261*0Sstevel@tonic-gate } 262*0Sstevel@tonic-gate } 263*0Sstevel@tonic-gate } 264*0Sstevel@tonic-gate else { 265*0Sstevel@tonic-gate if ($first eq '-' and $rest eq 'help') { 266*0Sstevel@tonic-gate version_mess($argumentative, 'main'); 267*0Sstevel@tonic-gate help_mess($argumentative, 'main'); 268*0Sstevel@tonic-gate try_exit(); 269*0Sstevel@tonic-gate shift(@ARGV); 270*0Sstevel@tonic-gate next; 271*0Sstevel@tonic-gate } elsif ($first eq '-' and $rest eq 'version') { 272*0Sstevel@tonic-gate version_mess($argumentative, 'main'); 273*0Sstevel@tonic-gate try_exit(); 274*0Sstevel@tonic-gate shift(@ARGV); 275*0Sstevel@tonic-gate next; 276*0Sstevel@tonic-gate } 277*0Sstevel@tonic-gate warn "Unknown option: $first\n"; 278*0Sstevel@tonic-gate ++$errs; 279*0Sstevel@tonic-gate if ($rest ne '') { 280*0Sstevel@tonic-gate $ARGV[0] = "-$rest"; 281*0Sstevel@tonic-gate } 282*0Sstevel@tonic-gate else { 283*0Sstevel@tonic-gate shift(@ARGV); 284*0Sstevel@tonic-gate } 285*0Sstevel@tonic-gate } 286*0Sstevel@tonic-gate } 287*0Sstevel@tonic-gate unless (ref $hash) { 288*0Sstevel@tonic-gate local $Exporter::ExportLevel = 1; 289*0Sstevel@tonic-gate import Getopt::Std; 290*0Sstevel@tonic-gate } 291*0Sstevel@tonic-gate $errs == 0; 292*0Sstevel@tonic-gate} 293*0Sstevel@tonic-gate 294*0Sstevel@tonic-gate1; 295