/* vi: set tabstop=4 shiftwidth=4 */

/*
 * $Id: options.c,v 2.1 2005/06/17 20:48:15 schweikh Exp $
 */

#include <stdio.h>    /* EOF */
#include <string.h>   /* strchr */
#include "shutup.h"
#include "options.h"

/*
 * After get_opt returned EOF, argv[opt_ind] is the first non-option
 * argument (may be NULL). You can adjust main's argc and argv with
 * argc -= opt_ind; argv += opt_ind. All non-options args now are in
 * argv[0..argc] where argv[argc] is NULL. Note that argv[0] no longer
 * is the program's invocation name but the first non-option arg.
 * If you need the original argv[0] you can process the non-options
 * with for (i = opt_ind; i < argc; ++i) { f (argv[i]); }
 */

/*@+charintliteral@*/
/*@+charint@*/
/*@-ptrarith@*/

char *opt_arg;
int opt_err = 1; /* wheter we should diagnose invalid options */
int opt_opt;     /* last known option returned we have returned */

/*
 * opt_ind and subidx: together they
 * adress the next option character to process, i.e.
 * argv[opt_ind][subidx] is the next option char to use.
 * opt_ind starts at 1 because 0 is the program name,
 * subidx starts at 1 because 0 is the dash `-'.
 */
int opt_ind = 1;

	int
get_opt (int argc, char **argv, const char *optstring)
/*
 * Simple getopt replacement.
 */
{
	static size_t subidx = 1;
	char *opt;

	/* End of the argv array or first non-option reached? */
	if (opt_ind == argc || *argv[opt_ind] != '-') {
		return EOF; /* then we're finally done */
	}
	opt_opt = argv[opt_ind][subidx];
	if (opt_opt == 0) { /* found an unadorned `-' */
		return EOF;
	}
	opt = strchr (optstring, opt_opt);
	if (opt == NULL) { /* unknown option */
		if (opt_err != 0) {
			Fprintf (stderr, "illegal option -- %c\n", opt_opt);
		}
		++subidx;
		if (argv[opt_ind][subidx] == 0) { /* end of current arg reached */
			subidx = 1;
			++opt_ind;
		}
		return '?';
	} else { /* known option */
		if (opt[1] == ':') { /* takes an arg */
			if (argv[opt_ind][subidx + 1] != 0) { /* immediate arg */
				opt_arg = argv[opt_ind++] + subidx + 1;
				subidx = 1;
				return opt_opt;
			} else { /* arg is next element in argv[] */
				++opt_ind;
				if (argv[opt_ind] == NULL) { /* end of argv[] reached */
					if (opt_err != 0) {
						Fprintf (stderr,
						"option %c requires an argument\n", opt_opt);
					}
					return '?'; /* next call returns EOF */
				}
				if (argv[opt_ind][0] == '-' && argv[opt_ind][1] != 0) {
					/* arg is other than `-' by itself */
					if (opt_err != 0) {
						Fprintf (stderr,
						"option %c requires an argument\n", opt_opt);
					}
					subidx = 1;
					return '?';
				} else {
					opt_arg = argv[opt_ind++];
					subidx = 1;
					return opt_opt;
				}
			}
		} else { /* takes no arg */
			++subidx;
			if (argv[opt_ind][subidx] == 0) { /* end of current arg reached */
				subidx = 1;
				++opt_ind;
			}
			return opt_opt;
		}
	}
}


syntax highlighted by Code2HTML, v. 0.9.1