# include	"../ingres.h"
# include	"../aux.h"
# include	"../symbol.h"
# include	"../tree.h"
# include	"../pipes.h"
# include	"ovqp.h"
/*
**	INTERP1.C
**
**	symbol I/O utility routines for OVQP interpreter.
**
*/

/*
** GETSYMBOL
**
**	Gets (type, len, value) symbols from list
**	A ptr to the list is advanced after
**	call.  Symbols are moved to a target location
**	(typically a slot on the interpreter's Stack).
**	Legality of symbol type and length is checked.
**	Returns		1  if no more symbols in list
**			0 otherwise
**
*/

getsymbol(ts, p)
struct symbol	*ts;		/* target location (on stack) */
struct symbol	***p;		/* pointer to list */
{
	int				len;	/*length of target symbol*/
	register char			*d;	/* ptr to data for target symbol */
	register char			*cp;	/* the item in the list */
	register struct stacksym	*tops;	/* target location on stack */

	tops = (struct stacksym *) ts;	/* copy stack pointer */
	cp = (char *) **p;		/* get list pointer */
#	ifdef xOTR1
	if(tTf(24, 0))
	{
		printf("GETSYM:");
		prsym(cp);
	}
#	endif

	if (((struct stacksym *)cp)->type == VAR || 
	    ((struct stacksym *)cp)->type == S_VAR)
	{
		tops->type = ((struct qt_v *)cp)->vtype;
		len = tops->len = ((struct qt_v *)cp)->vlen;
		d = (char *) ((struct qt_v *)cp)->vpoint;
	}
	else
	{
		tops->type = ((struct stacksym *)cp)->type;
		len = tops->len = ((struct stacksym *)cp)->len;
		len &= 0377;
		d = (char *) ((struct stacksym *)cp)->value;
	}
	/* advance Qvect sequencing pointer p */
	*p += 1;

	switch(tops->type)
	{
	  case INT:
		switch (len)
		{
		  case 1:
			*tops->value = *d;
			break;
		  case 2:
		  case 4:
			bmove(d, tops->value, len);
			break;

		  default:
			syserr("getsym:bad int len %d",len);
		}
		break;

	  case FLOAT:
		bmove(d, tops->value, len);
		if (len == 4)
			f8deref(tops->value) = f4deref(tops->value);	/* convert to double precision */
		else
			if (len != 8)
				syserr("getsym:bad FLOAT len %d",len);
		break;

	  case CHAR:
		cpderef(tops->value) = d;
		break;

	  case AOP:
	  case BOP:
	  case UOP:
	  case COP:
	  case RESDOM:
		/* all except aop are of length 1. aop is
		** length 6 but the first byte is the aop value
		*/
		*tops->value = *d & 0377;
		break;

	  case AND:
	  case OR:
		break;

	  case AGHEAD:
	  case BYHEAD:
	  case ROOT:
	  case QLEND:
		return (1);	/* all these are delimitors between lists */

	  default:
		syserr("getsym:bad type %d", tops->type);
	}
	return(0);
}



/*
*  TOUT
*
*	Copies a symbol value into the Output tuple buffer.
* 	Used to write target
*	list elements or aggregate values into the output tuple.
*/

tout(sp, offp, rlen)
struct symbol	*sp;
char		*offp;
{
	register struct symbol	*s;
	register int		i;
	register char		*p;
	int			slen;
	extern char		*bmove();

	s = sp;	/* copy pointer */

#	ifdef xOTR1
	if (tTf(24, 3))
	{
		printf("TOUT: s=");
		prstack(s);
		printf("  offset=%d, rlen=%d\n", offp-Outtup, rlen);
	}
#	endif
	if (s->type == CHAR)
	{
		slen = s->len & 0377;
		rlen &= 0377;
		i = rlen - slen;	/* compute difference between sizes */
		if (i <= 0)
			bmove(cpderef(s->value), offp, rlen);
		else
		{
			p = bmove(cpderef(s->value), offp, slen);
			while (i--)
				*p++ = ' ';	/* blank out remainder */
		}
	}
	else
	{
		bmove(s->value, offp, rlen);
	}
}



rcvt(tosp, restype, reslen)
struct symbol	*tosp;
int		restype, reslen;
{
	register struct symbol	*tos;
	register int		rtype, rlen;
	int			stype, slen;

	tos = tosp;
	rtype = restype;
	rlen = reslen;
	stype = tos->type;
	slen= tos->len;
#	ifdef xOTR1
	if (tTf(24, 6))
	{
		printf("RCVT:rt=%d, rl=%d, tos=", rtype, rlen);
		prstack(tos);
	}
#	endif

	if (rtype != stype)
	{
		if (rtype == CHAR || stype == CHAR)
			ov_err(BADCONV);	/* bad char to numeric conversion requested */
		if (rtype == FLOAT)
			itof(tos);
		else
		{
			if (rlen == 4)
				ftoi4(tos);
			else
				ftoi2(tos);
		}
		tos->len = rlen;	/* handles conversion to i1 or f4 */
	}

	else
		if (rtype != CHAR && rlen != slen)
		{
			if (rtype == INT)
			{
				if (rlen == 4)
					i2toi4(tos);
				else
					if (slen == 4)
						i4toi2(tos);
			}
			tos->len = rlen;	/* handles conversion to i1 or f4 */
		}
}
