home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / Reference / DevCon / Washington_1988 / DevCon88.1 / JimmDemos / DemoSource / getargs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  4.8 KB  |  189 lines

  1. /* getargs.c -- get command switch arguments    */
  2. /* by Jim Mackraz, 1987.  Placed in the public domain by the author */
  3.  
  4. /*
  5.  *        getargs() -- parses switch arguements in argv[]
  6.  *    (a "switch argument" starts with SWITCHCHAR, normally '-')
  7.  *
  8.  *    SYNOPSIS:
  9.  *  getargs( argv, argspec, numargs, prognameptr)
  10.  *     char    **argv;            -- as passed to main(), NULL terminated
  11.  *     struct Arg argspec[];    -- array specifying arguments expected
  12.  *     int        numargs;    -- elements in argspec[]
  13.  *     char    **prognameptr    -- if non-NULL, will put value of argv[0] here
  14.  *
  15.  *    DESCRIPTION:
  16.  *    Parses argv for arguments of type: "-<char>" where 'char' is single
  17.  *        character followed by data
  18.  *    Types of arguments include integer, boolean, and string.
  19.  *    Boolean args, by there presence, are true, so their default should be
  20.  *        FALSE.  They have no data part
  21.  *    Arguments with data can be provided with or without whitespace:
  22.  *        -i8 equiv. to -i 8    (integer)
  23.  *        -sfoo equiv. to -s foo    (string)
  24.  *
  25.  *    getargs() will call its internal argUsage() function to print
  26.  *    switch arguments usage, with descriptions gotten from argspec[].
  27.  *
  28.  *    RETURNS:
  29.  *    If successful, returns amount argv incremented to get past "switch"
  30.  *    arguments.  Errors are negative numbers, and defined in "getargs.h"
  31.  *
  32.  *    WARNING:
  33.  *    For strings, this function only changes pointers to point to correct
  34.  *    places in **argv, so if argv storage is messed with, the strings
  35.  *  (including argv[0]) should be copied first.  Also, the pointers
  36.  *    in argv[] are changed in the course of processing and so argv
  37.  *    cannot be reused.  The arguments following the switch arguments
  38.  *    are not affected.
  39.  */
  40.  
  41. #include "getargs.h"
  42.  
  43. #define D(x) ;
  44.  
  45. /* this array synced to arg_type defines    */
  46. char    *argtypes[] = {
  47.     "<integer>",
  48.     "         ",
  49.     "<string>",
  50. };
  51.  
  52. #define TEST 0
  53. #if TEST
  54.  
  55. char    *myprogname;        /* set to argv[0]    */
  56. int        myint1 = 5;
  57. int        mybool1 = 0;    
  58. char    *mystring = "Default String";
  59.  
  60. struct Arg    myargs[] = {
  61.     {'i', ARG_TINT, &myint1, "generic integer argument"},
  62.     {'b', ARG_TBOOL, &mybool1, "generic bool argument"},
  63.     {'s', ARG_TSTRING, &mystring, "generic string argument"}
  64. };
  65.  
  66.  
  67. main(argc, argv)
  68. char    **argv;
  69. {
  70.     int        argb;
  71.  
  72.     argb = getargs( argv, myargs, NUMARGS( myargs ), &myprogname);
  73.  
  74.     if (argb >= 0) argv += argb;        /* bump argv to following arg    */
  75.     else exit (-argb);
  76.  
  77.     /** ALL DONE ARGS    **/
  78.     printf("progname %s, myint1 %d, mybool1 %d mystring  %s\n",
  79.         myprogname, myint1, mybool1, mystring);
  80.  
  81.     printf("getargs returned %d\n", argb);
  82.     printf("next argv = %s\n", *argv? *argv: "NULL");
  83. }
  84. #endif TEST
  85.  
  86. static char    *pname;
  87.  
  88. /*
  89.  * returns number of times argv was incremented, else
  90.  * negative number for error (see getargs.h)
  91.  */
  92. getargs( argv, argspec, numargs, prognameptr)
  93. char    **argv;
  94. struct Arg    *argspec;
  95. int        numargs;
  96. char    **prognameptr;            /* copy argv[0] here if non-null    */
  97. {
  98.     register struct Arg    *aptr;
  99.     char     achar;
  100.     int        i;
  101.     int        argfound;
  102.     int        argbump = 0;        /* count how many times ++argv        */
  103.  
  104.     /* give him the command name (argv[0])    */
  105.     pname = *argv;
  106.     if (prognameptr) *prognameptr = pname;
  107.  
  108.     /* check argv until arg is not a switchchar    */
  109.     for (++argv, argbump++; *argv && (**argv == SWITCHCHAR); ++argv, argbump++)
  110.     {
  111.         achar = *(++(*argv));    /* first char following SWITCHCHAR    */
  112.         (*argv)++;                /* second char after SWITCHCHAR        */
  113.  
  114.         D( printf("checking for arg_char: 0x%x <%c>\n", achar, achar) );
  115.         argfound = 0;
  116.  
  117.         /* run through args for (first) match    */
  118.         for (aptr = argspec, i = 0; i < numargs; ++i, ++aptr)
  119.         {
  120.             if ( aptr->arg_char == achar )
  121.             {
  122.                 argfound = 1;
  123.  
  124.                 /* all but bool args have arg data    */
  125.                 /* check if data follows white space */
  126.                 if ( aptr->arg_type != ARG_TBOOL && **argv == '\0' )
  127.                 {
  128.                     argv++;        /* point *argv to beginning of next arg    */
  129.                     argbump++;
  130.  
  131.                     if (!(*argv))     /* no more args, one expected    */
  132.                     {
  133.                         D( printf("arg data not found\n") );
  134.                         argUsage( argspec, numargs );
  135.                         return (ARG_ENODATA);
  136.                     }
  137.                 }
  138.  
  139.                 switch (aptr->arg_type)
  140.                 {
  141.                 case ARG_TINT:
  142.                     if (sscanf( *argv, "%d", aptr->arg_var) != 1)
  143.                     {
  144.                         D( printf("bad int: %s\n", *argv) );
  145.                         argUsage( argspec, numargs );
  146.                         return (ARG_EBADINT);
  147.                     }
  148.                     break;
  149.  
  150.                 case ARG_TBOOL:        /* arg exists => TRUE    */
  151.                     *((int *) aptr->arg_var) = 1;
  152.                     break;
  153.  
  154.                 case ARG_TSTRING:
  155.                     *( (char **) aptr->arg_var) = *argv;
  156.                     break;
  157.  
  158.                 default:
  159.                     D( printf("unknown arg type\n") );
  160.                     argUsage( argspec, numargs );
  161.                     return (ARG_EBADTYPE);
  162.                 }
  163.             }
  164.         }
  165.         if (!argfound)
  166.         {
  167.             D( printf("unknown argument\n") );
  168.             argUsage( argspec, numargs );
  169.             return (ARG_EUNKNOWN);
  170.         }
  171.     }
  172.     return (argbump);
  173. }
  174.  
  175.  
  176. static argUsage( argspec, numargs)
  177. struct    Arg    argspec[];
  178. {
  179.     int        i;
  180.  
  181.     printf("%s argument usage:\n", pname);
  182.     for (i = 0; i < numargs; ++i)
  183.     {
  184.         printf("\t%c%c %s\t - %s\n", SWITCHCHAR, argspec[i].arg_char,
  185.             argtypes[argspec[i].arg_type], argspec[i].arg_descr);
  186.     }
  187. }
  188.  
  189.