home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume29 / parseargs / part03 / parseargs.awk < prev    next >
Encoding:
AWK Script  |  1992-05-19  |  6.6 KB  |  176 lines

  1. #!/usr/bin/awk -f
  2.  
  3. ##########################################################################
  4. ## ^FILE: parseargs.awk - parseargs for awk programs
  5. ##
  6. ## ^DESCRIPTION:
  7. ##    This file defines an awk function named parseargs to parse
  8. ##    command-line arguments for awk scripts. It also contains a
  9. ##    bare-bones template of what such an awk-script might contain.
  10. ##
  11. ## ^HISTORY:
  12. ##    02/21/91    Brad Appleton    <brad@ssd.csd.harris.com>    Created
  13. ###^^#####################################################################
  14.  
  15.  
  16. #########
  17. ## ^FUNCTION: parseargs - parse command-line argument vectors
  18. ##
  19. ## ^SYNOPSIS:
  20. ##    parseargs( argc, argv, argd, arr )
  21. ##
  22. ## ^PARAMETERS:
  23. ##    argc -- the number of elements in argv (usually ARGC-1).
  24. ##    argv -- the vector of command-line arguments (usually ARGV).
  25. ##    argd -- the argument-description string
  26. ##    arr  -- the associative array to assign command-line values from
  27. ##
  28. ## ^DESCRIPTION:
  29. ##    Parseargs will invoke parseargs(1) to parse the command-line given
  30. ##    in <argv> for the command defined by <argd>.  The resulting values
  31. ##    will be assigned to elements of the associative array given by <arr>.
  32. ##    Values are assigned using using the syntax: arr [ "argname" ] = value;
  33. ##    The exception to this is that if the <argname> is "ARGV" then the global
  34. ##    array ARGV is reset to the given array (using tab separated fields).
  35. ##
  36. ## ^REQUIREMENTS:
  37. ##    Any desired initial values for items in <arr> should be assigned BEFORE
  38. ##    calling this function (using the syntax: arr[ "argname" ] = initial-val).
  39. ##
  40. ##    The following global variables may be assigned before calling parseargs:
  41. ##
  42. ##       PROGNAME -- name of the current awk script (default= ARGV[0])
  43. ##       PARSEOPTS -- any extra options to pass to parseargs() (default="-ul")
  44. ##       PARSEINPUT -- input file for parseargs(1) (default=unique-name)
  45. ##       PARSEOUTPUT -- output file for parseargs(1) (default=unique-name)
  46. ##
  47. ## ^SIDE-EFFECTS:
  48. ##    The files PARSEINPUT and PARSEOUTPUT are created and then deleted.
  49. ##
  50. ##    The return value from parseargs(1) will be stored in the global-variable
  51. ##    named PARSESTATUS.
  52. ##
  53. ##    The global variable PARSEARGS will contain the command-line used to
  54. ##    invoke parseargs(1).
  55. ##
  56. ##    ARGV and ARGC may be reset, all other values are (re)set in <arr>.
  57. ##
  58. ## ^RETURN-VALUE:
  59. ##    The exit code returned by parseargs(1).
  60. ##
  61. ## ^BUGS:
  62. ##    Assumes that short-options are NOT disabled by $PARSECNTL.
  63. ##
  64. ##    Due to the limited ability of awk, scripts using parseargs(1) cannot
  65. ##    use short-options (with a  dash '-') because awk will attempt to interpret
  66. ##    any such arguments as options to awk and remove them from ARGV (regardless
  67. ##    of whether or not they are valid awk-options). Keyword options (with a
  68. ##    plus sign '+') may still be used without this difficulty. Dash-options
  69. ##    may be successfully processed if they did not first appear on the command
  70. ##    to the awk-script, so the full syntax of unix-style options could be 
  71. ##    provided in an array other than ARGV.
  72. ##
  73. ## ^ALGORITHM:
  74. ##    - set defaults for PROGNAME, PARSEOPTS, PARSEINPUT, and PARSEOUTPUT.
  75. ##    - build the parseargs command (dont forget to quote arguments).
  76. ##    - redirect input and output of the parseargs command.
  77. ##    - run parseargs(1)
  78. ##    - assign the exit-code from parseargs(1) to PARSESTATUS
  79. ##    - remove PARSEINPUT
  80. ##    - if PARSESTATUS != 0
  81. ##      - save RS and FS and reset RS = "" and FS = "\n"
  82. ##      - for each record in PARSEOUTPUT
  83. ##        - $1 is the argname and $2 is the value
  84. ##        - if $1 is "ARGV" reset ARGV and ARGC ($2 is a tab separated array)
  85. ##        - else assign arr[ $1 ] = $2
  86. ##      end-for
  87. ##      - restore RS and FS to previous values
  88. ##      - remove PARSEOUTPUT
  89. ##      - return PARSESTATUS
  90. ###^^####
  91.  
  92. function parseargs(argc, argv, argd, arr) {
  93.       ## set defaults -- use $$ to get a unique suffix string
  94.    if ( ! PROGNAME )     PROGNAME = ARGV[0];
  95.    if ( ! PARSEOPTS )    PARSEOPTS = "-u -l";
  96.  
  97.    "echo  ${TMP:-/tmp}/parseargs.${$}_"  |  getline TMPFILE;
  98.    if ( ! PARSEINPUT )   PARSEINPUT = TMPFILE "in";
  99.    if ( ! PARSEOUTPUT )  PARSEOUTPUT = TMPFILE "out";
  100.  
  101.       ## build the options and required arguments for parseargs(1)
  102.    PARSEARGS = sprintf( "parseargs -s awk %s -S '\t' -- '%s'",
  103.                             PARSEOPTS, PROGNAME );
  104.  
  105.       ## quote each elemnt in argv and append it to the parseargs-command
  106.    for ( i = 1 ; i <= argc ; i++ ) {
  107.       arg = argv[i];
  108.       gsub( /'/, "'\\''", arg );
  109.       PARSEARGS = PARSEARGS " '" arg "'";
  110.    }
  111.  
  112.       ## set up i/o redirection
  113.    PARSEARGS = PARSEARGS  " <" PARSEINPUT  " >" PARSEOUTPUT;
  114.    print  argd > PARSEINPUT;
  115.  
  116.       ## invoke parseargs(1) and save the status
  117.    PARSESTATUS = system( PARSEARGS );
  118.    system( "/bin/rm -f " PARSEINPUT );  ## dont need input anymore
  119.  
  120.       ## if successful status, read the result
  121.    if ( PARSESTATUS == 0 ) {
  122.       save_RS = RS; save_FS = FS;
  123.       RS = ""; FS = "\n";
  124.       while ( getline  < PARSEOUTPUT  > 0 ) {
  125.          gsub( /\034/, "\n" );
  126.          if ( $1 == "ARGV" ) {
  127.             ARGC = 1 + split( $2, ARGV, "\t" );
  128.             ARGV[0] = PROGNAME;
  129.          }
  130.          else  arr[ $1 ] = $2;
  131.       }
  132.       RS = save_RS; FS = save_FS;
  133.    }
  134.    system( "/bin/rm -f " PARSEOUTPUT );
  135.  
  136.    return  PARSESTATUS;
  137. }
  138.  
  139.  
  140. BEGIN {
  141.   PROGNAME = "test.awk";
  142.   ARGD = sprintf( "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s",
  143.     "'?', ARGHIDDEN, argUsage, NULL,    'Help : print usage and exit'" ,
  144.     "'S', ARGVALOPT, argStr,   string,  'STRing : optional string arg'" ,
  145.     "'g', ARGLIST,   argStr,   groups,  'newsGROUPS : groups to test'" ,
  146.     "'r', ARGOPT,    argInt,   count,   'REPcount : group repeat count'" ,
  147.     "'d', ARGOPT,    argStr,   dirname, 'DIRectory : working directory'" ,
  148.     "'x', ARGOPT,    argBool,  xflag,   'Xflag : turn on X-mode'" ,
  149.     "'y', ARGOPT,    argUBool, yflag,   'Yflag : turn off Y-mode'" ,
  150.     "'s', ARGOPT,    argChar,  sepch,   'SEPchar : field separator'" ,
  151.     "'f', ARGLIST,   argStr,   files,   'files : files to process'" ,
  152.     "' ', ARGREQ,    argStr,   name,    'name : name to use'" ,
  153.     "' ', ARGLIST,   argStr,   argv,    'argv : any remaining arguments'" ,
  154.     "ENDOFARGS" );
  155.  
  156.   Args[ "count" ] = 1;
  157.   Args[ "dirname" ] = ".";
  158.   Args[ "sepch" ] = ",";
  159.   Args[ "yflag" ] = "TRUE";
  160.  
  161.   rc = parseargs( ARGC-1, ARGV, ARGD, Args );
  162.   if ( rc != 0 )  exit( rc );
  163.  
  164.   ## print  the parsed arguments (use defaults if not defined)
  165.   print "ARGUMENTS:";
  166.   print "==========";
  167.  
  168.   for ( i in Args )
  169.     printf( "Args[\"%s\"] = \"%s\"\n", i, Args[i] );
  170.  
  171.   argc = split( Args[ "argv" ], argv, "\t" );
  172.   for ( i = 1 ; i <= argc ; i++ )
  173.     printf( "argv[%d] = \"%s\"\n", i, argv[i] );
  174.     
  175. }
  176.