home *** CD-ROM | disk | FTP | other *** search
- /* getargs.c -- get command switch arguments */
- /* by Jim Mackraz, 1987. Placed in the public domain by the author */
-
- /*
- * getargs() -- parses switch arguements in argv[]
- * (a "switch argument" starts with SWITCHCHAR, normally '-')
- *
- * SYNOPSIS:
- * getargs( argv, argspec, numargs, prognameptr)
- * char **argv; -- as passed to main(), NULL terminated
- * struct Arg argspec[]; -- array specifying arguments expected
- * int numargs; -- elements in argspec[]
- * char **prognameptr -- if non-NULL, will put value of argv[0] here
- *
- * DESCRIPTION:
- * Parses argv for arguments of type: "-<char>" where 'char' is single
- * character followed by data
- * Types of arguments include integer, boolean, and string.
- * Boolean args, by there presence, are true, so their default should be
- * FALSE. They have no data part
- * Arguments with data can be provided with or without whitespace:
- * -i8 equiv. to -i 8 (integer)
- * -sfoo equiv. to -s foo (string)
- *
- * getargs() will call its internal argUsage() function to print
- * switch arguments usage, with descriptions gotten from argspec[].
- *
- * RETURNS:
- * If successful, returns amount argv incremented to get past "switch"
- * arguments. Errors are negative numbers, and defined in "getargs.h"
- *
- * WARNING:
- * For strings, this function only changes pointers to point to correct
- * places in **argv, so if argv storage is messed with, the strings
- * (including argv[0]) should be copied first. Also, the pointers
- * in argv[] are changed in the course of processing and so argv
- * cannot be reused. The arguments following the switch arguments
- * are not affected.
- */
-
- #include "getargs.h"
-
- #define D(x) ;
-
- /* this array synced to arg_type defines */
- char *argtypes[] = {
- "<integer>",
- " ",
- "<string>",
- };
-
- #define TEST 0
- #if TEST
-
- char *myprogname; /* set to argv[0] */
- int myint1 = 5;
- int mybool1 = 0;
- char *mystring = "Default String";
-
- struct Arg myargs[] = {
- {'i', ARG_TINT, &myint1, "generic integer argument"},
- {'b', ARG_TBOOL, &mybool1, "generic bool argument"},
- {'s', ARG_TSTRING, &mystring, "generic string argument"}
- };
-
-
- main(argc, argv)
- char **argv;
- {
- int argb;
-
- argb = getargs( argv, myargs, NUMARGS( myargs ), &myprogname);
-
- if (argb >= 0) argv += argb; /* bump argv to following arg */
- else exit (-argb);
-
- /** ALL DONE ARGS **/
- printf("progname %s, myint1 %d, mybool1 %d mystring %s\n",
- myprogname, myint1, mybool1, mystring);
-
- printf("getargs returned %d\n", argb);
- printf("next argv = %s\n", *argv? *argv: "NULL");
- }
- #endif TEST
-
- static char *pname;
-
- /*
- * returns number of times argv was incremented, else
- * negative number for error (see getargs.h)
- */
- getargs( argv, argspec, numargs, prognameptr)
- char **argv;
- struct Arg *argspec;
- int numargs;
- char **prognameptr; /* copy argv[0] here if non-null */
- {
- register struct Arg *aptr;
- char achar;
- int i;
- int argfound;
- int argbump = 0; /* count how many times ++argv */
-
- /* give him the command name (argv[0]) */
- pname = *argv;
- if (prognameptr) *prognameptr = pname;
-
- /* check argv until arg is not a switchchar */
- for (++argv, argbump++; *argv && (**argv == SWITCHCHAR); ++argv, argbump++)
- {
- achar = *(++(*argv)); /* first char following SWITCHCHAR */
- (*argv)++; /* second char after SWITCHCHAR */
-
- D( printf("checking for arg_char: 0x%x <%c>\n", achar, achar) );
- argfound = 0;
-
- /* run through args for (first) match */
- for (aptr = argspec, i = 0; i < numargs; ++i, ++aptr)
- {
- if ( aptr->arg_char == achar )
- {
- argfound = 1;
-
- /* all but bool args have arg data */
- /* check if data follows white space */
- if ( aptr->arg_type != ARG_TBOOL && **argv == '\0' )
- {
- argv++; /* point *argv to beginning of next arg */
- argbump++;
-
- if (!(*argv)) /* no more args, one expected */
- {
- D( printf("arg data not found\n") );
- argUsage( argspec, numargs );
- return (ARG_ENODATA);
- }
- }
-
- switch (aptr->arg_type)
- {
- case ARG_TINT:
- if (sscanf( *argv, "%d", aptr->arg_var) != 1)
- {
- D( printf("bad int: %s\n", *argv) );
- argUsage( argspec, numargs );
- return (ARG_EBADINT);
- }
- break;
-
- case ARG_TBOOL: /* arg exists => TRUE */
- *((int *) aptr->arg_var) = 1;
- break;
-
- case ARG_TSTRING:
- *( (char **) aptr->arg_var) = *argv;
- break;
-
- default:
- D( printf("unknown arg type\n") );
- argUsage( argspec, numargs );
- return (ARG_EBADTYPE);
- }
- }
- }
- if (!argfound)
- {
- D( printf("unknown argument\n") );
- argUsage( argspec, numargs );
- return (ARG_EUNKNOWN);
- }
- }
- return (argbump);
- }
-
-
- static argUsage( argspec, numargs)
- struct Arg argspec[];
- {
- int i;
-
- printf("%s argument usage:\n", pname);
- for (i = 0; i < numargs; ++i)
- {
- printf("\t%c%c %s\t - %s\n", SWITCHCHAR, argspec[i].arg_char,
- argtypes[argspec[i].arg_type], argspec[i].arg_descr);
- }
- }
-
-