home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-01-28 | 27.2 KB | 1,046 lines |
- Newsgroups: comp.lang.perl
- Path: sparky!uunet!charon.amdahl.com!pacbell.com!ames!saimiri.primate.wisc.edu!zaphod.mps.ohio-state.edu!caen!uvaarpa!mmdf
- From: Alan Stebbens <aks%anywhere@hub.ucsb.edu>
- Subject: ParseArgs options parser w/bells & whistles
- Message-ID: <1993Jan26.194814.919@uvaarpa.Virginia.EDU>
- Sender: mmdf@uvaarpa.Virginia.EDU (Mail System)
- Reply-To: Alan Stebbens <aks@hub.ucsb.edu>
- Organization: The Internet
- Date: Tue, 26 Jan 1993 19:48:14 GMT
- Lines: 1034
-
- The code in the archive below is yet another options parser, but this
- one takes care of any requirement I have ever used in any program, C,
- Perl, or whatever.
-
- I've been using it for a while, but hadn't taken the time to
- write the man page. Well, using "wrapman", it now has an embedded man
- page, and a Makefile to install it in your favorite place.
-
- Below, is the first page of the man page, so you can see if you care to
- even unpack the "sh" archive which follows it.
-
- Feel free to submit bug fixes, or suggest improvements.
-
- Enjoy.
-
- -- Alan Stebbens, UCSB, Santa Barbara <aks@hub.ucsb.edu>
- "If all you have is a hammer, then everything looks like a nail."
-
- ============================= cut here ===================================
-
- PARSEARGS(3) (January 14, 1993) PARSEARGS(3)
-
- NAME
- parseargs.pl - Parse the argument vector
-
- SYNOPSIS
- require 'parseargs.pl'
-
- &ParseOpts('FLAG1 FLAG2 ... FLAGn');
-
- &ParseArgs('FLAG1', 'ACTION1', 'FLAG2', 'ACTION2', ...);
-
- &ParseArgs(<<'EOF');
- FLAG1 ACTION1
- FLAG2 ACTION2
- ...
- FLAGn ACTIONn
- EOF
-
- DESCRIPTION
- These subroutines parse the current command argument vector,
- @ARGV, for switches which match defined FLAG expressions,
- evaluating associated ACTION expressions.
-
- The argument parsing stops on the first unhandled non-flag
- argument. An error is reported on any unhandled flag
- arguments (-flag).
-
- There are two subroutines: ParseArgs, and ParseOpts. The
- former is more general and allows complete control over the
- flag strings and the associated actions. The ParseOpts
- routine has a simpler interface, with useful default actions
- for the specified flag strings.
-
- In both routines, each FLAG is matched against the current
- argument, and, if successful, the corresponding ACTION is
- evaluated, followed by a next. FLAG can be a general Perl
- expression, or it can be one of a special syntax (defined
- below), which is used to create a Perl expression for
- testing.
-
- Any argument not matching any of the test expressions causes
- an error. When an error occurs, if the string $Usage is
- defined, it will be printed after the error message.
-
- ACTION can be a general Perl expression, except that no
- embedded newlines are permitted. An empty string, or action
- of `#' is considered to be a null action, for which useful
- defaults are supplied.
-
- Within ACTION, the string `ARG' will be substituted with the
- appropriate Perl expression which evaluates to the argument
- of the switch which selected the action.
-
- Page 1 (printed 1/26/93)
-
- ============================= cut here ===================================
-
- parseargs.shar
- ============================= cut here ===================================
- #!/bin/sh
- # This is a shell archive (produced by shar 3.49)
- # To extract the files from this archive, save it to a file, remove
- # everything above the "!/bin/sh" line above, and type "sh file_name".
- #
- # made 01/26/1993 19:43 UTC by aks@anywhere
- # Source directory /fs.real/anywhere/home/aks/src/Lang/perl/Lib/parseargs
- #
- # existing files will NOT be overwritten unless -c is specified
- #
- #
- #
- #
- # This shar contains:
- # length mode name
- # ------ ---------- ------------------------------------------
- # 19844 -r--r--r-- parseargs.pl
- # 534 -r--r--r-- Makefile
- # 723 -rwxr-xr-x test.pl
- # 113 -rwxr-xr-x test1
- #
- if test -r _shar_seq_.tmp; then
- echo 'Must unpack archives in sequence!'
- echo Please unpack part `cat _shar_seq_.tmp` next
- exit 1
- fi
- # ============= parseargs.pl ==============
- if test -f 'parseargs.pl' -a X"$1" != X"-c"; then
- echo 'x - skipping parseargs.pl (File already exists)'
- rm -f _shar_wnt_.tmp
- else
- | _shar_wnt_.tmp
- echo 'x - extracting parseargs.pl (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'parseargs.pl' &&
- # ParseArgs.pl script for perl
- 'di';
- 'ig00';
- #
- # Author: Alan K. Stebbens <aks@hub.ucsb.edu>
- # $Id: parseargs.pl,v 1.5 1993/01/26 19:43:43 aks Exp $
- # See bottom of file for documentation.
- X
- $InitParseProgram = '
- X Arg:while (@ARGV && ($_ = shift @ARGV)) {
- X $arg = s/=(.*)// ? $1 : undef;
- X while (/^-./) { # parse clustered switches
- X ';
- X
- $FinishParseProgram = '
- X last;
- X }
- X if (!index(\'-debug\',$_)) {
- X $Debug = $arg || 1; next;
- X }
- X if (!index(\'-verbose\',$_)) {
- X $Verbose = $arg || 1; next;
- X }
- X next if /^-$/;
- X last unless /^-/;
- X die "Bad arg: $_\n", $Usage;
- X }
- X unshift(@ARGV, $_) if length;
- X ';
- X
- sub ParseOpts {
- X local($i);
- X local(@opts) = split(' ',shift);
- X for ($i = $#opts + 1; $i > $[; $i--) {
- X splice(@opts, $i, 0, ''); # insert null actions
- X }
- X &ParseArgs(@opts);
- }
- X
- %ParseArgFlags = ( '<', 'ParseArgInFile',
- X '>', 'ParseArgOutFile',
- X '/', 'ParseArgDirectory',
- X '.', 'ParseArgPlainFile',
- X '!', 'ParseArgNewFile',
- X '@', 'ParseArgsFromFile',
- X '#', 'ParseNumberArgs',
- X '~', 'ParseUserLogin',
- X '(', 'ParseGroupName',
- X '=', '',
- X ':', '',
- X '+', '',
- X '*', '',
- X );
- X
- $ParseArgFlags = join('',keys(%ParseArgFlags));
- X
- sub ParseArgs {
- X local(@arglist) = @_; # argument list
- X local($_);
- X local($NoArg) = "Missing argument for option: ";
- X if ($#arglist == $[) { # a single string?
- X local(@lines) = split(/\n/,$arglist[0]);
- X @arglist = ();
- X foreach (@lines) { # parse strings into FLAG, ACTION pairs
- X if (/^\s*(\S+)\s+(\S.*)$/) {
- X push(@arglist,$1,$2);
- X } elsif (/^\s*(\S+)/) {
- X push(@arglist,$1,''); # default ACTION
- X }
- X }
- X }
- X local($parser,$x,$option,$flag,$action,$expr,$arg,$interp);
- X $parser = $InitParseProgram;
- X for ($x = 0; $x <= $#arglist; $x += 2) {
- X $option = $arglist[$x];
- X $action = $arglist[$x+1];
- X length($option) || next; # ignore null options
- X $action =~ s/\s*\#\s*$//; # remove any comments
- X $action =~ s/\bARG\b/\$arg/; # substitute
- X # check for --word, -word, +word, or _word w or w/o =
- X if ($option =~ /^(--|-|\+|_)(\w+)(\W|)/) {
- X die "$0: Unknown option flag: $flag\n"
- X if !defined($ParseArgFlags{$flag = $3});
- X $expr = "\t if (!index('$1$2',\$_)) {\n";
- X $interp = $ParseArgFlags{$flag};
- X if ($flag) {
- X $arg = "\$arg = defined(\$arg) ? \$arg : shift \@ARGV";
- X $arg .= " || die \"$NoArg $2\\n\", \$Usage" if $flag eq '=';
- X $expr .= "\t\t".$arg.";\n";
- X $expr .= "\t\t\$arg = \&".$interp."(\$2,\$arg);\n" if $interp;
- X $action = "\$opt_$2 = \$arg" unless $action;
- X $expr .= "\t\t".$action.";\n";
- X } else { # no flag char: -xyz
- X $arg = $1 eq '--' ? 1 : $1 eq '-' ? 2 : $1 eq '+' ? 4 : 8;
- X $action = "\$opt_$2 = $arg" unless $action;
- X $expr .= "\t\t".$action.";\n";
- X }
- X $expr .= "\t\tnext Arg;\n";
- X } elsif ($option =~ /^(\w)(\W)?/) { # how about single character option?
- X $interp = ($flag = $2) && $ParseArgFlags{$flag};
- X die "$0: Unknown option flag: $flag on option $option\n"
- X if index($ParseArgFlags,$flag = $2) < $[;
- X $expr = "\t if (s/^-$1/-/) {\n";
- X $interp = $ParseArgFlags{$flag};
- X if ($flag) { # assignment option?
- X $arg = "\$arg = ";
- X if ($flag eq '+' || $flag eq '*') { # sticky args?
- X $expr = "\t if (s/^-$1(.*)//) {\n";
- X $arg .= "length(\$1) ? \$1 : ";
- X }
- X $arg .= "defined(\$arg) ? \$arg : shift \@ARGV";
- X $arg .= " || die \"$NoArg $1\\n\", \$Usage"
- X if $flag eq '=' || $flag eq '+';
- X $expr .= "\t\t".$arg.";\n";
- X $expr .= "\t\t\$arg = \&".$interp."(\$2,\$arg);" if $interp;
- X $action = "\$opt_$1 = \$arg" unless $action;
- X $expr .= "\t\t".$action.";\n" if $action;
- X $expr .= "\t\tundef \$arg;\n";
- X } else {
- X $expr .= "\t\t\$opt_$1++;\n" unless $action;
- X $expr .= "\t\t".$action.";\n" if $action;
- X }
- X $expr .= "\t\tnext;\n";
- X } else { # use option as expr
- X $expr = "\t if ($option) {\n";
- X $expr .= "\t\t".$action.";\n" if $action;
- X $expr .= "\t\tnext Arg;\n" unless $action !~ /\bnext\b/;
- X }
- X $parser .= $expr;
- X $parser .= "\t }\n";
- X }
- X $parser .= $FinishParseProgram;
- X print STDERR $parser
- X if @ARGV && $ARGV[0] eq '-DEBUG_PARSER' && shift @ARGV;
- X eval $parser;
- X die $@ if $@;
- }
- X
- # Reference this routine in an action if you want an option to
- # insert arguments acquired by reading a file.
- X
- sub ParseArgsFromFile {
- X local($file) = shift;
- X open(FEXP,$file) || die "Can't open input: $file: $!\n";
- X unshift(@ARGV, grep((chop, s/\s*\#.*$//, length > 0),<FEXP>));
- X close FEXP;
- }
- X
- sub ParseArgInFile {
- X local($opt,$_) = @_;
- X die "$0: File $_ cannot be read!\n" unless -r;
- X open("FH_$opt","<$_") || die "$O: Cannot open $_ for input: $!\n";
- X $_;
- }
- X
- sub ParseArgOutFile {
- X local($opt,$_) = @_;
- X -e && ( -w || die "$0: File $_ cannot be written!\n" );
- X open("FH_$opt",">$_") || die "$0: Cannot open $_ for output: $!\n";
- X $_;
- }
- X
- sub ParseArgDirectory {
- X local($opt,$_) = @_;
- X -e || die "$0: Directory $_ does not exist!\n";
- X -d || die "$0: $_ is not a directory!\n";
- X $_;
- }
- X
- sub ParseArgPlainFile {
- X local($opt,$_) = @_;
- X -e || die "$0: File $_ does not exist!\n";
- X -f || die "$0: File $_ is not a plain file!\n";
- X $_;
- }
- X
- sub ParseArgNewFile {
- X local($opt,$_) = @_;
- X ! -e || die "$0: File $_ already exists!\n";
- X $_;
- }
- X
- sub ParseNumberArgs {
- X local($opt,$_) = @_;
- X /^\d+$/ || die "$0: Option $opt $_ is not a number!\n";
- X $_;
- }
- X
- sub ParseUserLogin {
- X local($opt,$_) = @_;
- X /^\d+$/ ?
- X $_ == (getpwuid($_))[$[+2] || die "$0: $_ is not a valid user id!\n"
- X : $_ eq (getpwnam($_))[$[] || die "$0: $_ is not a valid login name!\n";
- X $_;
- }
- X
- sub ParseGroupName {
- X local($opt,$_) = @_;
- X /^\d+$/ ?
- X $_ == (getgrgid($_))[$[+2] || die "$0: $_ is not a valid group id!\n"
- X : $_ eq (getgrnam($_))[$[] || die "$0: $_ is not a valid group name!\n";
- X $_;
- }
- X
- 1;
- __END__
- ###############################################################
- X # These next few lines are legal in both Perl and nroff.
- X
- .00; # finish .ig
- X
- 'di \" finish diversion--previous line must be blank
- .nr nl 0-1 \" fake up transition to first page again
- .nr % 0 \" start at page 1
- .rm ';
- .\" Bullet Item
- .de Bi
- .TP 1i
- .B \\h'.5i'\\$1
- ..
- .TH PARSEARGS 3 "January 14, 1993"
- .AT 3
- .SH NAME
- parseargs.pl - Parse the argument vector
- .SH SYNOPSIS
- .B require 'parseargs.pl'
- .sp
- .B &ParseOpts('FLAG1 FLAG2 ... FLAGn');
- .sp
- .B &ParseArgs('FLAG1', 'ACTION1', 'FLAG2', 'ACTION2', ...);
- .sp
- .nf
- .na
- .ft B
- &ParseArgs(<<'EOF');
- X FLAG1 ACTION1
- X FLAG2 ACTION2
- X ...
- X FLAGn ACTIONn
- EOF
- .ft R
- .ad
- .fi
- .SH DESCRIPTION
- These subroutines parse the current command argument vector,
- .BR @ARGV ,
- for switches which match defined
- .B FLAG
- expressions, evaluating associated
- .B ACTION
- expressions.
- .sp
- The argument parsing stops on the first unhandled non-flag argument.
- An error is reported on any unhandled flag arguments (\c
- .BI -flag ).
- .sp
- There are two subroutines:
- .BR ParseArgs ,
- and
- .BR ParseOpts .
- The former is
- more general and allows complete control over the flag strings and the
- associated actions. The
- .B ParseOpts
- routine has a simpler interface,
- with useful default actions for the specified flag strings.
- .sp
- In both routines, each
- .B FLAG
- is matched against the current argument,
- and, if successful, the corresponding
- .B ACTION
- is evaluated, followed by
- a
- .BR next .
- .B FLAG
- can be a general Perl expression, or it can be one of
- a special syntax (defined below), which is used to create a Perl
- expression for testing.
- .sp
- Any argument not matching any of the test expressions causes an error.
- When an error occurs, if the string
- .B $Usage
- is defined, it will be
- printed after the error message.
- .sp
- .B ACTION
- can be a general Perl expression, except that no embedded
- newlines are permitted. An empty string, or action of
- .B `#'
- is considered to be a null action, for which useful defaults are
- supplied.
- .sp
- Within
- .BR ACTION ,
- the string
- .I `ARG'
- will be substituted with the
- appropriate Perl expression which evaluates to the argument of the switch
- which selected the action.
- .sp
- In the case of
- .BR ParseOpts ,
- all actions are provided by default.
- .sp
- As a convenience for Perl script writers (that is, myself :^), the
- following flags and actions are supplied, after all other flags have
- been tested:
- .sp
- .nf
- .B \t-debug\t$DEBUG++
- .B \t-verbose\t$VERBOSE++
- .fi
- .sp
- Also, for the case of when arguments may be obtained by reading a file
- passed as an argument itself, the user may reference the subroutine
- .B &ParseArgsFromFile(\c
- .IB ARG )
- as an action, where
- .I ARG
- is the special
- string recognized and substituted with an appropriate expression.
- .sp
- The syntax of
- .B FLAG
- is:
- .TP .5i
- (a) \fB(--|-|+|_)\fIWORD\fB[\fIF\fB]\fR
- .sp
- This syntax allows the various methods of setting switches to be
- recognized, with an optional trailing flag character
- .IR `F' ,
- indicating how to handle the
- argument, if any.
- If there is no graphic character suffixed to the
- .IR WORD ,
- then the option accepts no arguments, and is set to 1 when supplied on
- the command line.
- .sp
- The following graphic flag characters are recognized and provide for
- interpretation of the arguments, when given. When an explicit user
- action is given in conjunction with one of these flag characters, the
- interpretation action is accomplished before the user action. When no
- user action is given, the default variable,
- .BI `$opt_ WORD' ,
- is assigned the value of the argument.
- .Bi `='
- this flag accepts a required argument, either in the same word following an
- equal sign (\c
- .BR `=' ),
- or in the next word of the argument vector. That is, both of these
- argument types are valid:
- .sp
- .B \t-WORD=VALUE\t
- and
- .B \t-WORD VALUE
- .sp
- An omitted argument is an error with the \fB`='\fP flag character.
- .Bi `:'
- this flag character causes the option to take an
- optional argument, not causing an error should it be omitted.
- .Bi `<'
- treat the argument as an input file,
- causing an error if the file is non-existent or unreadable. The file is
- opened for reading under the file handle
- .BI FH_ WORD.
- .Bi `>'
- treat the argument as an output file,
- causing an error if the file is not writable. The file is opened for
- writing under the file handle
- .BI FH_ WORD.
- .Bi `/'
- treat the argument as a directory, which must exist.
- .Bi "`.'" "(a period)"
- treat the argument as a plain file which must exist; if the file is a
- directory, or a special file, then an error occurs. Symbolic links are
- ok, if they point to a plain file.
- .Bi `!'
- treat the argument as a new, nonexistent file name. An error occurs if
- the file already exists, in any form.
- .Bi `#'
- treat the argument as an integer, causing an error for any non-digits
- found.
- .Bi `~'
- verify the argument as a valid user login name or numerical user id.
- .Bi `('
- treat the argument as a valid group name, or numerical group id.
- .Bi `@'
- treat the argument as a readable file, read the files contents, and
- split the lines into the argument vector,
- .BR @ARGV .
- .IP "" .5i
- The switches recognized by
- .I (a)
- may all be minimally abbreviated, as
- the test expression used to recognize the switch is
- .B `!index(FLAG,$_)'.
- Thus, for the flag
- .BR `-edit' ,
- the options
- .BR `-edit' ,
- .BR `-edi' ,
- .BR `-ed',
- and
- .B `-e'
- will be recognized.
- .sp
- When designing switch names with abbreviation, care must be taken to
- specify the longer abbreviations first, so they will not be masked
- by shorter ones.
- .sp
- The default
- .B ACTION
- performed by a switch matching this style
- .BR FLAG ,
- is to set a Perl variable,
- .BI $opt_ WORD,
- to a `1', if no value was given, or to the argument supplied.
- .sp
- X The following are all examples of this syntax:
- .sp
- .B --list-all -edit +help -verbose _broadcast= _netmask=
- .B -input< -output> -dir/ --user~ -file@ -count#
- .sp
- .TP .5i
- (b) \fIC\fB[=:<>/.!#~(+*]\fR
- .sp
- In this syntax,
- .B C
- is a single character switch, which may be followed by one of the
- previously documented flag characters, or one of the following two
- additional ones:
- .Bi `+'
- This flag character causes the option to require an argument, which may
- be given either juxtaposed with the option word itself, or on the
- subsequent argument vector word.
- .Bi `*'
- This flag character causes the option to attempt to obtain an argument,
- and failing that, cause no error.
- .IP "" .5i
- Single character switches may be given separately, or may be clustered into
- a single switch word. For example, the options
- .B -l
- and
- .BR -t ,
- may be given as:
- .B -lt
- or
- .BR -tl .
- .sp
- The single character assignable options may require arguments, or
- they may be optional. The argument syntax may be one of:
- .sp
- .nf
- .B \t\fR(1)\fB `-O=arg'
- .B \t\fR(2)\fB `-Oarg'
- .B \t\fR(3)\fB `-O arg'
- .fi
- .sp
- where
- .B `-O'
- is your favorite option. The argument flags
- .B `='
- and
- .B `:'
- indicate required or optional arguments which can only be assigned
- via styles
- .I (1)
- and
- .IR (3) .
- The argument flags
- .B `+'
- and
- .B `*'
- also mean required and optional, but indicate that style
- .I (2)
- is permissible, which disallows option clustering.
- .sp
- The following table should make this a little clearer:
- .sp
- .ta .5i +.5i +1i +1i +1i
- .nf
- .ft B
- X Flag Argument? -O=arg -Oarg -O arg
- .ft R
- X ---- --------- ------ ----- ------
- X \fB=\fP required ok no ok
- X \fB:\fP optional ok no ok
- X \fB+\fP required ok ok ok
- X \fB*\fP optional ok ok ok
- .fi
- .ta 0.5i
- .sp
- If a switch defined with an argument is given in a cluster, its
- argument may come from:
- .sp
- .IP \\h'.5i'1. 1i
- the immediately following characters, if the
- .I FLAG
- is defined as
- .B `C+'
- or
- .BR `C*' .
- This behavior is similar to how
- .I lpr
- parses its printer switch:
- .BR `-Pprinter' .
- In this case, the flag would be given as
- .BR `P+' .
- If the flag is defined as
- .BR `P=' ,
- then either an equal sign must be used, or the subsequent word will be
- used as the argument.
- .sp
- .IP \\h'.5i'2. 1i
- the string followed by the equal sign (\fB`='\fP)
- in the same word as the switch. This allows single character switches
- to be given similar to longer switches:
- .B `-l=999'
- or
- .BR `-length=999' .
- .IP \\h'.5i'3. 1i
- the subsequent word in the argument vector, if there are no
- strings resulting from cases
- .I (1)
- or
- .I (2)
- above.
- .sp
- The default action for this style flag is to increment a Perl
- variable,
- .BI $opt_ C,
- where
- .B `C'
- is the single character switch name, or to set its value to the argument
- if defined to accept arguments.
- For example, if the flags
- .B `l'
- and
- .B `t'
- were defined, then the switch
- .B `-lt'
- would cause the variables
- .B $opt_l
- and
- .B $opt_t
- to both be incremented.
- .TP .5i
- (c) \fBexpr\fR
- This syntax is the usual Perl expression. It is tested
- directly, and no default action is assumed; actions must be
- specified by the user.
- .PP
- Since the order of the flags is the order in which the tests will be
- performed, if the user mixes flag styles, and there are overlaps between
- single character options and word options, the word options should
- be specified first, otherwise the single character parsing will cause
- the word argument to get broken into characters.
- .PP
- In order to facilitate debugging the options specifications and the
- resulting parser, if the first argument is
- .BR `-DEBUG_PARSER' ,
- then the parser code will be printed to
- .B STDERR
- before being eval'ed.
- .SH EXAMPLES
- .sp
- .nf
- .ft B
- &ParseArgs(<<'EOF') \fR# NOTE: single quotes!\fB
- X t $tbl++
- X l $lst++
- EOF
- .ft R
- .fi
- .IP
- This example recognizes the
- .B `-t'
- and
- .B `-l'
- switches, which may be
- given separately or combined as
- .B `-lt'
- or
- .BR `-tl' ,
- and sets the associated variables accordingly. In this case, the
- default variable assignments (\c
- .B $opt_t
- and
- .BR $opt_l )
- are NOT done.
- .PP
- .nf
- .ft B
- &ParseArgs('t', '$tbl++', 'l', '$lst++');
- .ft R
- .fi
- .IP
- This is equivalent to the previous example.
- .PP
- .ft B
- &ParseOpts('t l');
- .ft R
- .IP
- This is essentially equivalent to the first two examples, except
- that the variables set for
- .B `-t'
- and
- .B `-l'
- are
- .B $opt_t
- and
- .BR $opt_l ,
- respectively.
- .PP
- .nf
- .ft B
- &ParseOpts('-file= -list: -edit -optimize');
- .ft R
- .fi
- .IP
- In this example, the variables set would be:
- .BR $opt_file ,
- .BR $opt_list ,
- .BR $opt_edit ,
- and
- .BR $opt_optimize .
- The
- .B `-list'
- option has an optional argument, while
- .B `-file'
- must be supplied with an argument or an error will result.
- .PP
- .nf
- .ft B
- &ParseArgs(<<'EOF");
- X -file= &ParseArgsFromFile(ARG);
- X b $Brief++
- X v $Verbose++
- X l* $Len = ARG || 80
- X -edit
- X -arch= $Arch = ARG
- X -os= $OS = ARG
- EOF
- .fi
- .ft R
- .IP
- This example illustrates the combination of the various types,
- including a default action.
- .sp
- The
- .B `-file'
- switch, which may be abbreviated as
- .B `-f'
- causes the routine,
- .I &ParseArgsFromFile
- to be invoked with computed argument
- .B (ARG)
- of the
- .B `-file'
- switch. The arguments read from the file argument are then placed on
- the argument stack as if they had been typed by the user. These new
- arguments are parsed along with any remaining, original arguments.
- .sp
- The
- .B $Brief
- and
- .B $Verbose
- variables will be set if their respective, clusterable option flags are
- given.
- .sp
- The
- .B `-l'
- option may be optionally given an argument, either as
- .B `-lXYZ' or
- .BR `-l\ XYZ' ;
- it is assigned to
- .BR $Len .
- .sp
- The variable
- .B $opt_edit
- will be set (to 1).
- .sp
- The
- .B $Arch
- variable will be set to the argument supplied to the
- .B `-arch'
- switch; similarly, the
- .B $OS
- variable will be set by the
- .B `-os'
- switch, both of which may be abbreviated.
- .sp
- .PP
- .ft B
- &ParseOpts('-in< -out> -directory/ -file. -user~ -group( -num# -new!');
- .ft R
- .PP
- This is a rather baroque example illustrating the features of useful
- default actions. The following variables will be set as follows.
- .TP 1i
- .B $opt_in
- is set to the name of a file which is opened for input, using the
- filehandle of
- .BR `FH_in' .
- The variable and filehandle names are always
- .BI `$opt_ OPTION'
- and
- .BI `FH_ OPTION'.
- If the file could not be opened for input, an error would have occurred.
- .TP
- .B $opt_out
- is set to the name of a file opened for writing, using the filehandle of
- .BR `FH_out' .
- .TP
- .B $opt_directory
- is set to the name of an existing directory; an error will occur if the
- directory doesn't exist.
- .TP
- .B $opt_file
- is set to the name of an existing file; no other tests are made, just
- existence. If the file given as an argument doesn't exist, an error
- occurs.
- .TP
- .B $opt_user
- is set to the name of a valid user login name or numeric user id.
- .TP
- .B $opt_group
- is set to the name of a valid group name or numeric group id.
- .TP
- .B $opt_num
- is set to a number given as the argument; anything other than a number
- causes an error.
- .IP
- .B $opt_new
- is set to the name of a non-existent file; an error occurs if the file
- already exists.
- .sp
- .SH ENVIRONMENT
- .B
- .IP @ARGV
- The argument vector is implicitly parsed.
- .SH FILES
- None.
- .SH AUTHOR
- Alan Stebbens <aks@hub.ucsb.edu>
- .SH "SEE ALSO"
- .IR getopts.pl (3),
- .IR perl (1)
- .SH DIAGNOSTICS
- .PP
- When an error occurs, one of the following error messages is generated,
- followed by the value of
- .I $Usage
- if it is defined.
- .sp
- Unknown option flag: $flag
- .sp
- Can't open input: $file: $!
- .sp
- Unknown option flag: $flag on option $option
- .sp
- File $_ cannot be read!
- .sp
- File $_ cannot be written
- .sp
- Cannot open $_ for output: $!
- .sp
- Directory $_ does not exist!
- .sp
- $_ is not a directory!
- .sp
- File $_ does not exist!
- .sp
- File $_ is not a plain file!
- .sp
- File $_ already exists!
- .sp
- Option $opt: $_ is not a number!
- .sp
- $_ is not a valid user id!
- .sp
- $_ is not a valid login name!
- .sp
- $_ is not a valid group id!
- .sp
- $_ is not a valid group name!
- .sp
- Missing argument for option: $option
- .sp
- Bad option: $option
- .SH BUGS
- Probably.
- .\" Emacs Local Variables:
- .\" Emacs mode: perl
- .\" Emacs End:
- SHAR_EOF
- chmod 0444 parseargs.pl ||
- echo 'restore of parseargs.pl failed'
- Wc_c="`wc -c < 'parseargs.pl'`"
- test 19844 -eq "$Wc_c" ||
- echo 'parseargs.pl: original size 19844, current size' "$Wc_c"
- rm -f _shar_wnt_.tmp
- fi
- # ============= Makefile ==============
- if test -f 'Makefile' -a X"$1" != X"-c"; then
- echo 'x - skipping Makefile (File already exists)'
- rm -f _shar_wnt_.tmp
- else
- | _shar_wnt_.tmp
- echo 'x - extracting Makefile (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'Makefile' &&
- # Makefile to install parseargs
- X
- X ROOT = /eci/share
- X PERLLIB = $(ROOT)/lib/perl
- X MANDIR = $(ROOT)/man/man3
- X
- X INSTALL = /usr/ucb/install
- X
- I = ( set -x ; $(INSTALL) -c -m 444 $? $@ )
- L = ( set -x ; ln -s $? $@ )
- R = if [ -f $@ ]; then rm -f $@ ; fi
- X
- default:
- X @( set -x ; $(MAKE) -n install )
- X
- install: $(PERLLIB)/parseargs.pl $(MANDIR)/parseargs.3
- X
- $(PERLLIB)/parseargs.pl: parseargs.pl ; @$R ; $I
- $(MANDIR)/parseargs.3: $(PERLLIB)/parseargs.pl ; @$R ; $L
- X
- shar:
- X shar -L50 -o parseargs.shar parseargs.pl Makefile test.pl test1
- SHAR_EOF
- chmod 0444 Makefile ||
- echo 'restore of Makefile failed'
- Wc_c="`wc -c < 'Makefile'`"
- test 534 -eq "$Wc_c" ||
- echo 'Makefile: original size 534, current size' "$Wc_c"
- rm -f _shar_wnt_.tmp
- fi
- # ============= test.pl ==============
- if test -f 'test.pl' -a X"$1" != X"-c"; then
- echo 'x - skipping test.pl (File already exists)'
- rm -f _shar_wnt_.tmp
- else
- | _shar_wnt_.tmp
- echo 'x - extracting test.pl (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'test.pl' &&
- #!/bin/perl
- X
- require 'parseargs.pl';
- X
- $Usage = <<EOF;
- usage: $0 -input INPUT -output OUTPUT -new NEW -exists OLD
- X -login LOGIN -group GROUP -number NUM
- EOF
- X
- &ParseArgs(<<'EOF');
- X -input<
- X -dir/
- X -output>
- X -new!
- X -exists.
- X -login~
- X -group(
- X -number#
- EOF
- X
- format STDOUT =
- X input = @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
- X $opt_input
- X dir = @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
- X $opt_dir
- output = @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
- X $opt_output
- X new = @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
- X $opt_new
- exists = @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
- X $opt_exists
- X login = @<<<<<<<<<<<<<<
- X $opt_login
- X group = @<<<<<<<<<<<<<<<
- X $opt_group
- number = @<<<<<<<<<<<<<<
- X $opt_number
- .
- X
- write;
- X
- exit;
- SHAR_EOF
- chmod 0755 test.pl ||
- echo 'restore of test.pl failed'
- Wc_c="`wc -c < 'test.pl'`"
- test 723 -eq "$Wc_c" ||
- echo 'test.pl: original size 723, current size' "$Wc_c"
- rm -f _shar_wnt_.tmp
- fi
- # ============= test1 ==============
- if test -f 'test1' -a X"$1" != X"-c"; then
- echo 'x - skipping test1 (File already exists)'
- rm -f _shar_wnt_.tmp
- else
- | _shar_wnt_.tmp
- echo 'x - extracting test1 (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'test1' &&
- #!/bin/sh
- set -x
- ./test.pl -input=test.pl -dir . -output=xyz -new=qrz -exists=test1 -login bin -group bin -num 1
- SHAR_EOF
- chmod 0755 test1 ||
- echo 'restore of test1 failed'
- Wc_c="`wc -c < 'test1'`"
- test 113 -eq "$Wc_c" ||
- echo 'test1: original size 113, current size' "$Wc_c"
- rm -f _shar_wnt_.tmp
- fi
- exit 0
-