#include <useful.h>
#include <parseargs.h>
#include <ctype.h>

#ifdef __STDC__
typedef void *pointer;
#else
typedef char *pointer;
#endif

extern pointer malloc();

#define ALL_AD		ad = argd; ad->ad_name != '\0'; ad++
#define ALL_DEFS	ad = _DefaultArgs; ad->ad_name != '\0'; ad++

extern char	*ProgName;

/*
**  ARGtype -- argument translation routines.
**
**	Each of these converts a parameter value to the internal form,
**	including validity checking.  Their parameters and return values
**	all behave identically.
**
**	Parameters:
**		ad -- the argument descriptor for this parameter.
**		vp -- a pointer to the string input value.
**		copyf -- if TRUE, the value will be destroyed later,
**			and so should be copied if it will be retained
**			(as for a string).
**
**	Returns:
**		TRUE -- if the conversion was successful.  The actual
**			value should be stored in the location indicated
**			by ad->ad_valp.
**		FALSE -- if the conversion failed.  The reason for failure
**			should be diagnosed using usrerr().
**
**	Side Effects:
**		The value should be stored through ad->ad_valp.
*/

BOOL
argStr(ad, vp, copyf)
	register ARGDESC *ad;
	register char *vp;
	BOOL copyf;
{
	char *cp;

	if (copyf)
	{
		register int i;

		i = strlen(vp) + 1;
		cp = (char *) malloc(i);
		if(!cp) {
			usrerr("out of memory parsing %s", ad->ad_prompt);
			return FALSE;
		}
		bcopy(vp, cp, i);
	}
	else
	{
		cp = vp;
	}
	*(char **) ad->ad_valp = cp;
	return (TRUE);
}

BOOL
argChar(ad, vp, copyf)
	register ARGDESC *ad;
	register char *vp;
	BOOL copyf;
{
	auto char *vpp;
	extern long strtol ARGS((char *, char **, int));
	int status = FALSE;
	char c;

	if (strlen(vp) == 2 && vp[0]=='^')
	{
		c = vp[1] ^ '@';
		status = TRUE;
	}
	else if(strlen(vp) > 1 && vp[0]=='\\')
	{
		c = (int) strtol(&vp[1], &vpp, 8);
		if (*vpp == '\0')
			status = TRUE;
	}
	else if(strlen(vp) == 1)
	{
		c = *vp;
		status = TRUE;
	}

	if(status == TRUE)
		*(char *) ad->ad_valp = c;
	else
	{
		usrerr("invalid character argument '%s' for %s",
			vp, ad->ad_prompt);
	}
	return status;
}

/*ARGSUSED*/
BOOL
argInt(ad, vp, copyf)
	register ARGDESC *ad;
	register char *vp;
	BOOL copyf;
{
	auto char *vpp;
	extern long strtol ARGS((char *, char **, int));

	*(int *) ad->ad_valp = (int) strtol(vp, &vpp, 0);
	if (*vpp != '\0')
	{
		usrerr("invalid integer argument '%s' for %s",
			vp, ad->ad_prompt);
		return (FALSE);
	}
	else
	{
		return (TRUE);
	}
}

/*ARGSUSED*/
BOOL
argShort(ad, vp, copyf)
	register ARGDESC *ad;
	register char *vp;
	BOOL copyf;
{
	auto char *vpp;
	extern long strtol ARGS((char *, char **, int));

	*(short *) ad->ad_valp = (short) strtol(vp, &vpp, 0);
	if (*vpp != '\0')
	{
		usrerr("invalid integer argument '%s' for %s",
			vp, ad->ad_prompt);
		return (FALSE);
	}
	else
	{
		return (TRUE);
	}
}

/*ARGSUSED*/
BOOL
argLong(ad, vp, copyf)
	register ARGDESC *ad;
	register char *vp;
	BOOL copyf;
{
	auto char *vpp;
	extern long strtol ARGS((char *, char **, int));

	*(long *) ad->ad_valp = strtol(vp, &vpp, 0);
	if (*vpp != '\0')
	{
		usrerr("invalid integer argument '%s' for %s",
			vp, ad->ad_prompt);
		return (FALSE);
	}
	else
	{
		return (TRUE);
	}
}

struct booltab
{
	char	*bname;		/* string to match against */
	char	bneedmatch;	/* number of characters that must match */
	BOOL	bval;		/* value to use */
};

STATIC struct booltab	_BoolTab[] =
{
	"yes",		1,	TRUE,
	"no",		1,	FALSE,
	"true",		1,	TRUE,
	"false",	1,	FALSE,
	"on",		2,	TRUE,
	"off",		3,	FALSE,
	CHARNULL
};

/*ARGSUSED*/
BOOL
argBool(ad, vp, copyf)
	register ARGDESC *ad;
	register char *vp;
	BOOL copyf;
{
	register struct booltab *b;
	register char *cp;
	int l;

	/* convert input to lower case */
	for (l = 0, cp = vp; *cp != '\0'; l++, cp++)
	{
		if (isupper(*cp))
			*cp = tolower(*cp);
	}

	/* search for a match in the table */
	for (b = _BoolTab; b->bname != CHARNULL; b++)
	{
		/* if too short, don't even bother trying */
		if (l < b->bneedmatch)
			continue;

		if (bcmp(vp, b->bname, l) == 0)
		{
			/* got a match */
			*(BOOL *) ad->ad_valp = b->bval;
			return (TRUE);
		}
	}

	usrerr("invalid Boolean argument '%s' for %s", vp, ad->ad_prompt);
	return (FALSE);
}

/*ARGSUSED*/
BOOL
argEnd(ad, vp, copyf)
	register ARGDESC *ad;
	register char *vp;
	BOOL copyf;
{
	return (FALSE);
}
