/* getopt.c

   Yet another of the million of these.  Parse the arguments like
   the System V "getopt".

   There is a "man" page for it somewhere on Unix, but simply:

   Three arguments:

	1. Number of args (argc from the command line).
	2. Pointer to array of pointers to args. (argv)
	3. Switch/option string to parse.  String contains switch characters
	   optionally followed by a ':' if the switch requires an argument.

   Actions:
	1. The global value "optind" is set to the index of the next arg
	   to look at.
	2. The global value "optarg" is set to the value of an option that
	   needs one.  (i.e. "-f file" would set optarg to point to "file".)

   Returns:
	1. If an option not in the "opts" argument is found or an argument
	   to an option that requires one is not found return '?'.
	2. If we run off the end of the args or the end of the switches or
	   we see the "special" switches ('--' or '-'), return -1.
*/

#include <stdio.h>
#include <string.h>

int	optind = 1;		/* Externally visible Index into argv */
char	*optarg;		/* argument associated with option */
int	opterr = 1;		/* Print errors?  Default to yes. */

getopt(int argc,char **argv, char *opts)
{
    char *cp;
    int c;
    static char *next = "";

    if (!*next) {			/* Get more switches */
	/* if no more arguments at all or if this arg is not a switch, done. */
	if (optind >= argc || *(next = argv[optind]) != '-')
		return(-1);		/* then we are done parsing */

	/* if argument was '-' or '--', bump "optind" to next arg, then done */
	if (!*++next || *next == '-') {
	    optind++;
	    return(-1);
	}
    }
    /* Hidden in the tests above, "next" was set to point to next option char.
	If ':' shows up alone or cmd line option char is not found in option
	string, return the error character: '?'
    */
    if ((c = *next++) == ':' || !(cp = strchr (opts, c))) {
	if (!*next) optind++;		/* if no more options, move optind */
	if (opterr) fprintf(stderr, "%s:%c: illegal option\n", *argv, c);
	return('?');
    }
    if (*++cp != ':') {			/* No argument asked for */
	optarg = NULL;
	if (!*next) optind++;
    } else {				/* need an argument */
	if (*next)
	    optarg = next;		/* e.g. -lm -- argument is "m" */
	else {
	    optind++;
	    if (argc <= optind) {	/* No argument found */
		next = "";
		if (opterr) fprintf(stderr,"%s:%c: missing argument\n",*argv,c);
		return('?');
	    }
	    optarg = argv[optind];	/* e.g. -l m -- argument is "m" */
	}
	next = "";
	optind++;
    }
    return(c);
}
