home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1993 #3 / NN_1993_3.iso / spool / comp / lang / perl / 8009 < prev    next >
Encoding:
Text File  |  1993-01-28  |  27.2 KB  |  1,046 lines

  1. Newsgroups: comp.lang.perl
  2. Path: sparky!uunet!charon.amdahl.com!pacbell.com!ames!saimiri.primate.wisc.edu!zaphod.mps.ohio-state.edu!caen!uvaarpa!mmdf
  3. From: Alan Stebbens <aks%anywhere@hub.ucsb.edu>
  4. Subject: ParseArgs options parser w/bells & whistles
  5. Message-ID: <1993Jan26.194814.919@uvaarpa.Virginia.EDU>
  6. Sender: mmdf@uvaarpa.Virginia.EDU (Mail System)
  7. Reply-To: Alan Stebbens <aks@hub.ucsb.edu>
  8. Organization: The Internet
  9. Date: Tue, 26 Jan 1993 19:48:14 GMT
  10. Lines: 1034
  11.  
  12. The code in the archive below is yet another options parser, but this
  13. one takes care of any requirement I have ever used in any program, C,
  14. Perl, or whatever.
  15.  
  16. I've been using it for a while, but hadn't taken the time to
  17. write the man page.  Well, using "wrapman", it now has an embedded man
  18. page, and a Makefile to install it in your favorite place.
  19.  
  20. Below, is the first page of the man page, so you can see if you care to
  21. even unpack the "sh" archive which follows it.
  22.  
  23. Feel free to submit bug fixes, or suggest improvements.
  24.  
  25. Enjoy.
  26.  
  27. -- Alan Stebbens, UCSB, Santa Barbara <aks@hub.ucsb.edu>
  28. "If all you have is a hammer, then everything looks like a nail."
  29.  
  30. ============================= cut here ===================================
  31.  
  32.      PARSEARGS(3)            (January 14, 1993)           PARSEARGS(3)
  33.  
  34.      NAME
  35.           parseargs.pl - Parse the argument vector
  36.  
  37.      SYNOPSIS
  38.           require 'parseargs.pl'
  39.  
  40.           &ParseOpts('FLAG1 FLAG2 ... FLAGn');
  41.  
  42.           &ParseArgs('FLAG1', 'ACTION1', 'FLAG2', 'ACTION2', ...);
  43.  
  44.           &ParseArgs(<<'EOF');
  45.              FLAG1   ACTION1
  46.              FLAG2   ACTION2
  47.              ...
  48.              FLAGn   ACTIONn
  49.           EOF
  50.  
  51.      DESCRIPTION
  52.           These subroutines parse the current command argument vector,
  53.           @ARGV,  for  switches  which match defined FLAG expressions,
  54.           evaluating associated ACTION expressions.
  55.  
  56.           The argument parsing stops on the first  unhandled  non-flag
  57.           argument.   An  error  is  reported  on  any  unhandled flag
  58.           arguments (-flag).
  59.  
  60.           There are two subroutines: ParseArgs,  and  ParseOpts.   The
  61.           former  is more general and allows complete control over the
  62.           flag strings and  the  associated  actions.   The  ParseOpts
  63.           routine has a simpler interface, with useful default actions
  64.           for the specified flag strings.
  65.  
  66.           In both routines, each FLAG is matched against  the  current
  67.           argument,  and,  if  successful, the corresponding ACTION is
  68.           evaluated, followed by a next.  FLAG can be a  general  Perl
  69.           expression,  or  it  can be one of a special syntax (defined
  70.           below), which is  used  to  create  a  Perl  expression  for
  71.           testing.
  72.  
  73.           Any argument not matching any of the test expressions causes
  74.           an  error.   When  an  error occurs, if the string $Usage is
  75.           defined, it will be printed after the error message.
  76.  
  77.           ACTION can be a general  Perl  expression,  except  that  no
  78.           embedded newlines are permitted.  An empty string, or action
  79.           of `#' is considered to be a null action, for  which  useful
  80.           defaults are supplied.
  81.  
  82.           Within ACTION, the string `ARG' will be substituted with the
  83.           appropriate  Perl expression which evaluates to the argument
  84.           of the switch which selected the action.
  85.  
  86.      Page 1                                          (printed 1/26/93)
  87.  
  88. ============================= cut here ===================================
  89.  
  90. parseargs.shar
  91. ============================= cut here ===================================
  92. #!/bin/sh
  93. # This is a shell archive (produced by shar 3.49)
  94. # To extract the files from this archive, save it to a file, remove
  95. # everything above the "!/bin/sh" line above, and type "sh file_name".
  96. #
  97. # made 01/26/1993 19:43 UTC by aks@anywhere
  98. # Source directory /fs.real/anywhere/home/aks/src/Lang/perl/Lib/parseargs
  99. #
  100. # existing files will NOT be overwritten unless -c is specified
  101. #
  102. #                                                                          
  103. #                                                                          
  104. #
  105. # This shar contains:
  106. # length  mode       name
  107. # ------ ---------- ------------------------------------------
  108. #  19844 -r--r--r-- parseargs.pl
  109. #    534 -r--r--r-- Makefile
  110. #    723 -rwxr-xr-x test.pl
  111. #    113 -rwxr-xr-x test1
  112. #
  113. if test -r _shar_seq_.tmp; then
  114.     echo 'Must unpack archives in sequence!'
  115.     echo Please unpack part `cat _shar_seq_.tmp` next
  116.     exit 1
  117. fi
  118. # ============= parseargs.pl ==============
  119. if test -f 'parseargs.pl' -a X"$1" != X"-c"; then
  120.     echo 'x - skipping parseargs.pl (File already exists)'
  121.     rm -f _shar_wnt_.tmp
  122. else
  123. | _shar_wnt_.tmp
  124. echo 'x - extracting parseargs.pl (Text)'
  125. sed 's/^X//' << 'SHAR_EOF' > 'parseargs.pl' &&
  126. # ParseArgs.pl script for perl
  127. 'di';
  128. 'ig00';
  129. #
  130. # Author: Alan K. Stebbens <aks@hub.ucsb.edu>
  131. # $Id: parseargs.pl,v 1.5 1993/01/26 19:43:43 aks Exp $
  132. # See bottom of file for documentation.
  133. X
  134. $InitParseProgram = '
  135. X Arg:while (@ARGV && ($_ = shift @ARGV)) {
  136. X       $arg = s/=(.*)// ? $1 : undef;
  137. X       while (/^-./) {        # parse clustered switches
  138. X ';
  139. X
  140. $FinishParseProgram = '
  141. X           last;
  142. X       }
  143. X       if (!index(\'-debug\',$_)) {
  144. X       $Debug = $arg || 1; next;
  145. X       }
  146. X       if (!index(\'-verbose\',$_)) {
  147. X       $Verbose = $arg || 1; next;
  148. X       }
  149. X       next if /^-$/;
  150. X       last unless /^-/;
  151. X       die "Bad arg: $_\n", $Usage;
  152. X    }
  153. X    unshift(@ARGV, $_) if length;
  154. X ';
  155. X
  156. sub ParseOpts {
  157. X    local($i);
  158. X    local(@opts) = split(' ',shift);
  159. X    for ($i = $#opts + 1; $i > $[; $i--) {
  160. X        splice(@opts, $i, 0, ''); # insert null actions
  161. X    }
  162. X    &ParseArgs(@opts);
  163. }
  164. X
  165. %ParseArgFlags =   ( '<', 'ParseArgInFile',
  166. X             '>', 'ParseArgOutFile',
  167. X             '/', 'ParseArgDirectory',
  168. X             '.', 'ParseArgPlainFile',
  169. X             '!', 'ParseArgNewFile',
  170. X             '@', 'ParseArgsFromFile',
  171. X             '#', 'ParseNumberArgs',
  172. X             '~', 'ParseUserLogin',
  173. X             '(', 'ParseGroupName',
  174. X             '=', '',
  175. X             ':', '',
  176. X             '+', '',
  177. X             '*', '',
  178. X           );
  179. X
  180. $ParseArgFlags = join('',keys(%ParseArgFlags));
  181. X
  182. sub ParseArgs {
  183. X    local(@arglist) = @_;    # argument list
  184. X    local($_);
  185. X    local($NoArg) = "Missing argument for option: ";
  186. X    if ($#arglist == $[) {    # a single string?
  187. X    local(@lines) = split(/\n/,$arglist[0]);
  188. X    @arglist = ();
  189. X    foreach (@lines) {    # parse strings into FLAG, ACTION pairs
  190. X        if (/^\s*(\S+)\s+(\S.*)$/) {
  191. X        push(@arglist,$1,$2);
  192. X        } elsif (/^\s*(\S+)/) {
  193. X        push(@arglist,$1,''); # default ACTION
  194. X        }
  195. X    }
  196. X    }
  197. X    local($parser,$x,$option,$flag,$action,$expr,$arg,$interp);
  198. X    $parser = $InitParseProgram;
  199. X    for ($x = 0; $x <= $#arglist; $x += 2) {
  200. X    $option = $arglist[$x];
  201. X    $action = $arglist[$x+1];
  202. X    length($option) || next;    # ignore null options
  203. X    $action =~ s/\s*\#\s*$//; # remove any comments
  204. X    $action =~ s/\bARG\b/\$arg/; # substitute
  205. X    # check for --word, -word, +word, or _word w or w/o =
  206. X    if ($option =~ /^(--|-|\+|_)(\w+)(\W|)/) {
  207. X        die "$0: Unknown option flag: $flag\n" 
  208. X        if !defined($ParseArgFlags{$flag = $3});
  209. X        $expr = "\t    if (!index('$1$2',\$_)) {\n";
  210. X        $interp = $ParseArgFlags{$flag};
  211. X        if ($flag) {
  212. X        $arg = "\$arg = defined(\$arg) ? \$arg : shift \@ARGV";
  213. X        $arg .= " || die \"$NoArg $2\\n\", \$Usage" if $flag eq '=';
  214. X        $expr .= "\t\t".$arg.";\n";
  215. X        $expr .= "\t\t\$arg = \&".$interp."(\$2,\$arg);\n" if $interp;
  216. X        $action = "\$opt_$2 = \$arg" unless $action;
  217. X        $expr .= "\t\t".$action.";\n";
  218. X        } else {        # no flag char: -xyz
  219. X        $arg = $1 eq '--' ? 1 : $1 eq '-' ? 2 : $1 eq '+' ? 4 : 8;
  220. X        $action = "\$opt_$2 = $arg" unless $action;
  221. X        $expr .= "\t\t".$action.";\n";
  222. X        }
  223. X        $expr .= "\t\tnext Arg;\n";
  224. X    } elsif ($option =~ /^(\w)(\W)?/) { # how about single character option?
  225. X        $interp = ($flag = $2) && $ParseArgFlags{$flag};
  226. X        die "$0: Unknown option flag: $flag on option $option\n"
  227. X        if index($ParseArgFlags,$flag = $2) < $[;
  228. X        $expr = "\t    if (s/^-$1/-/) {\n";
  229. X        $interp = $ParseArgFlags{$flag};
  230. X        if ($flag) {    # assignment option?
  231. X        $arg = "\$arg = ";
  232. X        if ($flag eq '+' || $flag eq '*') { # sticky args?
  233. X            $expr = "\t    if (s/^-$1(.*)//) {\n";
  234. X            $arg .= "length(\$1) ? \$1 : ";
  235. X        }
  236. X        $arg .= "defined(\$arg) ? \$arg : shift \@ARGV";
  237. X        $arg .= " || die \"$NoArg $1\\n\", \$Usage" 
  238. X            if $flag eq '=' || $flag eq '+';
  239. X        $expr .= "\t\t".$arg.";\n";
  240. X        $expr .= "\t\t\$arg = \&".$interp."(\$2,\$arg);" if $interp;
  241. X        $action = "\$opt_$1 = \$arg" unless $action;
  242. X        $expr .= "\t\t".$action.";\n" if $action;
  243. X        $expr .= "\t\tundef \$arg;\n";
  244. X        } else {
  245. X        $expr .= "\t\t\$opt_$1++;\n" unless $action;
  246. X        $expr .= "\t\t".$action.";\n" if $action;
  247. X        }
  248. X        $expr .= "\t\tnext;\n";
  249. X    } else {        # use option as expr
  250. X        $expr = "\t    if ($option) {\n";
  251. X        $expr .= "\t\t".$action.";\n" if $action;
  252. X        $expr .= "\t\tnext Arg;\n" unless $action !~ /\bnext\b/;
  253. X    }
  254. X    $parser .= $expr;
  255. X    $parser .= "\t    }\n";
  256. X    }
  257. X    $parser .= $FinishParseProgram;
  258. X    print STDERR $parser 
  259. X    if @ARGV && $ARGV[0] eq '-DEBUG_PARSER' && shift @ARGV;
  260. X    eval $parser;
  261. X    die $@ if $@;
  262. }
  263. X    
  264. # Reference this routine in an action if you want an option to 
  265. # insert arguments acquired by reading a file.
  266. X
  267. sub ParseArgsFromFile {
  268. X    local($file) = shift;
  269. X    open(FEXP,$file) || die "Can't open input: $file: $!\n";
  270. X    unshift(@ARGV, grep((chop, s/\s*\#.*$//, length > 0),<FEXP>));
  271. X    close FEXP;
  272. }
  273. X
  274. sub ParseArgInFile {
  275. X    local($opt,$_) = @_;
  276. X    die "$0: File $_ cannot be read!\n" unless -r;
  277. X    open("FH_$opt","<$_") || die "$O: Cannot open $_ for input: $!\n";
  278. X    $_;
  279. }
  280. X
  281. sub ParseArgOutFile {
  282. X    local($opt,$_) = @_;
  283. X    -e && ( -w || die "$0: File $_ cannot be written!\n" );
  284. X    open("FH_$opt",">$_") || die "$0: Cannot open $_ for output: $!\n";
  285. X    $_;
  286. }
  287. X
  288. sub ParseArgDirectory {
  289. X    local($opt,$_) = @_;
  290. X    -e || die "$0: Directory $_ does not exist!\n";
  291. X    -d || die "$0: $_ is not a directory!\n";
  292. X    $_;
  293. }
  294. X
  295. sub ParseArgPlainFile {
  296. X    local($opt,$_) = @_;
  297. X    -e || die "$0: File $_ does not exist!\n";
  298. X    -f || die "$0: File $_ is not a plain file!\n";
  299. X    $_;
  300. }
  301. X
  302. sub ParseArgNewFile {
  303. X    local($opt,$_) = @_;
  304. X    ! -e || die "$0: File $_ already exists!\n";
  305. X    $_;
  306. }
  307. X
  308. sub ParseNumberArgs {
  309. X    local($opt,$_) = @_;
  310. X    /^\d+$/ || die "$0: Option $opt $_ is not a number!\n";
  311. X    $_;
  312. }
  313. X
  314. sub ParseUserLogin {
  315. X    local($opt,$_) = @_;
  316. X    /^\d+$/ ? 
  317. X    $_ == (getpwuid($_))[$[+2] || die "$0: $_ is not a valid user id!\n"
  318. X        : $_ eq (getpwnam($_))[$[] || die "$0: $_ is not a valid login name!\n";
  319. X    $_;
  320. }
  321. X
  322. sub ParseGroupName {
  323. X    local($opt,$_) = @_;
  324. X    /^\d+$/ ?
  325. X    $_ == (getgrgid($_))[$[+2] || die "$0: $_ is not a valid group id!\n"
  326. X        : $_ eq (getgrnam($_))[$[] || die "$0: $_ is not a valid group name!\n";
  327. X    $_;
  328. }
  329. X
  330. 1;
  331. __END__
  332. ###############################################################
  333. X    # These next few lines are legal in both Perl and nroff.
  334. X
  335. .00;                       # finish .ig
  336. 'di           \" finish diversion--previous line must be blank
  337. .nr nl 0-1    \" fake up transition to first page again
  338. .nr % 0         \" start at page 1
  339. .rm ';
  340. .\" Bullet Item
  341. .de Bi
  342. .TP 1i
  343. .B \\h'.5i'\\$1
  344. ..
  345. .TH PARSEARGS 3 "January 14, 1993"
  346. .AT 3
  347. .SH NAME
  348. parseargs.pl - Parse the argument vector
  349. .SH SYNOPSIS
  350. .B require 'parseargs.pl'
  351. .sp
  352. .B &ParseOpts('FLAG1 FLAG2 ... FLAGn');
  353. .sp
  354. .B &ParseArgs('FLAG1', 'ACTION1', 'FLAG2', 'ACTION2', ...);
  355. .sp
  356. .nf
  357. .na
  358. .ft B
  359. &ParseArgs(<<'EOF');
  360. X   FLAG1   ACTION1
  361. X   FLAG2   ACTION2
  362. X   ...
  363. X   FLAGn   ACTIONn
  364. EOF
  365. .ft R
  366. .ad
  367. .fi
  368. .SH DESCRIPTION
  369. These subroutines parse the current command argument vector, 
  370. .BR @ARGV ,
  371. for switches which match defined 
  372. .B FLAG
  373. expressions, evaluating associated 
  374. .B ACTION
  375. expressions.
  376. .sp
  377. The argument parsing stops on the first unhandled non-flag argument.
  378. An error is reported on any unhandled flag arguments (\c
  379. .BI -flag ).
  380. .sp
  381. There are two subroutines: 
  382. .BR ParseArgs ,
  383. and 
  384. .BR ParseOpts .
  385. The former is
  386. more general and allows complete control over the flag strings and the
  387. associated actions.  The 
  388. .B ParseOpts
  389. routine has a simpler interface,
  390. with useful default actions for the specified flag strings.
  391. .sp
  392. In both routines, each 
  393. .B FLAG
  394. is matched against the current argument,
  395. and, if successful, the corresponding 
  396. .B ACTION 
  397. is evaluated, followed by
  398. .BR next .
  399. .B FLAG
  400. can be a general Perl expression, or it can be one of
  401. a special syntax (defined below), which is used to create a Perl
  402. expression for testing.
  403. .sp
  404. Any argument not matching any of the test expressions causes an error.
  405. When an error occurs, if the string 
  406. .B $Usage
  407. is defined, it will be
  408. printed after the error message.
  409. .sp
  410. .B ACTION
  411. can be a general Perl expression, except that no embedded
  412. newlines are permitted.  An empty string, or action of 
  413. .B `#'
  414. is considered to be a null action, for which useful defaults are
  415. supplied.
  416. .sp
  417. Within 
  418. .BR ACTION ,
  419. the string 
  420. .I `ARG'
  421. will be substituted with the
  422. appropriate Perl expression which evaluates to the argument of the switch
  423. which selected the action. 
  424. .sp
  425. In the case of 
  426. .BR ParseOpts ,
  427. all actions are provided by default.
  428. .sp
  429. As a convenience for Perl script writers (that is, myself :^), the
  430. following flags and actions are supplied, after all other flags have
  431. been tested: 
  432. .sp
  433. .nf
  434. .B \t-debug\t$DEBUG++
  435. .B \t-verbose\t$VERBOSE++
  436. .fi
  437. .sp
  438. Also, for the case of when arguments may be obtained by reading a file
  439. passed as an argument itself, the user may reference the subroutine
  440. .B &ParseArgsFromFile(\c
  441. .IB ARG )
  442. as an action, where 
  443. .I ARG
  444. is the special
  445. string recognized and substituted with an appropriate expression.
  446. .sp
  447. The syntax of 
  448. .B FLAG
  449. is:
  450. .TP .5i
  451. (a) \fB(--|-|+|_)\fIWORD\fB[\fIF\fB]\fR
  452. .sp
  453. This syntax allows the various methods of setting switches to be
  454. recognized, with an optional trailing flag character
  455. .IR `F' ,
  456. indicating how to handle the
  457. argument, if any.
  458. If there is no graphic character suffixed to the
  459. .IR WORD ,
  460. then the option accepts no arguments, and is set to 1 when supplied on
  461. the command line.
  462. .sp
  463. The following graphic flag characters are recognized and provide for
  464. interpretation of the arguments, when given.  When an explicit user
  465. action is given in conjunction with one of these flag characters, the
  466. interpretation action is accomplished before the user action.  When no
  467. user action is given, the default variable,
  468. .BI `$opt_ WORD' ,
  469. is assigned the value of the argument.
  470. .Bi `='
  471. this flag accepts a required argument, either in the same word following an
  472. equal sign (\c
  473. .BR `=' ),
  474. or in the next word of the argument vector.  That is, both of these
  475. argument types are valid:
  476. .sp
  477. .B \t-WORD=VALUE\t
  478. and
  479. .B \t-WORD VALUE
  480. .sp
  481. An omitted argument is an error with the \fB`='\fP flag character.
  482. .Bi `:'
  483. this flag character causes the option to take an 
  484. optional argument, not causing an error should it be omitted.
  485. .Bi `<'
  486. treat the argument as an input file,
  487. causing an error if the file is non-existent or unreadable.  The file is
  488. opened for reading under the file handle 
  489. .BI FH_ WORD.
  490. .Bi `>'
  491. treat the argument as an output file,
  492. causing an error if the file is not writable.  The file is opened for
  493. writing under the file handle
  494. .BI FH_ WORD.
  495. .Bi `/'
  496. treat the argument as a directory, which must exist.
  497. .Bi "`.'" "(a period)"
  498. treat the argument as a plain file which must exist; if the file is a
  499. directory, or a special file, then an error occurs.  Symbolic links are
  500. ok, if they point to a plain file.
  501. .Bi `!'
  502. treat the argument as a new, nonexistent file name.  An error occurs if
  503. the file already exists, in any form.
  504. .Bi `#'
  505. treat the argument as an integer, causing an error for any non-digits
  506. found.
  507. .Bi `~'
  508. verify the argument as a valid user login name or numerical user id.
  509. .Bi `('
  510. treat the argument as a valid group name, or numerical group id.
  511. .Bi `@'
  512. treat the argument as a readable file, read the files contents, and
  513. split the lines into the argument vector, 
  514. .BR @ARGV .
  515. .IP "" .5i
  516. The switches recognized by 
  517. .I (a)
  518. may all be minimally abbreviated, as
  519. the test expression used to recognize the switch is
  520. .B `!index(FLAG,$_)'.
  521. Thus, for the flag 
  522. .BR `-edit' , 
  523. the options 
  524. .BR `-edit' ,
  525. .BR `-edi' ,
  526. .BR `-ed',
  527. and
  528. .B `-e'
  529. will be recognized.
  530. .sp
  531. When designing switch names with abbreviation, care must be taken to
  532. specify the longer abbreviations first, so they will not be masked
  533. by shorter ones.
  534. .sp
  535. The default 
  536. .B ACTION
  537. performed by a switch matching this style 
  538. .BR FLAG ,
  539. is to set a Perl variable,
  540. .BI $opt_ WORD,
  541. to a `1', if no value was given, or to the argument supplied.
  542. .sp
  543. X  The following are all examples of this syntax:
  544. .sp
  545. .B  --list-all -edit +help -verbose _broadcast= _netmask=
  546. .B  -input< -output> -dir/ --user~ -file@ -count#
  547. .sp
  548. .TP .5i
  549. (b) \fIC\fB[=:<>/.!#~(+*]\fR
  550. .sp
  551. In this syntax, 
  552. .B C
  553. is a single character switch, which may be followed by one of the
  554. previously documented flag characters, or one of the following two 
  555. additional ones:
  556. .Bi `+'
  557. This flag character causes the option to require an argument, which may
  558. be given either juxtaposed with the option word itself, or on the
  559. subsequent argument vector word.
  560. .Bi `*'
  561. This flag character causes the option to attempt to obtain an argument,
  562. and failing that, cause no error.
  563. .IP "" .5i
  564. Single character switches may be given separately, or may be clustered into
  565. a single switch word.  For example, the options
  566. .B -l
  567. and
  568. .BR -t ,
  569. may be given as:
  570. .B -lt
  571. or
  572. .BR -tl .
  573. .sp
  574. The single character assignable options may require arguments, or
  575. they may be optional.  The argument syntax may be one of:
  576. .sp
  577. .nf
  578. .B \t\fR(1)\fB `-O=arg'
  579. .B \t\fR(2)\fB `-Oarg'
  580. .B \t\fR(3)\fB `-O arg'
  581. .fi
  582. .sp
  583. where 
  584. .B `-O'
  585. is your favorite option.  The argument flags 
  586. .B `=' 
  587. and 
  588. .B `:'
  589. indicate required or optional arguments which can only be assigned
  590. via styles 
  591. .I (1) 
  592. and 
  593. .IR (3) .
  594. The argument flags 
  595. .B `+' 
  596. and 
  597. .B `*'
  598. also mean required and optional, but indicate that style 
  599. .I (2)
  600. is permissible, which disallows option clustering.
  601. .sp
  602. The following table should make this a little clearer:
  603. .sp
  604. .ta .5i +.5i +1i +1i +1i
  605. .nf
  606. .ft B
  607. X    Flag    Argument?    -O=arg    -Oarg    -O arg
  608. .ft R
  609. X    ----    ---------    ------    -----    ------
  610. X     \fB=\fP    required      ok      no      ok      
  611. X     \fB:\fP    optional      ok      no      ok
  612. X     \fB+\fP    required      ok      ok      ok
  613. X     \fB*\fP    optional      ok      ok      ok
  614. .fi
  615. .ta 0.5i
  616. .sp
  617. If a switch defined with an argument is given in a cluster, its
  618. argument may come from:
  619. .sp 
  620. .IP \\h'.5i'1. 1i
  621. the immediately following characters, if the 
  622. .I FLAG
  623. is defined as 
  624. .B `C+' 
  625. or 
  626. .BR `C*' .
  627. This behavior is similar to how 
  628. .I lpr
  629. parses its printer switch: 
  630. .BR `-Pprinter' .
  631. In this case, the flag would be given as
  632. .BR `P+' .
  633. If the flag is defined as 
  634. .BR `P=' ,
  635. then either an equal sign must be used, or the subsequent word will be
  636. used as the argument.
  637. .sp
  638. .IP \\h'.5i'2. 1i
  639. the string followed by the equal sign (\fB`='\fP)
  640. in the same word as the switch.  This allows single character switches
  641. to be given similar to longer switches:
  642. .B `-l=999'
  643. or 
  644. .BR `-length=999' .
  645. .IP \\h'.5i'3. 1i
  646. the subsequent word in the argument vector, if there are no
  647. strings resulting from cases 
  648. .I (1)
  649. or 
  650. .I (2)
  651. above.
  652. .sp 
  653. The default action for this style flag is to increment a Perl
  654. variable, 
  655. .BI $opt_ C, 
  656. where 
  657. .B `C' 
  658. is the single character switch name, or to set its value to the argument
  659. if defined to accept arguments. 
  660. For example, if the flags 
  661. .B `l'
  662. and 
  663. .B `t'
  664. were defined, then the switch 
  665. .B `-lt'
  666. would cause the variables
  667. .B $opt_l
  668. and
  669. .B $opt_t
  670. to both be incremented.
  671. .TP .5i
  672. (c) \fBexpr\fR
  673. This syntax is the usual Perl expression.  It is tested
  674. directly, and no default action is assumed; actions must be
  675. specified by the user.
  676. .PP
  677. Since the order of the flags is the order in which the tests will be
  678. performed, if the user mixes flag styles, and there are overlaps between
  679. single character options and word options, the word options should
  680. be specified first, otherwise the single character parsing will cause
  681. the word argument to get broken into characters.
  682. .PP
  683. In order to facilitate debugging the options specifications and the 
  684. resulting parser, if the first argument is
  685. .BR `-DEBUG_PARSER' ,
  686. then the parser code will be printed to 
  687. .B STDERR
  688. before being eval'ed.
  689. .SH EXAMPLES
  690. .sp
  691. .nf
  692. .ft B
  693. &ParseArgs(<<'EOF')            \fR# NOTE: single quotes!\fB
  694. X    t     $tbl++
  695. X    l     $lst++
  696. EOF
  697. .ft R
  698. .fi
  699. .IP
  700. This example recognizes the 
  701. .B `-t'
  702. and 
  703. .B `-l'
  704. switches, which may be
  705. given separately or combined as 
  706. .B `-lt' 
  707. or 
  708. .BR `-tl' ,
  709. and sets the associated variables accordingly.  In this case, the
  710. default variable assignments (\c
  711. .B $opt_t
  712. and 
  713. .BR $opt_l )
  714. are NOT done.
  715. .PP
  716. .nf
  717. .ft B
  718. &ParseArgs('t', '$tbl++', 'l', '$lst++');
  719. .ft R
  720. .fi
  721. .IP
  722. This is equivalent to the previous example.
  723. .PP
  724. .ft B
  725. &ParseOpts('t l');
  726. .ft R
  727. .IP
  728. This is essentially equivalent to the first two examples, except
  729. that the variables set for 
  730. .B `-t'
  731. and 
  732. .B `-l'
  733. are 
  734. .B $opt_t
  735. and 
  736. .BR $opt_l ,
  737. respectively.
  738. .PP
  739. .nf
  740. .ft B
  741. &ParseOpts('-file= -list: -edit -optimize');
  742. .ft R
  743. .fi
  744. .IP
  745. In this example, the variables set would be: 
  746. .BR $opt_file ,
  747. .BR $opt_list ,
  748. .BR $opt_edit ,
  749. and 
  750. .BR $opt_optimize .
  751. The 
  752. .B `-list'
  753. option has an optional argument, while 
  754. .B `-file'
  755. must be supplied with an argument or an error will result.
  756. .PP
  757. .nf
  758. .ft B
  759. &ParseArgs(<<'EOF");
  760. X     -file=   &ParseArgsFromFile(ARG);
  761. X     b        $Brief++
  762. X     v        $Verbose++
  763. X     l*       $Len = ARG || 80
  764. X     -edit
  765. X     -arch=   $Arch = ARG
  766. X     -os=     $OS = ARG
  767. EOF
  768. .fi
  769. .ft R
  770. .IP
  771. This example illustrates the combination of the various types,
  772. including a default action.  
  773. .sp
  774. The 
  775. .B `-file'
  776. switch, which may be abbreviated as 
  777. .B `-f'
  778. causes the routine,
  779. .I &ParseArgsFromFile
  780. to be invoked with computed argument 
  781. .B (ARG)
  782. of the 
  783. .B `-file'
  784. switch.  The arguments read from the file argument are then placed on
  785. the argument stack as if they had been typed by the user.  These new
  786. arguments are parsed along with any remaining, original arguments.
  787. .sp
  788. The 
  789. .B $Brief
  790. and
  791. .B $Verbose
  792. variables will be set if their respective, clusterable option flags are
  793. given. 
  794. .sp
  795. The 
  796. .B `-l'
  797. option may be optionally given an argument, either as
  798. .B `-lXYZ' or 
  799. .BR `-l\ XYZ' ;
  800. it is assigned to 
  801. .BR $Len .
  802. .sp
  803. The variable
  804. .B $opt_edit 
  805. will be set (to 1).
  806. .sp
  807. The 
  808. .B $Arch
  809. variable will be set to the argument supplied to the
  810. .B `-arch'
  811. switch; similarly, the
  812. .B $OS 
  813. variable will be set by the 
  814. .B `-os'
  815. switch, both of which may be abbreviated.
  816. .sp
  817. .PP
  818. .ft B
  819. &ParseOpts('-in< -out> -directory/ -file. -user~ -group( -num# -new!');
  820. .ft R
  821. .PP
  822. This is a rather baroque example illustrating the features of useful
  823. default actions.  The following variables will be set as follows.
  824. .TP 1i
  825. .B $opt_in
  826. is set to the name of a file which is opened for input, using the
  827. filehandle of
  828. .BR `FH_in' .
  829. The variable and filehandle names are always 
  830. .BI `$opt_ OPTION'
  831. and
  832. .BI `FH_ OPTION'.
  833. If the file could not be opened for input, an error would have occurred.
  834. .TP
  835. .B $opt_out
  836. is set to the name of a file opened for writing, using the filehandle of
  837. .BR `FH_out' .
  838. .TP
  839. .B $opt_directory
  840. is set to the name of an existing directory; an error will occur if the
  841. directory doesn't exist.
  842. .TP
  843. .B $opt_file
  844. is set to the name of an existing file; no other tests are made, just
  845. existence.  If the file given as an argument doesn't exist, an error
  846. occurs.
  847. .TP
  848. .B $opt_user
  849. is set to the name of a valid user login name or numeric user id.
  850. .TP
  851. .B $opt_group
  852. is set to the name of a valid group name or numeric group id.
  853. .TP
  854. .B $opt_num
  855. is set to a number given as the argument; anything other than a number
  856. causes an error.
  857. .IP
  858. .B $opt_new
  859. is set to the name of a non-existent file; an error occurs if the file
  860. already exists.
  861. .sp
  862. .SH ENVIRONMENT
  863. .B
  864. .IP @ARGV
  865. The argument vector is implicitly parsed.
  866. .SH FILES
  867. None.
  868. .SH AUTHOR
  869. Alan Stebbens <aks@hub.ucsb.edu>
  870. .SH "SEE ALSO"
  871. .IR getopts.pl (3),
  872. .IR perl (1)
  873. .SH DIAGNOSTICS
  874. .PP
  875. When an error occurs, one of the following error messages is generated,
  876. followed by the value of 
  877. .I $Usage
  878. if it is defined.
  879. .sp
  880. Unknown option flag: $flag
  881. .sp
  882. Can't open input: $file: $!
  883. .sp
  884. Unknown option flag: $flag on option $option
  885. .sp
  886. File $_ cannot be read!
  887. .sp
  888. File $_ cannot be written
  889. .sp
  890. Cannot open $_ for output: $!
  891. .sp
  892. Directory $_ does not exist!
  893. .sp
  894. $_ is not a directory!
  895. .sp
  896. File $_ does not exist!
  897. .sp
  898. File $_ is not a plain file!
  899. .sp
  900. File $_ already exists!
  901. .sp
  902. Option $opt: $_ is not a number!
  903. .sp
  904. $_ is not a valid user id!
  905. .sp
  906. $_ is not a valid login name!
  907. .sp
  908. $_ is not a valid group id!
  909. .sp
  910. $_ is not a valid group name!
  911. .sp
  912. Missing argument for option: $option
  913. .sp
  914. Bad option: $option
  915. .SH BUGS
  916. Probably.
  917. .\" Emacs Local Variables:
  918. .\" Emacs mode: perl
  919. .\" Emacs End:
  920. SHAR_EOF
  921. chmod 0444 parseargs.pl ||
  922. echo 'restore of parseargs.pl failed'
  923. Wc_c="`wc -c < 'parseargs.pl'`"
  924. test 19844 -eq "$Wc_c" ||
  925.     echo 'parseargs.pl: original size 19844, current size' "$Wc_c"
  926. rm -f _shar_wnt_.tmp
  927. fi
  928. # ============= Makefile ==============
  929. if test -f 'Makefile' -a X"$1" != X"-c"; then
  930.     echo 'x - skipping Makefile (File already exists)'
  931.     rm -f _shar_wnt_.tmp
  932. else
  933. | _shar_wnt_.tmp
  934. echo 'x - extracting Makefile (Text)'
  935. sed 's/^X//' << 'SHAR_EOF' > 'Makefile' &&
  936. # Makefile to install parseargs
  937. X
  938. X    ROOT = /eci/share
  939. X PERLLIB = $(ROOT)/lib/perl
  940. X  MANDIR = $(ROOT)/man/man3
  941. X
  942. X INSTALL = /usr/ucb/install
  943. X
  944. I    = ( set -x ; $(INSTALL) -c -m 444 $? $@ )
  945. L    = ( set -x ; ln -s $? $@ )
  946. R    = if [ -f $@ ]; then rm -f $@ ; fi
  947. X
  948. default:
  949. X    @( set -x ; $(MAKE) -n install )
  950. X
  951. install: $(PERLLIB)/parseargs.pl $(MANDIR)/parseargs.3
  952. X
  953. $(PERLLIB)/parseargs.pl:    parseargs.pl ;            @$R ; $I
  954. $(MANDIR)/parseargs.3:        $(PERLLIB)/parseargs.pl ;    @$R ; $L
  955. X
  956. shar:
  957. X    shar -L50 -o parseargs.shar parseargs.pl Makefile test.pl test1
  958. SHAR_EOF
  959. chmod 0444 Makefile ||
  960. echo 'restore of Makefile failed'
  961. Wc_c="`wc -c < 'Makefile'`"
  962. test 534 -eq "$Wc_c" ||
  963.     echo 'Makefile: original size 534, current size' "$Wc_c"
  964. rm -f _shar_wnt_.tmp
  965. fi
  966. # ============= test.pl ==============
  967. if test -f 'test.pl' -a X"$1" != X"-c"; then
  968.     echo 'x - skipping test.pl (File already exists)'
  969.     rm -f _shar_wnt_.tmp
  970. else
  971. | _shar_wnt_.tmp
  972. echo 'x - extracting test.pl (Text)'
  973. sed 's/^X//' << 'SHAR_EOF' > 'test.pl' &&
  974. #!/bin/perl
  975. X
  976. require 'parseargs.pl';
  977. X
  978. $Usage = <<EOF;
  979. usage: $0 -input INPUT -output OUTPUT -new NEW -exists OLD
  980. X      -login LOGIN -group GROUP -number NUM
  981. EOF
  982. X    
  983. &ParseArgs(<<'EOF');
  984. X    -input<
  985. X    -dir/
  986. X    -output>
  987. X    -new!
  988. X    -exists.
  989. X    -login~
  990. X    -group(
  991. X    -number#
  992. EOF
  993. X
  994. format STDOUT =
  995. X input = @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  996. X     $opt_input
  997. X   dir = @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  998. X     $opt_dir
  999. output = @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  1000. X     $opt_output
  1001. X   new = @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  1002. X     $opt_new
  1003. exists = @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  1004. X     $opt_exists
  1005. X login = @<<<<<<<<<<<<<<
  1006. X     $opt_login
  1007. X group = @<<<<<<<<<<<<<<<
  1008. X     $opt_group
  1009. number = @<<<<<<<<<<<<<<
  1010. X     $opt_number
  1011. .
  1012. X
  1013. write;
  1014. X
  1015. exit;
  1016. SHAR_EOF
  1017. chmod 0755 test.pl ||
  1018. echo 'restore of test.pl failed'
  1019. Wc_c="`wc -c < 'test.pl'`"
  1020. test 723 -eq "$Wc_c" ||
  1021.     echo 'test.pl: original size 723, current size' "$Wc_c"
  1022. rm -f _shar_wnt_.tmp
  1023. fi
  1024. # ============= test1 ==============
  1025. if test -f 'test1' -a X"$1" != X"-c"; then
  1026.     echo 'x - skipping test1 (File already exists)'
  1027.     rm -f _shar_wnt_.tmp
  1028. else
  1029. | _shar_wnt_.tmp
  1030. echo 'x - extracting test1 (Text)'
  1031. sed 's/^X//' << 'SHAR_EOF' > 'test1' &&
  1032. #!/bin/sh
  1033. set -x
  1034. ./test.pl -input=test.pl -dir . -output=xyz -new=qrz -exists=test1 -login bin -group bin -num 1
  1035. SHAR_EOF
  1036. chmod 0755 test1 ||
  1037. echo 'restore of test1 failed'
  1038. Wc_c="`wc -c < 'test1'`"
  1039. test 113 -eq "$Wc_c" ||
  1040.     echo 'test1: original size 113, current size' "$Wc_c"
  1041. rm -f _shar_wnt_.tmp
  1042. fi
  1043. exit 0
  1044.