#ifndef lint
static char *RCSid = "$Header: /usr/brule/guest/empire/empire/emprcs/lib/subs/nstr.c,v 2.0 1995/01/25 19:58:54 empire Exp $";
#endif

/*
 * nstr.c
 *
 * compile and execute the item selections
 * on sectors.
 *
 * Dave Pare, 1989
 */

#include <ctype.h>
#include "struct.h"
#include "misc.h"
#include "var.h"
#include "xy.h"
#include "sect.h"
#include "nsc.h"
#include "nat.h"
#include "match.h"
#include "file.h"
#include "player.h"

/*
 * Compiles and adds "str" to the list of conditionals.
 * type is the EF typename of the item type we're selecting.
 * returns amount of "str" used by nstr_comp (i.e. how far
 * the pointer was advanced).  The last is only meaningful
 * if several conditionals are expected in one string.
 */
s_char *
nstr_comp(np, size, type, str)
	struct	nscstr *np;
	int	*size;
	int	type;
	s_char	*str;
{
	register s_char *bp;
	register s_char *cp;
	register int c;
	s_char	ident[80];
	s_char	arg[255];

	strncpy(arg, str, sizeof(arg)-1);
	arg[sizeof(arg)-1] = 0;
	cp = arg;
	bp = ident;
	while ((c = *cp++) && bp < &ident[sizeof(ident)-1]) {
		if (c == '<' || c == '=' || c == '>' || c == '#')
			break;
		*bp++ = c;
	}
	*bp = 0;
	if (c == 0) {
		pr("'%s'? -- meaningless condition?\n", arg);
		return 0;
	}
	np[*size].oper = c;
	if (encode(ident, &np[*size].fld1, type) < 0)
		return 0;
	bp = ident;
	while ((c = *cp++) && bp < &ident[sizeof(ident)-1]) {
		if (c == '&')
			break;
		*bp++ = c;
	}
	*bp = 0;
	if (encode(ident, &np[*size].fld2, type) < 0)
		return 0;
	if (c == 0)
		cp--;
	(*size)++;
	return str + (cp - arg);
}

int
encode(str, val, type)
	register s_char *str;
	long	*val;
	int	type;
{
	register int i;
	struct	castr *cap;

	if (str == 0) {
		*val = 0;
		return 0;
	}
	if (isdigit(*str) || *str == '-' && isdigit(str[1])) {
		/* XXX silently truncate to 16 bit int */
		*val = atoi(str) & 0xffff;
		return 1;
	}
	if ((i = typematch(str, type)) >= 0) {
		*val = i;
		return 1;
	}
	if ((cap = ef_cadef(type)) != 0) {
		i = stmtch(str, (caddr_t)cap, fldoff(castr, ca_name),
			sizeof(struct castr));
		if (i >= 0) {
			*val = cap[i].ca_code|NSC_OFF;
			*val &= ~NSC_ROUND;
			return legal_val(str, *val);
		}
		if (i == M_NOTUNIQUE) {
			pr("%s -- ambiguous type selector\n", str);
			return 0;
		}
	}
	/*
	 * Only check for commodity selectors on objects which
	 * are allowed to have commodities.
	 */
	if (ef_flags(type) & EFF_COM) {
		i = stmtch(str, (caddr_t)var_ca, fldoff(castr, ca_name),
			sizeof(struct castr));
		if (i >= 0) {
			*val = var_ca[i].ca_code & ~NSC_ROUND;
			return legal_val(str, *val);
			return 1;
		}
		if (i == M_NOTUNIQUE) {
			pr("%s -- ambiguous commodity selector\n", str);
			return 0;
		}
	}
	pr("%s -- not a valid selector\n", str);
	return 0;
}

static int
legal_val(str, val)
	s_char	*str;
	int	val;
{
	if (val & NSC_DEITY && !player->god) {
		pr("%s -- permission denied\n", str);
		return 0;
	}
	return 1;
}


/*
 * The rest of this stuff has been moved to libcommon
 * so it can be used elsewhere (emp_update, mostly)
 */
