/* SDB - boolean expression evaluator / compiler */

#include "bdscio.h"
#include "dbqdefs.h"

/* The first section of code originated from sdbint.c */

int db_interpret(slptr)
	struct sel *slptr;
{
	struct operand *result;
	int r,inting;


	if ((cptr = slptr->sl_where) == NULL)
		return (TRUE);

	sptr = stack;
#ifdef COMDEB
		printf("com:interpret - entry\n");
#endif

/*		patch out original

	while ((*(*cptr++).c_operator)())
#ifdef COMDEB
		printf("com:interpret - cptr loop\n")
#endif
		;

end of patch		*/

	/* own version */

	inting = TRUE;		/* Set for loop */
	while (inting) {
#ifdef COMDEB
		printf("interpret - operator = %d\n",(*cptr).c_operator);
#endif
		switch ((*cptr++).c_operator) {
			case XPUSH:
				*sptr++ = (*cptr++).c_operand;
				break;
			case TKXAND:
				inting = boolean('&');
				break;
			case TKXOR:
				inting = boolean('|');
				break;
			case LSS:
				inting = compare(LSS);
				break;
			case LEQ:
				inting = compare(LEQ);
				break;
			case EQL:
				inting = compare(EQL);
				break;
			case CONT:
				inting = compcont();
				break;
			case GEQ:
				inting = compare(GEQ);
				break;
			case GTR:
				inting = compare(GTR);
				break;
			case NEQ:
				inting = compare(NEQ);
				break;
			case XNOT:
				inting = db_xnot();
				break;
			default:
				inting = FALSE;
			}
			
	}	/* end while cptr loop */
	result = *--sptr;
	r = result->o_value.ov_boolean;
	if (result->o_type == TEMP)
		CFREE(result);

	while (sptr != stack) {
#ifdef COMDEB
		printf("com:interpret - stack loop\n");
#endif
		if ((*sptr)->o_type == TEMP)
			CFREE(*sptr);
		sptr -= 1;
	}

	return (r);
}
/*	Patch out unwanted functions
int db_xstop()
{
	return (FALSE);
}

int db_xpush()
{
	*sptr++ = (*cptr++).c_operand;
}

int db_xand()
{
	return (boolean('&'));
}

int db_xor()
{
	return (boolean('|'));
}

int db_xlss()
{
	return (compare(LSS));
}

int db_xleq()
{
	return (compare(LEQ));
}

int db_xeql()
{
	return (compare(EQL));
}

int db_xgeq()
{
	return (compare(GEQ));
}


int db_xgtr()
{
	return (compare(GTR));
}

int db_xneq()
{
	return (compare(NEQ));
}

end of unwanted functions */

int boolean(opr)
{
	struct operand *lval,*rval,*result;
	int lv,rv,r;

	rval = *--sptr; lval = *--sptr;
	lv = lval->o_value.ov_boolean;
	rv = rval->o_value.ov_boolean;
	if ((result = CALLOC(OPSIZE)) == NULL)
		{ RETERR(INSMEM) }
	result->o_type = TEMP;
	switch (opr) {
	case '&':	r = (lv && rv);
			break;
	case '|':	r = (lv || rv);
			break;
	}
#ifdef COMDEB
	printf("com:bool lv=%d,rv=%d,r=%d\n",lv,rv,r);
#endif
	result->o_value.ov_boolean = r;
	*sptr++ = result;
	if (lval->o_type == TEMP)
		CFREE(lval);
	if (rval->o_type == TEMP)
		CFREE(rval);
	return (TRUE);
}

int db_xnot()
{
	struct operand *val,*result;

	val = *--sptr;
	if ((result = CALLOC(OPSIZE)) == NULL)
		{ RETERR(INSMEM) }
	result->o_type = TEMP;
	result->o_value.ov_boolean = !val->o_value.ov_boolean;
	*sptr++ = result;
	if (val->o_type == TEMP)
		CFREE(val);
	return (TRUE);
}

