home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume29 / parseargs / part03 / test.awk < prev    next >
Text File  |  1992-05-19  |  7KB  |  173 lines

  1. #!/usr/bin/awk -f
  2.  
  3. ##########################################################################
  4. ## ^FILE: test.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 toi 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. ##    Due to the limited ability of awk, scripts using parseargs(1) cannot
  63. ##    use short-options (with a  dash '-') because awk will attempt to interpret
  64. ##    any such arguments as options to awk and remove them from ARGV (regardless
  65. ##    of whether or not they are valid awk-options). Keyword options (with a
  66. ##    plus sign '+') may still be used without this difficulty. Dash-options
  67. ##    may be successfully processed if they did not first appear on the command
  68. ##    to the awk-script, so the full syntax of unix-style options could be 
  69. ##    provided in an array other than ARGV.
  70. ##
  71. ## ^ALGORITHM:
  72. ##    - set defaults for PROGNAME, PARSEOPTS, PARSEINPUT, and PARSEOUTPUT.
  73. ##    - build the parseargs command (dont forget to quote arguments).
  74. ##    - redirect input and output of the parseargs command.
  75. ##    - run parseargs(1)
  76. ##    - assign the exit-code from parseargs(1) to PARSESTATUS
  77. ##    - remove PARSEINPUT
  78. ##    - if PARSESTATUS != 0
  79. ##      - save RS and FS and reset RS = "" and FS = "\n"
  80. ##      - for each record in PARSEOUTPUT
  81. ##        - $1 is the argname and $2 is the value
  82. ##        - if $1 is "ARGV" reset ARGV and ARGC ($2 is a tab separated array)
  83. ##        - else assign arr[ $1 ] = $2
  84. ##      end-for
  85. ##      - restore RS and FS to previous values
  86. ##      - remove PARSEOUTPUT
  87. ##      - return PARSESTATUS
  88. ###^^####
  89.  
  90. function parseargs(argc, argv, argd, arr) {
  91.       ## set defaults -- use $$ to get a unique suffix string
  92.    if ( ! PROGNAME )     PROGNAME = ARGV[0];
  93.    if ( ! PARSEOPTS )    PARSEOPTS = "-u -l";
  94.  
  95.    "echo  ${TMP:-/tmp}/parseargs.${$}_"  |  getline TMPFILE;
  96.    if ( ! PARSEINPUT )   PARSEINPUT = TMPFILE "in";
  97.    if ( ! PARSEOUTPUT )  PARSEOUTPUT = TMPFILE "out";
  98.  
  99.       ## build the options and required arguments for parseargs(1)
  100.    PARSEARGS = sprintf( "parseargs -s awk %s -- '%s'", PARSEOPTS, PROGNAME );
  101.  
  102.       ## quote each elemnt in argv and append it to the parseargs-command
  103.    for ( i = 1 ; i <= argc ; i++ ) {
  104.       arg = argv[i];
  105.       gsub( /'/, "'\\''", arg );
  106.       PARSEARGS = PARSEARGS " '" arg "'";
  107.    }
  108.  
  109.       ## set up i/o redirection
  110.    PARSEARGS = PARSEARGS  " <" PARSEINPUT  " >" PARSEOUTPUT;
  111.    print  argd > PARSEINPUT;
  112.  
  113.       ## invoke parseargs(1) and save the status
  114.    PARSESTATUS = system( PARSEARGS );
  115.    system( "/bin/rm -f " PARSEINPUT );  ## dont need input anymore
  116.  
  117.       ## if successful status, read the result
  118.    if ( PARSESTATUS == 0 ) {
  119.       save_RS = RS; save_FS = FS;
  120.       RS = ""; FS = "\n";
  121.       while ( getline  < PARSEOUTPUT  > 0 ) {
  122.          gsub( /\034/, "\n" );
  123.          if ( $1 == "ARGV" ) {
  124.             ARGC = 1 + split( $2, ARGV, "\t" );
  125.             ARGV[0] = PROGNAME;
  126.          }
  127.          else  arr[ $1 ] = $2;
  128.       }
  129.       RS = save_RS; FS = save_FS;
  130.    }
  131.    system( "/bin/rm -f " PARSEOUTPUT );
  132.  
  133.    return  PARSESTATUS;
  134. }
  135.  
  136.  
  137. BEGIN {
  138.   PROGNAME = "test.awk";
  139.   ARGD = sprintf( "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s",
  140.     "'?', ARGHIDDEN, argUsage, NULL,    'Help : print usage and exit'" ,
  141.     "'S', ARGVALOPT, argStr,   string,  'STRing : optional string arg'" ,
  142.     "'g', ARGLIST,   argStr,   groups,  'newsGROUPS : groups to test'" ,
  143.     "'r', ARGOPT,    argInt,   count,   'REPcount : group repeat count'" ,
  144.     "'d', ARGOPT,    argStr,   dirname, 'DIRectory : working directory'" ,
  145.     "'x', ARGOPT,    argBool,  xflag,   'Xflag : turn on X-mode'" ,
  146.     "'y', ARGOPT,    argUBool, yflag,   'Yflag : turn off Y-mode'" ,
  147.     "'s', ARGOPT,    argChar,  sepch,   'SEPchar : field separator'" ,
  148.     "'f', ARGLIST,   argStr,   files,   'files : files to process'" ,
  149.     "'n', ARGREQ|ARGPOS, argStr, name,  'name : name to use'" ,
  150.     "' ', ARGLIST,   argStr,   argv,    'argv : any remaining arguments'" ,
  151.     "ENDOFARGS" );
  152.  
  153.   Args[ "count" ] = 1;
  154.   Args[ "dirname" ] = ".";
  155.   Args[ "sepch" ] = ",";
  156.   Args[ "yflag" ] = "TRUE";
  157.  
  158.   rc = parseargs( ARGC-1, ARGV, ARGD, Args );
  159.   if ( rc != 0 )  exit( rc );
  160.  
  161.   ## print  the parsed arguments (use defaults if not defined)
  162.   print "ARGUMENTS:";
  163.   print "==========";
  164.  
  165.   for ( i in Args )
  166.     printf( "Args[\"%s\"] = \"%s\"\n", i, Args[i] );
  167.  
  168.   argc = split( Args[ "argv" ], argv, "\t" );
  169.   for ( i = 1 ; i <= argc ; i++ )
  170.     printf( "argv[%d] = \"%s\"\n", i, argv[i] );
  171.     
  172. }
  173.