/* transcript/src/getopt.c
 *
 * public domain getopt from mod.sources
 * RCSID: $Header: getopt.c,v 2.1 85/11/24 11:49:10 shore Rel $
 */

/*
**  This is a public domain version of getopt(3).
**  Bugs, fixes to:
**		Keith Bostic
**			ARPA: keith@seismo
**			UUCP: seismo!keith
**  Added NO_STDIO, opterr handling, Rich $alz (mirror!rs).
*/

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

/*
**  Error macro.  Maybe we want stdio, maybe we don't.
**  The (undocumented?) variable opterr tells us whether or not
**  to print errors.
*/

#ifdef	NO_STDIO

#define tell(s)								\
	if (opterr)							\
	{								\
	    char	ebuf[2];					\
	    (void)write(2, nargv, (unsigned int)strlen(nargv));		\
	    (void)write(2, s, (unsigned int)strlen(s));			\
	    ebuf[0] = optopt;						\
	    ebuf[1] = '\n';						\
	    (void)write(2, ebuf, 2);					\
	}

#else

#define tell(s)								\
	if (opterr)							\
	    (void)fputs(*nargv, stderr),				\
	    (void)fputs(s,stderr),					\
	    (void)fputc(optopt, stderr),				\
	    (void)fputc('\n', stderr)

#endif


/* Global variables. */
static char	 EMSG[] = "";
int		 opterr = 1;		/* undocumented error-suppressor*/
int		 optind = 1;		/* index into argv vector	*/
int		 optopt;		/* char checked for validity	*/
char		*optarg;		/* arg associated with option	*/



getopt(nargc, nargv, ostr)
    int			  nargc;
    char		**nargv;
    char		 *ostr;
{
    static char		 *place = EMSG;	/* option letter processing	*/
    register char	 *oli;		/* option letter list index	*/

    if (!*place)			/* update scanning pointer	*/
    {
	if (optind >= nargc || *(place = nargv[optind]) != '-' || !*++place)
	    return(EOF);
	if (*place == '-')		/* found "--"			*/
	{
	    optind++;
	    return(EOF);
	}
    }
    /* option letter okay? */
    if ((optopt = *place++) == ':' || (oli = strchr(ostr, optopt)) == NULL)
    {
	if (!*place)
	    optind++;
	tell(": illegal option -- ");
	goto Bad;
    }
    if (*++oli != ':')			/* don't need argument		*/
    {
	optarg = NULL;
	if (!*place)
	    optind++;
    }
    else				/* need an argument		*/
    {
	if (*place)
	    optarg = place;		/* no white space		*/
	else
	    if (nargc <= ++optind)
	    {
		place = EMSG;
		tell(": option requires an argument -- ");
		goto Bad;
	    }
	    else
		optarg = nargv[optind];	/* white space			*/
	place = EMSG;
	optind++;
    }
    return(optopt);			/* dump back option letter	*/
Bad:
    return('?');
}