int compare(cmp)
{
	struct operand *lval,*rval,*result;
	int i;

	rval = *--sptr; lval = *--sptr;
	if ((result = CALLOC(OPSIZE)) == NULL)
		{ RETERR(INSMEM) }
	result->o_type = TEMP;

	if (lval->o_value.ov_char.ovc_type == TCHAR)
		i = comp(lval,rval);
	else
		i = ncomp(lval,rval);
#ifdef COMDEB
	printf("com:compare - cmp=%d\n",cmp);
#endif
	switch (cmp) {
	case LSS:	i = (i < 0);
			break;
	case LEQ:	i = (i <= 0);
			break;
	case EQL:	i = (i == 0);
			break;
	case GEQ:	i = (i >= 0);
			break;
	case GTR:	i = (i > 0);
			break;
	case NEQ:	i = (i != 0);
			break;
	}
	result->o_value.ov_boolean = i;
	*sptr++ = result;
	if (lval->o_type == TEMP)
		CFREE(lval);
	if (rval->o_type == TEMP)
		CFREE(rval);
	return (TRUE);
}

int compcont(cmp)
{
	struct operand *lval,*rval,*result;
	int i;

	rval = *--sptr; lval = *--sptr;
	if ((result = CALLOC(OPSIZE)) == NULL)
		{ RETERR(INSMEM) }
	result->o_type = TEMP;

	i = contains(lval,rval);

/*	printf("i after contains = %d\n",i);	*/

	result->o_value.ov_boolean = i;
	*sptr++ = result;
	if (lval->o_type == TEMP)
		CFREE(lval);
	if (rval->o_type == TEMP)
		CFREE(rval);
	return (TRUE);
}

int contains(lval,rval)
struct operand *lval,*rval;
{
	char *lptr,*rptr;
	int lctr,rctr;
	int len;

	lptr = lval->o_value.ov_char.ovc_string;
	lctr = lval->o_value.ov_char.ovc_length;
	rptr = rval->o_value.ov_char.ovc_string;
	rctr = rval->o_value.ov_char.ovc_length;

	while (lctr > 0 && (lptr[lctr-1] == 0 || lptr[lctr-1] == ' '))
		lctr--;
	while (rctr > 0 && (rptr[rctr-1] == 0 || rptr[rctr-1] == ' '))
		rctr--;

/*	printf("lctr = %d, rctr = %d\n",lctr,rctr);	*/
	
	if (lctr < rctr)
		return(FALSE);
	else
		len = rctr;

/*	printf("length = %d\n",len);	*/

	while (lctr >= rctr) {
		if(db_sncmp(lptr,rptr,rctr) == 0) return(TRUE);
/*	printf("forloop - lptr = %s\n",lptr);		*/
		lptr++;
		lctr--;
		}
/*	printf("out of for loop\n");	*/
	return (FALSE);
}

int comp(lval,rval)
	struct operand *lval,*rval;
{
	char *lptr,*rptr; int lctr,rctr;
	int len;

	lptr = lval->o_value.ov_char.ovc_string;
	lctr = lval->o_value.ov_char.ovc_length;
	rptr = rval->o_value.ov_char.ovc_string;
	rctr = rval->o_value.ov_char.ovc_length;
#ifdef COMDEB
	printf("com:comp - lptr = %d,%d,%d,%d\n",lptr[6],lptr[7],lptr[8],lptr[9]);
#endif
	while (lctr > 0 && (lptr[lctr-1] == 0 || lptr[lctr-1] == ' '))
		lctr--;
	while (rctr > 0 && (rptr[rctr-1] == 0 || rptr[rctr-1] == ' '))
		rctr--;

	if (lctr < rctr)
		len = lctr;
	else
		len = rctr;
#ifdef COMDEB
	printf("com:comp - lctr=%d,rctr=%d\n",lctr,rctr);
#endif

	while ((len--) > 0) {
		if (*lptr++ != *rptr++)
			if (*--lptr < *--rptr)
				return (-1);
			else
				return (1);
	}
	if (lctr == rctr)
		return (0);
	else if (lctr < rctr)
		return (-1);
	else
		return (1);

/*	return(db_sncmp(lptr,rptr,len));	*/
}

