xref: /onnv-gate/usr/src/cmd/perl/5.8.4/distrib/lib/Getopt/Std.pm (revision 0:68f95e015346)
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