home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / perl / scripts-osu / getargs < prev    next >
Encoding:
Text File  |  1990-11-26  |  8.0 KB  |  272 lines

  1. Path: tut.cis.ohio-state.edu!pt.cs.cmu.edu!rochester!kodak!atexnet!lawrence
  2. From: lawrence@epps.kodak.com (Scott Lawrence)
  3. Newsgroups: comp.lang.perl
  4. Subject: getargs.pl (for use and comment)
  5. Message-ID: <5068@atexnet.UUCP>
  6. Date: 28 Nov 90 16:45:30 GMT
  7. Sender: news@atexnet.UUCP
  8. Reply-To: lawrence@epps.kodak.com
  9. Organization: Electronic Pre-Press Systems, a Kodak company
  10. Lines: 259
  11.  
  12.  
  13. I am a perl novice; as a learning exersize, and because I needed one, I am
  14. writing a document repository system in perl (assigns document numbers,
  15. stores and retrieves documents, searches by keywords, that sort of thing).
  16.  
  17. In the course of starting the system I found that the simple switch parsing
  18. stuff that comes with perl didn`t do all that I really wanted, so I wrote a
  19. more comprehensive package I call getargs. 
  20.  
  21. The getargs.pl package provides provides subroutine 'getargs' which takes a
  22. list which is interpreted as a picture of the expected arguments. It
  23. assigns values from ARGV into the variables specified in the list.  It 
  24. supports the model for arguments in which all switches come before any
  25. positional arguments, automatically handling '--', '-usage', and '-?'. If
  26. ARGV doesn`t parse correctly (too many or too few arguments or an
  27. unrecognized switch), it prints a usage message constructed from the picture
  28. and returns 0, otherwise it returns 1.  
  29.  
  30. Example:
  31.  
  32. &getargs( '-', 'test', 0, 'Test'
  33.          ,'-', 't', 0, 'Test'
  34.          ,'-', 'file', 1, 'File'
  35.          ,'m', 'required', 1, 'Required'
  36.          ,'o', 'optional-list', -1, 'OptionalList'
  37.         ) || exit 1;
  38.  
  39. produces:
  40.  
  41. > testget -usage
  42. Usage:
  43.     testget [-test] [-t] [-file <file>]
  44.             [--] <required> [<optional-list>] ...
  45.  
  46. Note that the -test and -t switches both assign to the same variable, so
  47. they are aliases (though the usage picture doesn't make that clear).
  48.  
  49. Any suggestions for improvements to the routine (or bug fixes) would be
  50. appreciated. 
  51.  
  52. ---
  53. Scott Lawrence         <lawrence@epps.kodak.com>       <s.lawrence@ieee.org>
  54. Atex Advanced Publishing Systems,     Voice: 508-670-4023  Fax: 508-670-4033
  55. Electronic Pre-Press Systems; 165 Lexington St. 400/165L; Billerica MA
  56. 01821
  57. ------- cut here ---------
  58. #!/usr/local/bin/perl
  59. #
  60. # Provides the routine getargs
  61. # which takes a picture of the expected arguments of the form:
  62. # ( <tuple> [, <tuple> ]... )
  63. # <tuple> ::= <type>, <keyword>, <size>, <variable>
  64. # <type>  ::= '-' for switch arguments
  65. #             'm' for mandatory positional arguments
  66. #             'o' for optional positional arguments
  67. # <keyword> ::= string to match for switch arguments 
  68. #               (also used to print for usage of postional arguments)
  69. # <size> ::= number of values to consume from ARGV ( 0 = set variable to 1 )
  70. # <variable> ::= name of variable (not including $ or @) to assign
  71. #                argument value into
  72. #
  73. # automatically provides -usage and -?
  74. # automatically provides --
  75. #
  76. # Copyright (c) 1990 by Scott Lawrence <s.lawrence@ieee.org>
  77. # May be copied and modified freely so long as the above copyright notice 
  78. # is retained. This program is distributed WITHOUT ANY WARRANTY and
  79. # without even the implied warranty of MERCHANTABILITY or FITNESS FOR 
  80. # A PARTICULAR PURPOSE. 
  81.  
  82. package getargs;
  83.  
  84. sub main'getargs 
  85. local(@Picture) = @_;
  86.  
  87. # Now  parse the argument picture 
  88. local( $Type,  $Keyword,  $Size, $Variable, $Tuple, %Sizes, %Switches ); 
  89. local( $Options, $Mandatories, @Positional, $Target, %Targets );
  90.  
  91. for ( $Tuple = 0; $Tuple < $#Picture; $Tuple += 4 )
  92. {
  93.     ( $Type, $Keyword, $Size, $Variable ) = @Picture[ $Tuple..$Tuple+3 ];
  94.  
  95.     $Sizes{ $Keyword } = $Size;
  96.     $Targets{ $Keyword } = $Variable;
  97.  
  98.     if ( $Type eq "-" ) # switch argument
  99.     {
  100.         # print "Switch: -$Keyword\n";
  101.     }
  102.     elsif ( $Type eq "m" ) # mandatory positional argument
  103.     {
  104.         $Options && die "Optional Arg in picture before Mandatory Arg\n";
  105.         $Mandatories++;
  106.         push( @Positional, $Keyword );
  107.     }
  108.     elsif ( $Type eq "o" ) # optional positional argument
  109.     {
  110.         $Options++;
  111.         push( @Positional, $Keyword );
  112.     }
  113.     else { die "Undefined Type: $Type\n"; } 
  114. }
  115.  
  116.     local( @ActualArgs ) = @ARGV; 
  117.  
  118. Switch: while ( $#Switches && ($_ = shift @ActualArgs) ) 
  119. {
  120.     if ( /^--/ ) ## force end of options processing
  121.         {
  122.             last Switch;
  123.         }
  124.     elsif ( /^-\d+/ ) ## numeric argument - not an option
  125.         {
  126.             unshift( @ActualArgs, $_ );
  127.             last Switch;
  128.         }
  129.     elsif ( /^-\?/ || /^-usage/ ) 
  130.         { 
  131.               &usage( @Picture ); 
  132.               return 0; 
  133.         }
  134.     elsif ( /^-(\w+)/ ) ## looks like a switch...
  135.         {
  136.             if ( $Target = $Targets{ $1 } )
  137.             {
  138.                 &assign_value( $Target, $Sizes{ $1 } );
  139.             }
  140.             else
  141.             {
  142.                 warn "Invalid switch $_\n";
  143.                 &usage( @Picture );
  144.                 return 0;
  145.             }
  146.         } 
  147.     else
  148.         {
  149.             unshift( @ActualArgs, $_ );
  150.             last Switch;
  151.         }
  152.     } # Switch
  153.  
  154.     Positional: while( $_ = shift( @Positional ) ) 
  155.     {
  156.         &assign_value( $Targets{ $_ }, $Sizes{ $_ } ) || last Positional; 
  157.         $Mandatories--;
  158.     }
  159.  
  160.     if ( @ActualArgs )
  161.     {
  162.         warn "Too many arguments: @ActualArgs\n";
  163.         &usage( @Picture );
  164.         0;
  165.     }
  166.     elsif ( $Mandatories > 0 ) 
  167.     { 
  168.         warn "Not enough arguments supplied\n";
  169.         &usage( @Picture );
  170.         0;
  171.     }
  172.     else
  173.     {
  174.         1;
  175.     }
  176.  
  177. } # sub getargs
  178.  
  179. sub assign_value 
  180. {
  181.     local ( $Target, $Size ) = @_;
  182.     local ( $Assignment );
  183.  
  184.     if ( $Size <= @ActualArgs )
  185.     {
  186.         Assign:
  187.         {
  188.           $Assignment = '$main\''.$Target.' = 1;'
  189.                                              , last Assign if ( $Size == 0 );
  190.           $Assignment = '$main\''.$Target.' = shift @ActualArgs;'
  191.                                              , last Assign if ( $Size == 1 );
  192.           $Assignment = '@main\''.$Target.' = @ActualArgs[ $[..$[+$Size-1 ],@ActualArgs = @ActualArgs[ $[+$Size..$#ActualArgs ];'
  193.                                              , last Assign if ( $Size > 1 );
  194.           $Assignment = '@main\''.$Target.' = @ActualArgs, @ActualArgs = ();'
  195.                                              , last Assign if ( $Size == -1 );
  196.           die "Invalid argument type in picture\n";
  197.         }
  198.  
  199.         eval $Assignment;
  200.         1;
  201.     }
  202.     else
  203.     {
  204.         @ActualArgs = ();
  205.         0;
  206.     }
  207. }
  208.  
  209. sub usage
  210.     print "Usage:\n"; 
  211.     print "    $0"; 
  212.     local( @Picture ) = @_;
  213.     local( $Type,  $Keyword,  $Size, $Tuple, $Switches );
  214.  
  215.     $Switches = 0;
  216.     Switch: for ( $Tuple = 0; $Tuple < $#Picture; $Tuple += 4 )
  217.     {
  218.         ( $Type, $Keyword, $Size ) = @Picture[ $Tuple..$Tuple+2 ];
  219.     
  220.         if ( $Type eq "-" ) # switch argument
  221.         {
  222.             $Switches++;
  223.             print " [-$Keyword";
  224.             if ( $Size == -1 )
  225.             {
  226.                 print " <$Keyword> ... ]"; 
  227.                 last Switch;
  228.             }
  229.             print " <$Keyword>" while ( $Size-- > 0 );
  230.             print "]";
  231.         }
  232.     }
  233.     
  234.     print "\n   "." " x length($0)."  [--]" if $Switches;
  235.     
  236.     Positional: for ( $Tuple = 0; $Tuple < $#Picture; $Tuple += 4 )
  237.     {
  238.         ( $Type, $Keyword, $Size ) = @Picture[ $Tuple..$Tuple+2 ];
  239.     
  240.         if ( $Type eq "m" ) # mandatory positional argument
  241.         {
  242.             if ( $Size == -1 )
  243.             {
  244.                 print " <$Keyword> ..."; 
  245.                 last Positional;
  246.             }
  247.             print " <$Keyword>" while ( $Size-- > 0 );
  248.         }
  249.         elsif ( $Type eq "o" ) # optional positional argument
  250.         {
  251.             if ( $Size == -1 )
  252.             {
  253.                 print " [<$Keyword>] ..."; 
  254.                 last Positional;
  255.             }
  256.             print " [<$Keyword>" while ( $Size-- > 0 );
  257.             print "]";
  258.         }
  259.     }
  260.     
  261.     print "\n";
  262. }
  263. 1;
  264. --
  265. ---
  266. Scott Lawrence         <lawrence@epps.kodak.com>       <s.lawrence@ieee.org>
  267. Atex Advanced Publishing Systems,     Voice: 508-670-4023  Fax: 508-670-4033
  268. Electronic Pre-Press Systems; 165 Lexington St. 400/165L; Billerica MA 01821
  269.  
  270.