int ncomp(lval,rval)
	struct operand *lval,*rval;
{
	char lstr[NUMBERMAX+1],rstr[NUMBERMAX+1];
	int len;

	strncpy(lstr,lval->o_value.ov_char.ovc_string,
		(len = lval->o_value.ov_char.ovc_length)); lstr[len] = EOS;

	strncpy(rstr,rval->o_value.ov_char.ovc_string,
		(len = rval->o_value.ov_char.ovc_length)); rstr[len] = EOS;


	return (db_cmp(lstr,rstr));
}

/* The following originated from com.c */


int db_compile(slptr)
	struct sel *slptr;
{
	int result,i;
	union codecell *cptr;
	int (*dns)();

#ifdef COMDEB
	printf("com:compile - entry\n");
#endif

	selptr = slptr;

	cndx = 0;

	if (!expr(&result)) {
#ifdef COMDEB
		printf("com:compile - expr-error = %d\n",dbv_errcode);
#endif
		code[cndx++].c_operator = XSTOP;
		freelit(code);
		return (FALSE);
	}
#ifdef COMDEB
	printf("com:compile - after expr call\n");
#endif
	code[cndx++].c_operator = XSTOP;

	if ((cptr = CALLOC(CELLSIZE * cndx)) == NULL) {
		freelit(code);
		return(FALSE);
	}

	slptr->sl_where = cptr;
	for (i = 0; i < cndx; i++) {
#ifdef COMDEB
		printf("com.compile - i = %d, op = %d\n",i,code[i].c_operator);
#endif

		(*cptr++).c_operator = code[i].c_operator;
		if (code[i].c_operator == XPUSH)
			(*cptr++).c_operand = code[++i].c_operand;
	}

	return (TRUE);
}

db_fcode(slptr)
	struct sel *slptr;
{
#ifdef COMDEB
	printf("com:fcode - entry\n");
#endif
	if (slptr->sl_where == NULL)
		return;

	freelit(slptr->sl_where);

	CFREE(slptr->sl_where);
}

int operator(opr)
	int *opr;
{
#ifdef COMDEB
	printf("com:operator - entry\n");
#endif
	if (cndx < CODEMAX)
		code[cndx++].c_operator = opr;
	else
		{ RETERR(CDSIZE) }

	return (TRUE);
}

int oprand(opr)
	struct operand *opr;
{
#ifdef COMDEB
	printf("com:oprand - entry\n");
#endif
	if (!operator(XPUSH))
		return (FALSE);

	if (cndx < CODEMAX)
		code[cndx++].c_operand = opr;
	else
		{ RETERR(CDSIZE) }

	return (TRUE);
}

int expr(result)
	int *result;
{
	int lval,rval;
#ifdef COMDEB
	printf("com:expr - entry\n");
#endif
	if (!land(&lval))
		return (FALSE);
	while (db_token() == '|') {
		db_ntoken();
		if (!land(&rval))
			return (FALSE);
		if (!operator(TKXOR))
			return (FALSE);
	}
	*result = lval;
	return (TRUE);
}

int land(result)
	int *result;
{
	int lval,rval;
#ifdef COMDEB
	printf("com:land - entry\n");
#endif
	if (!relat(&lval))
		return (FALSE);
	while (db_token() == '&') {
		db_ntoken();
		if (!relat(&rval))
			return (FALSE);
		if (!operator(TKXAND))
			return (FALSE);
	}
	*result = lval;
	return (TRUE);
}

int relat(result)
	int *result;
{
	int lval,rval;
	int tkn;
#ifdef COMDEB
	printf("com:relat - entry\n");
#endif
	if (!primary(&lval))
		return (FALSE);
	while (db_token() <= LSS && dbv_token >= GTR) {
		tkn = db_ntoken();
#ifdef COMDEB
		printf("com:relat - tkn = %d\n",tkn);
#endif
		if (!primary(&rval))
			return (FALSE);
		if (!operator(tkn))
			return (FALSE);
	}
	*result = lval;
	return (TRUE);
}

