/*
 *
 * Copyright 1998-1999, University of Notre Dame.
 * Authors: Jeffrey M. Squyres, Kinis L. Meyer with M. D. McNally 
 *          and Andrew Lumsdaine
 *
 * This file is part of the Notre Dame LAM implementation of MPI.
 *
 * You should have received a copy of the License Agreement for the
 * Notre Dame LAM implementation of MPI along with the software; see
 * the file LICENSE.  If not, contact Office of Research, University
 * of Notre Dame, Notre Dame, IN 46556.
 *
 * Permission to modify the code and to distribute modified code is
 * granted, provided the text of this NOTICE is retained, a notice that
 * the code was modified is included with the above COPYRIGHT NOTICE and
 * with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
 * file is distributed with the modified code.
 *
 * LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
 * By way of example, but not limitation, Licensor MAKES NO
 * REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
 * PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
 * OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
 * OR OTHER RIGHTS.  
 *
 * Additional copyrights may follow.
 *
 *	Ohio Trollius
 *	Copyright 1996 The Ohio State University
 *	RBD
 *
 *	$Id: do_args.c,v 6.2 1999/05/23 19:22:15 kmeyer1 Exp $
 * 
 *	Function:	- do_args(3) backward compatibility
 *			- uses all_opt package
 */

#include <stdlib.h>

#include <all_opt.h>
#include <args.h>
#include <portable.h>
#include <terror.h>
#include <typical.h>

/*
 * global variables
 */
int			argtailc = 0;
char			**argtailv = 0;

/*
 * local variables
 */
static OPT		*optd = 0;		/* option descriptor */

/*
 * local functions
 */
static int		init();

/*
 *	validopts
 *
 *	Function:	- declare valid options
 *	Accepts:	- string of options
 */
void
validopts(str)

CONST char		*str;

{
	char		opt[2];

	if (str == 0) return;
	if (init()) return;
/*
 * Loop declaring the options.
 */
	for (opt[1] = '\0'; *str; ++str) {
		*opt = (*str == '0') ? '#' : *str;
		if (ao_setopt(optd, opt, (char *) 0, 0, AODOARGS)) return;
	}
}

/*
 *	exclusive
 *
 *	Function:	- declare mutex option group
 *	Accepts:	- string of options
 */
void
exclusive(str)

CONST char		*str;

{
	char		opt[2];
	char		first[2];

	if (str == 0) return;
	if (init()) return;
/*
 * Declare first option.
 */
	first[0] = *str++; first[1] = '\0';
	if (ao_setopt(optd, first, (char *) 0, 0, AODOARGS)) return;
/*
 * Declare the rest.
 */
	for (opt[1] = '\0'; *str; ++str) {
		*opt = *str;
		if (ao_setopt(optd, opt, first, 0, AODOARGS)) return;
	}
}

/*
 *	followed
 *
 *	Function:	- declare followed options
 *	Accepts:	- string of options
 */
void
followed(str)

CONST char		*str;

{
	char		opt[2];

	if (str == 0) return;
	if (init()) return;
/*
 * Declare the options.
 */
	for (opt[1] = '\0'; *str; ++str) {
		*opt = *str;
		if (ao_setopt(optd, opt, (char *) 0, 1, AODOARGS)) return;
	}
}

/*
 *	twoletter
 *
 *	Function:	- declare two-letter option group
 *	Accepts:	- string of options
 */
void
twoletter(str)

CONST char		*str;

{
	char		opt[3];

	if (str == 0) return;
	if (init()) return;
/*
 * Declare two-letter options.
 */
	opt[0] = *str++; opt[2] = '\0';

	if (*str == ':') ++str;

	for ( ; *str; ++str) {
		opt[1] = *str;
		if (ao_setopt(optd, opt, (char *) 0, 0, AODOARGS)) return;
	}
}

/*
 *	opt_taken
 *
 *	Function:	- check if option taken
 *	Accepts:	- letter
 *	Returns:	- TRUE or FALSE
 */
int
opt_taken(let)

int			let;

{
	char		opt[2];

	opt[0] = (let == '0') ? '#' : let & 0xFF;
	opt[1] = '\0';

	return(ao_taken(optd, opt));
}

/*
 *	opt_chosen
 *
 *	Function:	- get mutex chosen option
 *	Accepts:	- a mutex option
 *	Returns:	- chosen option
 */
int
opt_chosen(let)

int			let;

{
	char		opt[2];
	char		*chosen;

	opt[0] = let & 0xFF; opt[1] = '\0';

	chosen = ao_chosen(optd, opt);

	return((chosen) ? *chosen : LAMERROR);
}

/*
 *	do_args
 *
 *	Function:	- parse arguments
 *	Accepts:	- ptr argc
 *			- argv
 *	Returns:	- 0 or LAMERROR
 */
int
do_args(argc, argv)

int			*argc;
char			**argv;

{
	if (optd == 0) return(LAMERROR);

	if (ao_parse(optd, argc, argv)) return(LAMERROR);

	argtailc = optd->ao_tailc;
	argtailv = optd->ao_tailv;

	return(0);
}

/*
 *	getparam
 *
 *	Function:	- get followed option parameter
 *	Accepts:	- taken option
 *	Returns:	- parameter or NULL
 */
char *
getparam(let)

int			let;

{
	char		opt[2];

	opt[0] = (let == '0') ? '#' : let & 0xFF;
	opt[1] = '\0';

	return(ao_param(optd, opt, 0, 0));
}

/*
 *	intparam
 *
 *	Function:	- get followed option integer parameter
 *	Accepts:	- taken option
 *			- ptr integer (returned value)
 *	Returns:	- 0 or LAMERROR
 */
int
intparam(let, pint)

int			let;
int			*pint;

{
	char		*param;

	param = getparam(let);
	if (param == 0) return(LAMERROR);

	return(xtoi(&param, pint));
}

/*
 *	get_2nd_let
 *
 *	Function:	- get 2nd letter of next taken two-letter option
 *			- resets state of two-letter options along the way
 *			  to handle the stateful design of the call
 *			- messy, not opaque in order to keep all_args nice
 *	Accepts:	- first letter of two-letter option
 *	Returns:	- 2nd letter or LAMERROR
 */
int
get_2nd_let(let)

int			let;

{
	struct ao_opt	*p;
	

	for (p = optd->ao_opttop; p; p = p->aoo_next) {

		if ((p->aoo_string[0] == let) && (p->aoo_flags & AOTAKEN)) {
			p->aoo_flags &= ~AOTAKEN;
			return(p->aoo_string[1]);
		}
	}

	return(LAMERROR);
}

/*
 *	reset_args
 *
 *	Function:	- free the arguments
 */
void
reset_args()

{
	if (optd) {
		ao_free(optd);
		optd = 0;
	}

	argtailc = 0;
	argtailv = 0;
}

/*
 *	xtoi
 *
 *	Function:	- convert string to integer (base 10 or 16) 
 *			- uses strtol()
 *	Accepts:	- ptr string
 *			- ptr integer (returned value)
 *	Returns:	- 0 or LAMERROR
 */
int
xtoi(pstr, pint)

char			**pstr;
int			*pint;

{
	char		*str;

	if ((str = *pstr) == 0) {
		errno = EUSAGE;
		return(LAMERROR);
	}

	*pint = (int) strtol(str, pstr, 0);

	if ((*pint == 0) && (str == *pstr)) {
		errno = EBADASCIINUMB;
		return(LAMERROR);
	}

	return(0);
}

/*
 *	init
 *
 *	Function:	- create option descriptor if needed
 *	Returns:	- 0 or LAMERROR
 */
static int
init()

{
	if (optd == 0) {
		optd = ao_init();
	}

	return((optd) ? 0 : LAMERROR);
}