int primary(result)
	int *result;
{
	int val;
	int tkn;
#ifdef COMDEB
	printf("com:primary - entry\n");
#endif
	if (db_token() == '~') {
		tkn = db_ntoken();
		if (!primary(&val))
			return (FALSE);
		switch (tkn) {
		case '~':
			if (!operator(XNOT))
				return (FALSE);
			break;
		}
	}
	else
		if (!factor(&val))
			return (FALSE);
	*result = val;
	return (TRUE);
}

int factor(result)
	int *result;
{
	int val;
#ifdef COMDEB
	printf("com:factor - entry");
#endif
	if (db_token() == '(') {
		db_ntoken();
		if (!expr(&val))
			return (FALSE);
		if (db_token() != ')')
			{ RETERR(SYNTAX) }
		db_ntoken();
	}
	else
		if (!get_operand(&val))
			return (FALSE);
		*result = val;
		return (TRUE);
}


int get_operand(result)
	int *result;
{
#ifdef COMDEB
	printf("com:getoper - entry\n");
#endif
	if (db_ntoken() == NUMBER)
		return (get_thing(result,TNUM));
	else if (dbv_token == ID)
		return (get_attr(result));
	else if (dbv_token == STRING)
		return (get_thing(result,TCHAR));
	else
		{ RETERR(SYNTAX) }
}

int get_attr(result)
	int *result;
{
	struct operand *opr;
	char rname[RNSIZE+1],aname[ANSIZE+1];
	char *aptr; int atype,alen;

	strncpy(aname,dbv_tstring,ANSIZE); aname[ANSIZE] = EOS;

	if (db_token() == '.') {
		db_ntoken();

		strcpy(rname,aname);

		if (db_ntoken() != ID)
			{ RETERR(SYNTAX) }

		strncpy(aname,dbv_tstring,ANSIZE); aname[ANSIZE] = EOS;

		if (!db_sattr(selptr,rname,aname,&atype,&aptr,&alen))
			return (FALSE);

	}
	else
		if (!db_sattr(selptr,NULL,aname,&atype,&aptr,&alen))
			return (FALSE);

	if ((opr = CALLOC(OPSIZE)) == NULL)
		{ RETERR(INSMEM) }

	opr->o_type = ATTR;
	opr->o_value.ov_char.ovc_type = atype;
	opr->o_value.ov_char.ovc_string = aptr;
	opr->o_value.ov_char.ovc_length = alen;

	if (!oprand(opr)) {
		CFREE(opr);
		return (FALSE);
	}

	*result = atype;

	return (TRUE);
}





int get_thing(result,tipe)
	int *result; int tipe;
{
	struct operand *opr;
#ifdef COMDEB
	printf("com:getthing\n");
#endif
	if ((opr = CALLOC(OPSIZE)) == NULL)
		{ RETERR(INSMEM) }

	opr->o_type = LITERAL;
	if ((opr->o_value.ov_char.ovc_string =
		CALLOC(strlen(dbv_tstring)+1)) == NULL) {
		CFREE(opr);
		RETERR(INSMEM)
	}
	opr->o_value.ov_char.ovc_type = tipe;
	strcpy(opr->o_value.ov_char.ovc_string,dbv_tstring);
	opr->o_value.ov_char.ovc_length = strlen(dbv_tstring);

	if (!oprand(opr)) {
		CFREE(opr->o_value.ov_char.ovc_string); CFREE(opr);
		return (FALSE);
	}

	*result = tipe;

	return (TRUE);
}

freelit(cptr)
	union codecell *cptr;
{
	int catch;
#ifdef COMDEB
	printf("com:freelit - entry\n");
#endif
	for (catch = 0; ((*cptr).c_operator != XSTOP) && (catch < CODEMAX); cptr++, catch++)
		{
#ifdef COMDEB
		printf("com:freelit - op = %d, ty = %d\n",(*cptr).c_operator,
				(*cptr).c_operand->o_type);
#endif
		if ((*cptr).c_operator == XPUSH) {
			if ((*++cptr).c_operand->o_type == LITERAL)
			   CFREE((*cptr).c_operand->o_value.ov_char.ovc_string);
			CFREE((*cptr).c_operand); }
		}
#ifdef COMDEB
	printf("exit\n");
#endif
}
r).c_operand->o_value.ov