Blame src/cmd/ksh93/sh/streval.c

Packit Service a8c26c
/***********************************************************************
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
*               This software is part of the ast package               *
Packit Service a8c26c
*          Copyright (c) 1982-2012 AT&T Intellectual Property          *
Packit Service a8c26c
*                      and is licensed under the                       *
Packit Service a8c26c
*                 Eclipse Public License, Version 1.0                  *
Packit Service a8c26c
*                    by AT&T Intellectual Property                     *
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
*                A copy of the License is available at                 *
Packit Service a8c26c
*          http://www.eclipse.org/org/documents/epl-v10.html           *
Packit Service a8c26c
*         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
*              Information and Software Systems Research               *
Packit Service a8c26c
*                            AT&T Research                             *
Packit Service a8c26c
*                           Florham Park NJ                            *
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
*                  David Korn <dgk@research.att.com>                   *
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
***********************************************************************/
Packit Service a8c26c
#pragma prototyped
Packit Service a8c26c
Packit Service a8c26c
/*
Packit Service a8c26c
 * D. G. Korn
Packit Service a8c26c
 * AT&T Labs
Packit Service a8c26c
 *
Packit Service a8c26c
 * arithmetic expression evaluator
Packit Service a8c26c
 *
Packit Service a8c26c
 * this version compiles the expression onto a stack
Packit Service a8c26c
 *	 and has a separate executor
Packit Service a8c26c
 */
Packit Service a8c26c
Packit Service a8c26c
#include	"streval.h"
Packit Service a8c26c
#include	<ctype.h>
Packit Service a8c26c
#include	<error.h>
Packit Service a8c26c
#include	<stak.h>
Packit Service a8c26c
#include	"FEATURE/externs"
Packit Service a8c26c
#include	"defs.h"	/* for sh.decomma */
Packit Service a8c26c
Packit Service a8c26c
#ifndef ERROR_dictionary
Packit Service a8c26c
#   define ERROR_dictionary(s)	(s)
Packit Service a8c26c
#endif
Packit Service a8c26c
#ifndef SH_DICT
Packit Service a8c26c
#   define SH_DICT	"libshell"
Packit Service a8c26c
#endif
Packit Service a8c26c
Packit Service a8c26c
#define MAXLEVEL	9
Packit Service a8c26c
#define SMALL_STACK	12
Packit Service a8c26c
Packit Service a8c26c
/*
Packit Service a8c26c
 * The following are used with tokenbits() macro
Packit Service a8c26c
 */
Packit Service a8c26c
#define T_OP		0x3f		/* mask for operator number */
Packit Service a8c26c
#define T_BINARY	0x40		/* binary operators */
Packit Service a8c26c
#define T_NOFLOAT	0x80		/* non floating point operator */
Packit Service a8c26c
#define A_LVALUE	(2*MAXPREC+2)
Packit Service a8c26c
Packit Service a8c26c
#define pow2size(x)		((x)<=2?2:(x)<=4?4:(x)<=8?8:(x)<=16?16:(x)<=32?32:64)
Packit Service a8c26c
#define round(x,size)		(((x)+(size)-1)&~((size)-1))
Packit Service a8c26c
#define stakpush(v,val,type)	((((v)->offset=round(staktell(),pow2size(sizeof(type)))),\
Packit Service a8c26c
				stakseek((v)->offset+sizeof(type)), \
Packit Service a8c26c
				*((type*)stakptr((v)->offset)) = (val)),(v)->offset)
Packit Service a8c26c
#define roundptr(ep,cp,type)	(((unsigned char*)(ep))+round(cp-((unsigned char*)(ep)),pow2size(sizeof(type))))
Packit Service a8c26c
Packit Service a8c26c
static int level;
Packit Service a8c26c
Packit Service a8c26c
struct vars				/* vars stacked per invocation */
Packit Service a8c26c
{
Packit Service a8c26c
	Shell_t		*shp;
Packit Service a8c26c
	const char	*expr;		/* current expression */	
Packit Service a8c26c
	const char	*nextchr;	/* next char in current expression */	
Packit Service a8c26c
	const char	*errchr; 	/* next char after error	*/
Packit Service a8c26c
	const char	*errstr;	/* error string			*/
Packit Service a8c26c
	struct lval	errmsg;	 	/* error message text		*/
Packit Service a8c26c
	int		offset;		/* offset for pushchr macro	*/
Packit Service a8c26c
	int		staksize;	/* current stack size needed	*/
Packit Service a8c26c
	int		stakmaxsize;	/* maximum stack size needed	*/
Packit Service a8c26c
	unsigned char	paren;	 	/* parenthesis level		*/
Packit Service a8c26c
	char		infun;	/* incremented by comma inside function	*/
Packit Service a8c26c
	int		emode;
Packit Service a8c26c
	Sfdouble_t	(*convert)(const char**,struct lval*,int,Sfdouble_t);
Packit Service a8c26c
};
Packit Service a8c26c
Packit Service a8c26c
typedef Sfdouble_t (*Math_f)(Sfdouble_t,...);
Packit Service a8c26c
typedef Sfdouble_t (*Math_1f_f)(Sfdouble_t);
Packit Service a8c26c
typedef int	   (*Math_1i_f)(Sfdouble_t);
Packit Service a8c26c
typedef Sfdouble_t (*Math_2f_f)(Sfdouble_t,Sfdouble_t);
Packit Service a8c26c
typedef Sfdouble_t (*Math_2f_i)(Sfdouble_t,int);
Packit Service a8c26c
typedef int        (*Math_2i_f)(Sfdouble_t,Sfdouble_t);
Packit Service a8c26c
typedef Sfdouble_t (*Math_3f_f)(Sfdouble_t,Sfdouble_t,Sfdouble_t);
Packit Service a8c26c
typedef int        (*Math_3i_f)(Sfdouble_t,Sfdouble_t,Sfdouble_t);
Packit Service a8c26c
Packit Service a8c26c
#define getchr(vp)	(*(vp)->nextchr++)
Packit Service a8c26c
#define peekchr(vp)	(*(vp)->nextchr)
Packit Service a8c26c
#define ungetchr(vp)	((vp)->nextchr--)
Packit Service a8c26c
Packit Service a8c26c
#if ('a'==97)	/* ASCII encodings */
Packit Service a8c26c
#   define getop(c)	(((c) >= sizeof(strval_states))? \
Packit Service a8c26c
				((c)=='|'?A_OR:((c)=='^'?A_XOR:((c)=='~'?A_TILDE:A_REG))):\
Packit Service a8c26c
				strval_states[(c)])
Packit Service a8c26c
#else
Packit Service a8c26c
#   define getop(c)	(isdigit(c)?A_DIG:((c==' '||c=='\t'||c=='\n'||c=='"')?0: \
Packit Service a8c26c
			(c=='<'?A_LT:(c=='>'?A_GT:(c=='='?A_ASSIGN: \
Packit Service a8c26c
			(c=='+'?A_PLUS:(c=='-'?A_MINUS:(c=='*'?A_TIMES: \
Packit Service a8c26c
			(c=='/'?A_DIV:(c=='%'?A_MOD:(c==','?A_COMMA: \
Packit Service a8c26c
			(c=='&'?A_AND:(c=='!'?A_NOT:(c=='('?A_LPAR: \
Packit Service a8c26c
			(c==')'?A_RPAR:(c==0?A_EOF:(c==':'?A_COLON: \
Packit Service a8c26c
			(c=='?'?A_QUEST:(c=='|'?A_OR:(c=='^'?A_XOR: \
Packit Service a8c26c
			(c=='\''?A_LIT: \
Packit Service a8c26c
			(c=='.'?A_DOT:(c=='~'?A_TILDE:A_REG)))))))))))))))))))))))
Packit Service a8c26c
#endif
Packit Service a8c26c
Packit Service a8c26c
#define seterror(v,msg)		_seterror(v,ERROR_dictionary(msg))
Packit Service a8c26c
#define ERROR(vp,msg)		return(seterror((vp),msg))
Packit Service a8c26c
Packit Service a8c26c
/*
Packit Service a8c26c
 * set error message string and return(0)
Packit Service a8c26c
 */
Packit Service a8c26c
static int _seterror(struct vars *vp,const char *msg)
Packit Service a8c26c
{
Packit Service a8c26c
	if(!vp->errmsg.value)
Packit Service a8c26c
		vp->errmsg.value = (char*)msg;
Packit Service a8c26c
	vp->errchr = vp->nextchr;
Packit Service a8c26c
	vp->nextchr = "";
Packit Service a8c26c
	level = 0;
Packit Service a8c26c
	return(0);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
Packit Service a8c26c
static void arith_error(const char *message,const char *expr, int mode)
Packit Service a8c26c
{
Packit Service a8c26c
        level = 0;
Packit Service a8c26c
	mode = (mode&3)!=0;
Packit Service a8c26c
        errormsg(SH_DICT,ERROR_exit(mode),message,expr);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
#if _ast_no_um2fm
Packit Service a8c26c
static Sfdouble_t U2F(Sfulong_t u)
Packit Service a8c26c
{
Packit Service a8c26c
	Sflong_t	s = u;
Packit Service a8c26c
	Sfdouble_t	f;
Packit Service a8c26c
Packit Service a8c26c
	if (s >= 0)
Packit Service a8c26c
		return s;
Packit Service a8c26c
	s = u / 2;
Packit Service a8c26c
	f = s;
Packit Service a8c26c
	f *= 2;
Packit Service a8c26c
	if (u & 1)
Packit Service a8c26c
		f++;
Packit Service a8c26c
	return f;
Packit Service a8c26c
}
Packit Service a8c26c
#else
Packit Service a8c26c
#define U2F(x)		x
Packit Service a8c26c
#endif
Packit Service a8c26c
Packit Service a8c26c
Sfdouble_t	arith_exec(Arith_t *ep)
Packit Service a8c26c
{
Packit Service a8c26c
	register Sfdouble_t num=0,*dp,*sp;
Packit Service a8c26c
	register unsigned char *cp = ep->code;
Packit Service a8c26c
	register int c,type=0;
Packit Service a8c26c
	register char *tp;
Packit Service a8c26c
	Sfdouble_t small_stack[SMALL_STACK+1],arg[9];
Packit Service a8c26c
	const char *ptr = "";
Packit Service a8c26c
	char	*lastval=0;
Packit Service a8c26c
	int	lastsub;
Packit Service a8c26c
	Math_f fun;
Packit Service a8c26c
	struct lval node;
Packit Service a8c26c
	Shell_t	*shp = ep->shp;
Packit Service a8c26c
	node.shp = shp;
Packit Service a8c26c
	node.emode = ep->emode;
Packit Service a8c26c
	node.expr = ep->expr;
Packit Service a8c26c
	node.elen = ep->elen;
Packit Service a8c26c
	node.value = 0;
Packit Service a8c26c
	node.nosub = 0;
Packit Service a8c26c
	node.ptr = 0;
Packit Service a8c26c
	node.eflag = 0;
Packit Service a8c26c
	if(level++ >=MAXLEVEL)
Packit Service a8c26c
	{
Packit Service a8c26c
		arith_error(e_recursive,ep->expr,ep->emode);
Packit Service a8c26c
		return(0);
Packit Service a8c26c
	}
Packit Service a8c26c
	if(ep->staksize < SMALL_STACK)
Packit Service a8c26c
		sp = small_stack;
Packit Service a8c26c
	else
Packit Service a8c26c
		sp = (Sfdouble_t*)stakalloc(ep->staksize*(sizeof(Sfdouble_t)+1));
Packit Service a8c26c
	tp = (char*)(sp+ep->staksize);
Packit Service a8c26c
	tp--,sp--;
Packit Service a8c26c
	while(c = *cp++)
Packit Service a8c26c
	{
Packit Service a8c26c
		if(c&T_NOFLOAT)
Packit Service a8c26c
		{
Packit Service a8c26c
			if(type==1 || ((c&T_BINARY) && (c&T_OP)!=A_MOD  && tp[-1]==1))
Packit Service a8c26c
				arith_error(e_incompatible,ep->expr,ep->emode);
Packit Service a8c26c
		}
Packit Service a8c26c
		switch(c&T_OP)
Packit Service a8c26c
		{
Packit Service a8c26c
		    case A_JMP: case A_JMPZ: case A_JMPNZ:
Packit Service a8c26c
			c &= T_OP;
Packit Service a8c26c
			cp = roundptr(ep,cp,short);
Packit Service a8c26c
			if((c==A_JMPZ && num) || (c==A_JMPNZ &&!num))
Packit Service a8c26c
				cp += sizeof(short);
Packit Service a8c26c
			else
Packit Service a8c26c
				cp = (unsigned char*)ep + *((short*)cp);
Packit Service a8c26c
			continue;
Packit Service a8c26c
		    case A_NOTNOT:
Packit Service a8c26c
			num = (num!=0);
Packit Service a8c26c
			type=0;
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_PLUSPLUS:
Packit Service a8c26c
			node.nosub = -1;
Packit Service a8c26c
			(*ep->fun)(&ptr,&node,ASSIGN,num+1);
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_MINUSMINUS:
Packit Service a8c26c
			node.nosub = -1;
Packit Service a8c26c
			(*ep->fun)(&ptr,&node,ASSIGN,num-1);
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_INCR:
Packit Service a8c26c
			num = num+1;
Packit Service a8c26c
			node.nosub = -1;
Packit Service a8c26c
			num = (*ep->fun)(&ptr,&node,ASSIGN,num);
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_DECR:
Packit Service a8c26c
			num = num-1;
Packit Service a8c26c
			node.nosub = -1;
Packit Service a8c26c
			num = (*ep->fun)(&ptr,&node,ASSIGN,num);
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_SWAP:
Packit Service a8c26c
			num = sp[-1];
Packit Service a8c26c
			sp[-1] = *sp;
Packit Service a8c26c
			type = tp[-1];
Packit Service a8c26c
			tp[-1] = *tp;
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_POP:
Packit Service a8c26c
			sp--;
Packit Service a8c26c
			continue;
Packit Service a8c26c
		    case A_ASSIGNOP1:
Packit Service a8c26c
			node.emode |= ARITH_ASSIGNOP;
Packit Service a8c26c
		    case A_PUSHV:
Packit Service a8c26c
			cp = roundptr(ep,cp,Sfdouble_t*);
Packit Service a8c26c
			dp = *((Sfdouble_t**)cp);
Packit Service a8c26c
			cp += sizeof(Sfdouble_t*);
Packit Service a8c26c
			c = *(short*)cp;
Packit Service a8c26c
			cp += sizeof(short);
Packit Service a8c26c
			lastval = node.value = (char*)dp;
Packit Service a8c26c
			if(node.flag = c)
Packit Service a8c26c
				lastval = 0;
Packit Service a8c26c
			node.isfloat=0;
Packit Service a8c26c
			node.level = level;
Packit Service a8c26c
			node.nosub = 0;
Packit Service a8c26c
			num = (*ep->fun)(&ptr,&node,VALUE,num);
Packit Service a8c26c
			if(node.emode&ARITH_ASSIGNOP)
Packit Service a8c26c
			{
Packit Service a8c26c
				lastsub = node.nosub;
Packit Service a8c26c
				node.nosub = 0;
Packit Service a8c26c
				node.emode &= ~ARITH_ASSIGNOP;
Packit Service a8c26c
			}
Packit Service a8c26c
			if(node.value != (char*)dp)
Packit Service a8c26c
				arith_error(node.value,ptr,ep->emode);
Packit Service a8c26c
			*++sp = num;
Packit Service a8c26c
			type = node.isfloat;
Packit Service a8c26c
			if(num > LDBL_ULLONG_MAX || num < LDBL_LLONG_MIN)
Packit Service a8c26c
				type = 1;
Packit Service a8c26c
			else
Packit Service a8c26c
			{
Packit Service a8c26c
				Sfdouble_t d=num;
Packit Service a8c26c
				if(num > LDBL_LLONG_MAX && num <= LDBL_ULLONG_MAX)
Packit Service a8c26c
				{
Packit Service a8c26c
					type = 2;
Packit Service a8c26c
					d -= LDBL_LLONG_MAX;
Packit Service a8c26c
				}
Packit Service a8c26c
				if((Sflong_t)d!=d)
Packit Service a8c26c
					type = 1;
Packit Service a8c26c
			}
Packit Service a8c26c
			*++tp = type;
Packit Service a8c26c
			c = 0;
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_ENUM:
Packit Service a8c26c
			node.eflag = 1;
Packit Service a8c26c
			continue;
Packit Service a8c26c
		    case A_ASSIGNOP:
Packit Service a8c26c
			node.nosub = lastsub;
Packit Service a8c26c
		    case A_STORE:
Packit Service a8c26c
			cp = roundptr(ep,cp,Sfdouble_t*);
Packit Service a8c26c
			dp = *((Sfdouble_t**)cp);
Packit Service a8c26c
			cp += sizeof(Sfdouble_t*);
Packit Service a8c26c
			c = *(short*)cp;
Packit Service a8c26c
			if(c<0)
Packit Service a8c26c
				c = 0;
Packit Service a8c26c
			cp += sizeof(short);
Packit Service a8c26c
			node.value = (char*)dp;
Packit Service a8c26c
			node.flag = c;
Packit Service a8c26c
			if(lastval)
Packit Service a8c26c
				node.eflag = 1;
Packit Service a8c26c
			node.ptr = 0;
Packit Service a8c26c
			num = (*ep->fun)(&ptr,&node,ASSIGN,num);
Packit Service a8c26c
			if(lastval && node.ptr) 
Packit Service a8c26c
			{
Packit Service a8c26c
				Sfdouble_t r; 
Packit Service a8c26c
				node.flag = 0;
Packit Service a8c26c
				node.value = lastval;
Packit Service a8c26c
				r =  (*ep->fun)(&ptr,&node,VALUE,num);
Packit Service a8c26c
				if(r!=num)
Packit Service a8c26c
				{
Packit Service a8c26c
					node.flag=c;
Packit Service a8c26c
					node.value = (char*)dp;
Packit Service a8c26c
					num = (*ep->fun)(&ptr,&node,ASSIGN,r);
Packit Service a8c26c
				}
Packit Service a8c26c
Packit Service a8c26c
			}
Packit Service a8c26c
			lastval = 0;
Packit Service a8c26c
			c=0;
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_PUSHF:
Packit Service a8c26c
			cp = roundptr(ep,cp,Math_f);
Packit Service a8c26c
			*++sp = (Sfdouble_t)(cp-ep->code);
Packit Service a8c26c
			cp += sizeof(Math_f);
Packit Service a8c26c
			*++tp = *cp++;
Packit Service a8c26c
			continue;
Packit Service a8c26c
		    case A_PUSHN:
Packit Service a8c26c
			cp = roundptr(ep,cp,Sfdouble_t);
Packit Service a8c26c
			num = *((Sfdouble_t*)cp);
Packit Service a8c26c
			cp += sizeof(Sfdouble_t);
Packit Service a8c26c
			*++sp = num;
Packit Service a8c26c
			*++tp = type = *cp++;
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_NOT:
Packit Service a8c26c
			type=0;
Packit Service a8c26c
			num = !num;
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_UMINUS:
Packit Service a8c26c
			num = -num;
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_TILDE:
Packit Service a8c26c
			num = ~((Sflong_t)(num));
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_PLUS:
Packit Service a8c26c
			num += sp[-1];
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_MINUS:
Packit Service a8c26c
			num = sp[-1] - num;
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_TIMES:
Packit Service a8c26c
			num *= sp[-1];
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_POW:
Packit Service a8c26c
			num = pow(sp[-1],num);
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_MOD:
Packit Service a8c26c
			if(!(Sflong_t)num)
Packit Service a8c26c
				arith_error(e_divzero,ep->expr,ep->emode);
Packit Service a8c26c
			if(type==2 || tp[-1]==2)
Packit Service a8c26c
				num = U2F((Sfulong_t)(sp[-1]) % (Sfulong_t)(num));
Packit Service a8c26c
			else
Packit Service a8c26c
				num = (Sflong_t)(sp[-1]) % (Sflong_t)(num);
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_DIV:
Packit Service a8c26c
			if(type==1 || tp[-1]==1)
Packit Service a8c26c
			{
Packit Service a8c26c
				num = sp[-1]/num;
Packit Service a8c26c
				type = 1;
Packit Service a8c26c
			}
Packit Service a8c26c
			else if((Sfulong_t)(num)==0)
Packit Service a8c26c
				arith_error(e_divzero,ep->expr,ep->emode);
Packit Service a8c26c
			else if(type==2 || tp[-1]==2)
Packit Service a8c26c
				num = U2F((Sfulong_t)(sp[-1]) / (Sfulong_t)(num));
Packit Service a8c26c
			else
Packit Service a8c26c
				num = (Sflong_t)(sp[-1]) / (Sflong_t)(num);
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_LSHIFT:
Packit Service a8c26c
			if(tp[-1]==2)
Packit Service a8c26c
				num = U2F((Sfulong_t)(sp[-1]) << (long)(num));
Packit Service a8c26c
			else
Packit Service a8c26c
				num = (Sflong_t)(sp[-1]) << (long)(num);
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_RSHIFT:
Packit Service a8c26c
			if(tp[-1]==2)
Packit Service a8c26c
				num = U2F((Sfulong_t)(sp[-1]) >> (long)(num));
Packit Service a8c26c
			else
Packit Service a8c26c
				num = (Sflong_t)(sp[-1]) >> (long)(num);
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_XOR:
Packit Service a8c26c
			if(type==2 || tp[-1]==2)
Packit Service a8c26c
				num = U2F((Sfulong_t)(sp[-1]) ^ (Sfulong_t)(num));
Packit Service a8c26c
			else
Packit Service a8c26c
				num = (Sflong_t)(sp[-1]) ^ (Sflong_t)(num);
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_OR:
Packit Service a8c26c
			if(type==2 || tp[-1]==2)
Packit Service a8c26c
				num = U2F((Sfulong_t)(sp[-1]) | (Sfulong_t)(num));
Packit Service a8c26c
			else
Packit Service a8c26c
				num = (Sflong_t)(sp[-1]) | (Sflong_t)(num);
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_AND:
Packit Service a8c26c
			if(type==2 || tp[-1]==2)
Packit Service a8c26c
				num = U2F((Sfulong_t)(sp[-1]) & (Sfulong_t)(num));
Packit Service a8c26c
			else
Packit Service a8c26c
				num = (Sflong_t)(sp[-1]) & (Sflong_t)(num);
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_EQ:
Packit Service a8c26c
			num = (sp[-1]==num);
Packit Service a8c26c
			type=0;
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_NEQ:
Packit Service a8c26c
			num = (sp[-1]!=num);
Packit Service a8c26c
			type=0;
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_LE:
Packit Service a8c26c
			num = (sp[-1]<=num);
Packit Service a8c26c
			type=0;
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_GE:
Packit Service a8c26c
			num = (sp[-1]>=num);
Packit Service a8c26c
			type=0;
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_GT:
Packit Service a8c26c
			num = (sp[-1]>num);
Packit Service a8c26c
			type=0;
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_LT:
Packit Service a8c26c
			num = (sp[-1]
Packit Service a8c26c
			type=0;
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_CALL1F:
Packit Service a8c26c
			sp--,tp--;
Packit Service a8c26c
			fun = *((Math_f*)(ep->code+(int)(*sp)));
Packit Service a8c26c
			type = *tp;
Packit Service a8c26c
			if(c&T_BINARY)
Packit Service a8c26c
			{
Packit Service a8c26c
				c &= ~T_BINARY;
Packit Service a8c26c
				arg[0] = num;
Packit Service a8c26c
				arg[1] = 0;
Packit Service a8c26c
				num = sh_mathfun(shp,(void*)fun,1,arg);
Packit Service a8c26c
				break;
Packit Service a8c26c
			}
Packit Service a8c26c
			num = (*((Math_1f_f)fun))(num);
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_CALL1I:
Packit Service a8c26c
			sp--,tp--;
Packit Service a8c26c
			fun = *((Math_f*)(ep->code+(int)(*sp)));
Packit Service a8c26c
			type = *tp;
Packit Service a8c26c
			num = (*((Math_1i_f)fun))(num);
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_CALL2F:
Packit Service a8c26c
			sp-=2,tp-=2;
Packit Service a8c26c
			fun = *((Math_f*)(ep->code+(int)(*sp)));
Packit Service a8c26c
			type = *tp;
Packit Service a8c26c
			if(c&T_BINARY)
Packit Service a8c26c
			{
Packit Service a8c26c
				c &= ~T_BINARY;
Packit Service a8c26c
				arg[0] = sp[1];
Packit Service a8c26c
				arg[1] = num;
Packit Service a8c26c
				arg[2] = 0;
Packit Service a8c26c
				num = sh_mathfun(shp,(void*)fun,2,arg);
Packit Service a8c26c
				break;
Packit Service a8c26c
			}
Packit Service a8c26c
			if(c&T_NOFLOAT)
Packit Service a8c26c
				num = (*((Math_2f_i)fun))(sp[1],(int)num);
Packit Service a8c26c
			else
Packit Service a8c26c
				num = (*((Math_2f_f)fun))(sp[1],num);
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_CALL2I:
Packit Service a8c26c
			sp-=2,tp-=2;
Packit Service a8c26c
			fun = *((Math_f*)(ep->code+(int)(*sp)));
Packit Service a8c26c
			type = *tp;
Packit Service a8c26c
			num = (*((Math_2i_f)fun))(sp[1],num);
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_CALL3F:
Packit Service a8c26c
			sp-=3,tp-=3;
Packit Service a8c26c
			fun = *((Math_f*)(ep->code+(int)(*sp)));
Packit Service a8c26c
			type = *tp;
Packit Service a8c26c
			if(c&T_BINARY)
Packit Service a8c26c
			{
Packit Service a8c26c
				c &= ~T_BINARY;
Packit Service a8c26c
				arg[0] = sp[1];
Packit Service a8c26c
				arg[1] = sp[2];
Packit Service a8c26c
				arg[2] = num;
Packit Service a8c26c
				arg[3] = 0;
Packit Service a8c26c
				num = sh_mathfun(shp,(void*)fun,3,arg);
Packit Service a8c26c
				break;
Packit Service a8c26c
			}
Packit Service a8c26c
			num = (*((Math_3f_f)fun))(sp[1],sp[2],num);
Packit Service a8c26c
			break;
Packit Service a8c26c
		}
Packit Service a8c26c
		if(c)
Packit Service a8c26c
			lastval = 0;
Packit Service a8c26c
		if(c&T_BINARY)
Packit Service a8c26c
		{
Packit Service a8c26c
			node.ptr = 0;
Packit Service a8c26c
			sp--,tp--;
Packit Service a8c26c
			type  |= (*tp!=0);
Packit Service a8c26c
		}
Packit Service a8c26c
		*sp = num;
Packit Service a8c26c
		*tp = type;
Packit Service a8c26c
	}
Packit Service a8c26c
	if(level>0)
Packit Service a8c26c
		level--;
Packit Service a8c26c
	if(type==0 && !num)
Packit Service a8c26c
		num = 0;
Packit Service a8c26c
	return(num);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
/*
Packit Service a8c26c
 * This returns operator tokens or A_REG or A_NUM
Packit Service a8c26c
 */
Packit Service a8c26c
static int gettok(register struct vars *vp)
Packit Service a8c26c
{
Packit Service a8c26c
	register int c,op;
Packit Service a8c26c
	vp->errchr = vp->nextchr;
Packit Service a8c26c
	while(1)
Packit Service a8c26c
	{
Packit Service a8c26c
		c = getchr(vp);
Packit Service a8c26c
		switch(op=getop(c))
Packit Service a8c26c
		{
Packit Service a8c26c
		    case 0:
Packit Service a8c26c
			vp->errchr = vp->nextchr;
Packit Service a8c26c
			continue;
Packit Service a8c26c
		    case A_EOF:
Packit Service a8c26c
			vp->nextchr--;
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_COMMA:
Packit Service a8c26c
			if(vp->shp->decomma && (c=peekchr(vp))>='0' && c<='9')
Packit Service a8c26c
			{
Packit Service a8c26c
				op = A_DIG;
Packit Service a8c26c
		    		goto keep;
Packit Service a8c26c
			}
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_DOT:
Packit Service a8c26c
			if((c=peekchr(vp))>='0' && c<='9')
Packit Service a8c26c
				op = A_DIG;
Packit Service a8c26c
			else
Packit Service a8c26c
				op = A_REG;
Packit Service a8c26c
			/*FALL THRU*/
Packit Service a8c26c
		    case A_DIG: case A_REG: case A_LIT:
Packit Service a8c26c
		    keep:
Packit Service a8c26c
			ungetchr(vp);
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_QUEST:
Packit Service a8c26c
			if(peekchr(vp)==':')
Packit Service a8c26c
			{
Packit Service a8c26c
				getchr(vp);
Packit Service a8c26c
				op = A_QCOLON;
Packit Service a8c26c
			}
Packit Service a8c26c
			break;
Packit Service a8c26c
		    case A_LT:	case A_GT:
Packit Service a8c26c
			if(peekchr(vp)==c)
Packit Service a8c26c
			{
Packit Service a8c26c
				getchr(vp);
Packit Service a8c26c
				op -= 2;
Packit Service a8c26c
				break;
Packit Service a8c26c
			}
Packit Service a8c26c
			/* FALL THRU */
Packit Service a8c26c
		    case A_NOT:	case A_COLON:
Packit Service a8c26c
			c = '=';
Packit Service a8c26c
			/* FALL THRU */
Packit Service a8c26c
		    case A_ASSIGN:
Packit Service a8c26c
		    case A_TIMES:
Packit Service a8c26c
		    case A_PLUS:	case A_MINUS:
Packit Service a8c26c
		    case A_OR:	case A_AND:
Packit Service a8c26c
			if(peekchr(vp)==c)
Packit Service a8c26c
			{
Packit Service a8c26c
				getchr(vp);
Packit Service a8c26c
				op--;
Packit Service a8c26c
			}
Packit Service a8c26c
		}
Packit Service a8c26c
		return(op);
Packit Service a8c26c
	}
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
/*   
Packit Service a8c26c
 * evaluate a subexpression with precedence
Packit Service a8c26c
 */
Packit Service a8c26c
Packit Service a8c26c
static int expr(register struct vars *vp,register int precedence)
Packit Service a8c26c
{
Packit Service a8c26c
	register int	c, op;
Packit Service a8c26c
	int		invalid,wasop=0;
Packit Service a8c26c
	struct lval	lvalue,assignop;
Packit Service a8c26c
	const char	*pos;
Packit Service a8c26c
	Sfdouble_t	d;
Packit Service a8c26c
Packit Service a8c26c
	lvalue.value = 0;
Packit Service a8c26c
	lvalue.nargs = 0;
Packit Service a8c26c
	lvalue.fun = 0;
Packit Service a8c26c
	lvalue.shp =  vp->shp;
Packit Service a8c26c
again:
Packit Service a8c26c
	op = gettok(vp);
Packit Service a8c26c
	c = 2*MAXPREC+1;
Packit Service a8c26c
	switch(op)
Packit Service a8c26c
	{
Packit Service a8c26c
	    case A_PLUS:
Packit Service a8c26c
		goto again;
Packit Service a8c26c
	    case A_EOF:
Packit Service a8c26c
		if(precedence>2)
Packit Service a8c26c
			ERROR(vp,e_moretokens);
Packit Service a8c26c
		return(1);
Packit Service a8c26c
	    case A_MINUS:
Packit Service a8c26c
		op =  A_UMINUS;
Packit Service a8c26c
		goto common;
Packit Service a8c26c
	    case A_NOT:
Packit Service a8c26c
		goto common;
Packit Service a8c26c
	    case A_MINUSMINUS:
Packit Service a8c26c
		c = A_LVALUE;
Packit Service a8c26c
		op = A_DECR|T_NOFLOAT;
Packit Service a8c26c
		goto common;
Packit Service a8c26c
	    case A_PLUSPLUS:
Packit Service a8c26c
		c = A_LVALUE;
Packit Service a8c26c
		op = A_INCR|T_NOFLOAT;
Packit Service a8c26c
		/* FALL THRU */
Packit Service a8c26c
	    case A_TILDE:
Packit Service a8c26c
		op |= T_NOFLOAT;
Packit Service a8c26c
	    common:
Packit Service a8c26c
		if(!expr(vp,c))
Packit Service a8c26c
			return(0);
Packit Service a8c26c
		stakputc(op);
Packit Service a8c26c
		break;
Packit Service a8c26c
	    default:
Packit Service a8c26c
		vp->nextchr = vp->errchr;
Packit Service a8c26c
		wasop = 1;
Packit Service a8c26c
	}
Packit Service a8c26c
	invalid = wasop;
Packit Service a8c26c
	while(1)
Packit Service a8c26c
	{
Packit Service a8c26c
		assignop.value = 0;
Packit Service a8c26c
		op = gettok(vp);
Packit Service a8c26c
		if(op==A_DIG || op==A_REG || op==A_LIT)
Packit Service a8c26c
		{
Packit Service a8c26c
			if(!wasop)
Packit Service a8c26c
				ERROR(vp,e_synbad);
Packit Service a8c26c
			goto number;
Packit Service a8c26c
		}
Packit Service a8c26c
		if(wasop++ && op!=A_LPAR)
Packit Service a8c26c
			ERROR(vp,e_synbad);
Packit Service a8c26c
		/* check for assignment operation */
Packit Service a8c26c
		if(peekchr(vp)== '=' && !(strval_precedence[op]&NOASSIGN))
Packit Service a8c26c
		{
Packit Service a8c26c
			if((!lvalue.value || precedence > 3))
Packit Service a8c26c
				ERROR(vp,e_notlvalue);
Packit Service a8c26c
			if(precedence==3)
Packit Service a8c26c
				precedence = 2;
Packit Service a8c26c
			assignop = lvalue;
Packit Service a8c26c
			getchr(vp);
Packit Service a8c26c
			c = 3;
Packit Service a8c26c
		}
Packit Service a8c26c
		else
Packit Service a8c26c
		{
Packit Service a8c26c
			c = (strval_precedence[op]&PRECMASK);
Packit Service a8c26c
			if(c==MAXPREC || op==A_POW)
Packit Service a8c26c
				c++;
Packit Service a8c26c
			c *= 2;
Packit Service a8c26c
		}
Packit Service a8c26c
		/* from here on c is the new precedence level */
Packit Service a8c26c
		if(lvalue.value && (op!=A_ASSIGN))
Packit Service a8c26c
		{
Packit Service a8c26c
			if(vp->staksize++>=vp->stakmaxsize)
Packit Service a8c26c
				vp->stakmaxsize = vp->staksize;
Packit Service a8c26c
			if(op==A_EQ || op==A_NEQ)
Packit Service a8c26c
				stakputc(A_ENUM);
Packit Service a8c26c
			stakputc(assignop.value?A_ASSIGNOP1:A_PUSHV);
Packit Service a8c26c
			stakpush(vp,lvalue.value,char*);
Packit Service a8c26c
			if(lvalue.flag<0)
Packit Service a8c26c
				lvalue.flag = 0;
Packit Service a8c26c
			stakpush(vp,lvalue.flag,short);
Packit Service a8c26c
			if(vp->nextchr==0)
Packit Service a8c26c
				ERROR(vp,e_badnum);
Packit Service a8c26c
			if(!(strval_precedence[op]&SEQPOINT))
Packit Service a8c26c
				lvalue.value = 0;
Packit Service a8c26c
			invalid = 0;
Packit Service a8c26c
		}
Packit Service a8c26c
		else if(precedence==A_LVALUE)
Packit Service a8c26c
			ERROR(vp,e_notlvalue);
Packit Service a8c26c
		if(invalid && op>A_ASSIGN)
Packit Service a8c26c
			ERROR(vp,e_synbad);
Packit Service a8c26c
		if(precedence >= c)
Packit Service a8c26c
			goto done;
Packit Service a8c26c
		if(strval_precedence[op]&RASSOC)
Packit Service a8c26c
			c--;
Packit Service a8c26c
		if((c < (2*MAXPREC+1)) && !(strval_precedence[op]&SEQPOINT))
Packit Service a8c26c
		{
Packit Service a8c26c
			wasop = 0;
Packit Service a8c26c
			if(!expr(vp,c))
Packit Service a8c26c
				return(0);
Packit Service a8c26c
		}
Packit Service a8c26c
		switch(op)
Packit Service a8c26c
		{
Packit Service a8c26c
		case A_RPAR:
Packit Service a8c26c
			if(!vp->paren)
Packit Service a8c26c
				ERROR(vp,e_paren);
Packit Service a8c26c
			if(invalid)
Packit Service a8c26c
				ERROR(vp,e_synbad);
Packit Service a8c26c
			goto done;
Packit Service a8c26c
Packit Service a8c26c
		case A_COMMA:
Packit Service a8c26c
			wasop = 0;
Packit Service a8c26c
			if(vp->infun)
Packit Service a8c26c
				vp->infun++;
Packit Service a8c26c
			else
Packit Service a8c26c
			{
Packit Service a8c26c
				stakputc(A_POP);
Packit Service a8c26c
				vp->staksize--;
Packit Service a8c26c
			}
Packit Service a8c26c
			if(!expr(vp,c))
Packit Service a8c26c
			{
Packit Service a8c26c
				stakseek(staktell()-1);
Packit Service a8c26c
				return(0);
Packit Service a8c26c
			}
Packit Service a8c26c
			lvalue.value = 0;
Packit Service a8c26c
			break;
Packit Service a8c26c
Packit Service a8c26c
		case A_LPAR:
Packit Service a8c26c
		{
Packit Service a8c26c
			int	infun = vp->infun;
Packit Service a8c26c
			int	userfun=0;
Packit Service a8c26c
			Sfdouble_t (*fun)(Sfdouble_t,...);
Packit Service a8c26c
			int nargs = lvalue.nargs;
Packit Service a8c26c
			if(nargs<0)
Packit Service a8c26c
				nargs = -nargs;
Packit Service a8c26c
			fun = lvalue.fun;
Packit Service a8c26c
			lvalue.fun = 0;
Packit Service a8c26c
			if(fun)
Packit Service a8c26c
			{
Packit Service a8c26c
				if(vp->staksize++>=vp->stakmaxsize)
Packit Service a8c26c
					vp->stakmaxsize = vp->staksize;
Packit Service a8c26c
				vp->infun=1;
Packit Service a8c26c
				if((int)lvalue.nargs<0)
Packit Service a8c26c
					userfun = T_BINARY;
Packit Service a8c26c
				else if((int)lvalue.nargs&040)
Packit Service a8c26c
					userfun = T_NOFLOAT;
Packit Service a8c26c
				stakputc(A_PUSHF);
Packit Service a8c26c
				stakpush(vp,fun,Math_f);
Packit Service a8c26c
				stakputc(1);
Packit Service a8c26c
			}
Packit Service a8c26c
			else
Packit Service a8c26c
				vp->infun = 0;
Packit Service a8c26c
			if(!invalid)
Packit Service a8c26c
				ERROR(vp,e_synbad);
Packit Service a8c26c
			vp->paren++;
Packit Service a8c26c
			if(!expr(vp,1))
Packit Service a8c26c
				return(0);
Packit Service a8c26c
			vp->paren--;
Packit Service a8c26c
			if(fun)
Packit Service a8c26c
			{
Packit Service a8c26c
				int  x= (nargs&010)?2:-1;
Packit Service a8c26c
				nargs &= 7;
Packit Service a8c26c
				if(vp->infun != nargs)
Packit Service a8c26c
					ERROR(vp,e_argcount);
Packit Service a8c26c
				if((vp->staksize+=nargs)>=vp->stakmaxsize)
Packit Service a8c26c
					vp->stakmaxsize = vp->staksize+nargs;
Packit Service a8c26c
				stakputc(A_CALL1F+userfun+nargs+x);
Packit Service a8c26c
				vp->staksize -= nargs;
Packit Service a8c26c
			}
Packit Service a8c26c
			vp->infun = infun;
Packit Service a8c26c
			if (gettok(vp) != A_RPAR)
Packit Service a8c26c
				ERROR(vp,e_paren);
Packit Service a8c26c
			wasop = 0;
Packit Service a8c26c
			break;
Packit Service a8c26c
		}
Packit Service a8c26c
Packit Service a8c26c
		case A_PLUSPLUS:
Packit Service a8c26c
		case A_MINUSMINUS:
Packit Service a8c26c
			wasop=0;
Packit Service a8c26c
			op |= T_NOFLOAT;
Packit Service a8c26c
		case A_ASSIGN:
Packit Service a8c26c
			if(!lvalue.value)
Packit Service a8c26c
				ERROR(vp,e_notlvalue);
Packit Service a8c26c
			if(op==A_ASSIGN)
Packit Service a8c26c
			{
Packit Service a8c26c
				stakputc(A_STORE);
Packit Service a8c26c
				stakpush(vp,lvalue.value,char*);
Packit Service a8c26c
				stakpush(vp,lvalue.flag,short);
Packit Service a8c26c
				vp->staksize--;
Packit Service a8c26c
			}
Packit Service a8c26c
			else
Packit Service a8c26c
				stakputc(op);
Packit Service a8c26c
			lvalue.value = 0;
Packit Service a8c26c
			break;
Packit Service a8c26c
Packit Service a8c26c
		case A_QUEST:
Packit Service a8c26c
		{
Packit Service a8c26c
			int offset1,offset2;
Packit Service a8c26c
			stakputc(A_JMPZ);
Packit Service a8c26c
			offset1 = stakpush(vp,0,short);
Packit Service a8c26c
			stakputc(A_POP);
Packit Service a8c26c
			if(!expr(vp,1))
Packit Service a8c26c
				return(0);
Packit Service a8c26c
			if(gettok(vp)!=A_COLON)
Packit Service a8c26c
				ERROR(vp,e_questcolon);
Packit Service a8c26c
			stakputc(A_JMP);
Packit Service a8c26c
			offset2 = stakpush(vp,0,short);
Packit Service a8c26c
			*((short*)stakptr(offset1)) = staktell();
Packit Service a8c26c
			stakputc(A_POP);
Packit Service a8c26c
			if(!expr(vp,3))
Packit Service a8c26c
				return(0);
Packit Service a8c26c
			*((short*)stakptr(offset2)) = staktell();
Packit Service a8c26c
			lvalue.value = 0;
Packit Service a8c26c
			wasop = 0;
Packit Service a8c26c
			break;
Packit Service a8c26c
		}
Packit Service a8c26c
Packit Service a8c26c
		case A_COLON:
Packit Service a8c26c
			ERROR(vp,e_badcolon);
Packit Service a8c26c
			break;
Packit Service a8c26c
Packit Service a8c26c
		case A_QCOLON:
Packit Service a8c26c
		case A_ANDAND:
Packit Service a8c26c
		case A_OROR:
Packit Service a8c26c
		{
Packit Service a8c26c
			int offset;
Packit Service a8c26c
			if(op==A_ANDAND)
Packit Service a8c26c
				op = A_JMPZ;
Packit Service a8c26c
			else
Packit Service a8c26c
				op = A_JMPNZ;
Packit Service a8c26c
			stakputc(op);
Packit Service a8c26c
			offset = stakpush(vp,0,short);
Packit Service a8c26c
			stakputc(A_POP);
Packit Service a8c26c
			if(!expr(vp,c))
Packit Service a8c26c
				return(0);
Packit Service a8c26c
			*((short*)stakptr(offset)) = staktell();
Packit Service a8c26c
			if(op!=A_QCOLON)
Packit Service a8c26c
				stakputc(A_NOTNOT);
Packit Service a8c26c
			lvalue.value = 0;
Packit Service a8c26c
			wasop=0;
Packit Service a8c26c
			break;
Packit Service a8c26c
		}
Packit Service a8c26c
		case A_AND:	case A_OR:	case A_XOR:	case A_LSHIFT:
Packit Service a8c26c
		case A_RSHIFT:	case A_MOD:
Packit Service a8c26c
			op |= T_NOFLOAT;
Packit Service a8c26c
			/* FALL THRU */
Packit Service a8c26c
		case A_PLUS:	case A_MINUS:	case A_TIMES:	case A_DIV:
Packit Service a8c26c
		case A_EQ:	case A_NEQ:	case A_LT:	case A_LE:
Packit Service a8c26c
		case A_GT:	case A_GE:	case A_POW:
Packit Service a8c26c
			stakputc(op|T_BINARY);
Packit Service a8c26c
			vp->staksize--;
Packit Service a8c26c
			break;
Packit Service a8c26c
		case A_NOT: case A_TILDE:
Packit Service a8c26c
		default:
Packit Service a8c26c
			ERROR(vp,e_synbad);
Packit Service a8c26c
		number:
Packit Service a8c26c
			wasop = 0;
Packit Service a8c26c
			if(*vp->nextchr=='L' && vp->nextchr[1]=='\'')
Packit Service a8c26c
			{
Packit Service a8c26c
				vp->nextchr++;
Packit Service a8c26c
				op = A_LIT;
Packit Service a8c26c
			}
Packit Service a8c26c
			pos = vp->nextchr;
Packit Service a8c26c
			lvalue.isfloat = 0;
Packit Service a8c26c
			lvalue.expr = vp->expr;
Packit Service a8c26c
			lvalue.emode = vp->emode;
Packit Service a8c26c
			if(op==A_LIT)
Packit Service a8c26c
			{
Packit Service a8c26c
				/* character constants */
Packit Service a8c26c
				if(pos[1]=='\\' && pos[2]=='\'' && pos[3]!='\'')
Packit Service a8c26c
				{
Packit Service a8c26c
					d = '\\';
Packit Service a8c26c
					vp->nextchr +=2;
Packit Service a8c26c
				}
Packit Service a8c26c
				else
Packit Service a8c26c
					d = chresc(pos+1,(char**)&vp->nextchr);
Packit Service a8c26c
				/* posix allows the trailing ' to be optional */
Packit Service a8c26c
				if(*vp->nextchr=='\'')
Packit Service a8c26c
					vp->nextchr++;
Packit Service a8c26c
			}
Packit Service a8c26c
			else
Packit Service a8c26c
				d = (*vp->convert)(&vp->nextchr, &lvalue, LOOKUP, 0);
Packit Service a8c26c
			if (vp->nextchr == pos)
Packit Service a8c26c
			{
Packit Service a8c26c
				if(vp->errmsg.value = lvalue.value)
Packit Service a8c26c
					vp->errstr = pos;
Packit Service a8c26c
				ERROR(vp,op==A_LIT?e_charconst:e_synbad);
Packit Service a8c26c
			}
Packit Service a8c26c
			if(op==A_DIG || op==A_LIT)
Packit Service a8c26c
			{
Packit Service a8c26c
				stakputc(A_PUSHN);
Packit Service a8c26c
				if(vp->staksize++>=vp->stakmaxsize)
Packit Service a8c26c
					vp->stakmaxsize = vp->staksize;
Packit Service a8c26c
				stakpush(vp,d,Sfdouble_t);
Packit Service a8c26c
				stakputc(lvalue.isfloat);
Packit Service a8c26c
			}
Packit Service a8c26c
	
Packit Service a8c26c
			/* check for function call */
Packit Service a8c26c
			if(lvalue.fun)
Packit Service a8c26c
				continue;
Packit Service a8c26c
			break;
Packit Service a8c26c
		}
Packit Service a8c26c
		invalid = 0;
Packit Service a8c26c
		if(assignop.value)
Packit Service a8c26c
		{
Packit Service a8c26c
			if(vp->staksize++>=vp->stakmaxsize)
Packit Service a8c26c
				vp->stakmaxsize = vp->staksize;
Packit Service a8c26c
			if(assignop.flag<0)
Packit Service a8c26c
				assignop.flag = 0;
Packit Service a8c26c
			stakputc(c&1?A_ASSIGNOP:A_STORE);
Packit Service a8c26c
			stakpush(vp,assignop.value,char*);
Packit Service a8c26c
			stakpush(vp,assignop.flag,short);
Packit Service a8c26c
		}
Packit Service a8c26c
	}
Packit Service a8c26c
 done:
Packit Service a8c26c
	vp->nextchr = vp->errchr;
Packit Service a8c26c
	return(1);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
Arith_t *arith_compile(Shell_t *shp,const char *string,char **last,Sfdouble_t(*fun)(const char**,struct lval*,int,Sfdouble_t),int emode)
Packit Service a8c26c
{
Packit Service a8c26c
	struct vars cur;
Packit Service a8c26c
	register Arith_t *ep;
Packit Service a8c26c
	int offset;
Packit Service a8c26c
	memset((void*)&cur,0,sizeof(cur));
Packit Service a8c26c
	cur.shp = shp;
Packit Service a8c26c
     	cur.expr = cur.nextchr = string;
Packit Service a8c26c
	cur.convert = fun;
Packit Service a8c26c
	cur.emode = emode;
Packit Service a8c26c
	cur.errmsg.value = 0;
Packit Service a8c26c
	cur.errmsg.emode = emode;
Packit Service a8c26c
	stakseek(sizeof(Arith_t));
Packit Service a8c26c
	if(!expr(&cur,0) && cur.errmsg.value)
Packit Service a8c26c
        {
Packit Service a8c26c
		if(cur.errstr)
Packit Service a8c26c
			string = cur.errstr;
Packit Service a8c26c
		if((*fun)( &string , &cur.errmsg, MESSAGE, 0) < 0)
Packit Service a8c26c
		{
Packit Service a8c26c
			stakseek(0);
Packit Service a8c26c
			*last = (char*)Empty;
Packit Service a8c26c
			return(0);
Packit Service a8c26c
		}
Packit Service a8c26c
		cur.nextchr = cur.errchr;
Packit Service a8c26c
	}
Packit Service a8c26c
	stakputc(0);
Packit Service a8c26c
	offset = staktell();
Packit Service a8c26c
	ep = (Arith_t*)stakfreeze(0);
Packit Service a8c26c
	ep->shp = shp;
Packit Service a8c26c
	ep->expr = string;
Packit Service a8c26c
	ep->elen = strlen(string);
Packit Service a8c26c
	ep->code = (unsigned char*)(ep+1);
Packit Service a8c26c
	ep->fun = fun;
Packit Service a8c26c
	ep->emode = emode;
Packit Service a8c26c
	ep->size = offset - sizeof(Arith_t);
Packit Service a8c26c
	ep->staksize = cur.stakmaxsize+1;
Packit Service a8c26c
	if(last)
Packit Service a8c26c
		*last = (char*)(cur.nextchr);
Packit Service a8c26c
	return(ep);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
/*
Packit Service a8c26c
 * evaluate an integer arithmetic expression in s
Packit Service a8c26c
 *
Packit Service a8c26c
 * (Sfdouble_t)(*convert)(char** end, struct lval* string, int type, Sfdouble_t value)
Packit Service a8c26c
 *     is a user supplied conversion routine that is called when unknown 
Packit Service a8c26c
 *     chars are encountered.
Packit Service a8c26c
 * *end points to the part to be converted and must be adjusted by convert to
Packit Service a8c26c
 * point to the next non-converted character; if typ is MESSAGE then string
Packit Service a8c26c
 * points to an error message string
Packit Service a8c26c
 *
Packit Service a8c26c
 * NOTE: (*convert)() may call strval()
Packit Service a8c26c
 */
Packit Service a8c26c
Packit Service a8c26c
Sfdouble_t strval(Shell_t *shp,const char *s,char **end,Sfdouble_t(*conv)(const char**,struct lval*,int,Sfdouble_t),int emode)
Packit Service a8c26c
{
Packit Service a8c26c
	Arith_t *ep;
Packit Service a8c26c
	Sfdouble_t d;
Packit Service a8c26c
	char *sp=0;
Packit Service a8c26c
	int offset;
Packit Service a8c26c
	if(offset=staktell())
Packit Service a8c26c
		sp = stakfreeze(1);
Packit Service a8c26c
	ep = arith_compile(shp,s,end,conv,emode);
Packit Service a8c26c
	ep->emode = emode;
Packit Service a8c26c
	d = arith_exec(ep);
Packit Service a8c26c
	stakset(sp?sp:(char*)ep,offset);
Packit Service a8c26c
	return(d);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
#if _mem_name__exception
Packit Service a8c26c
#undef	_mem_name_exception
Packit Service a8c26c
#define	_mem_name_exception	1
Packit Service a8c26c
#undef	exception
Packit Service a8c26c
#define	exception		_exception
Packit Service a8c26c
#undef	matherr
Packit Service a8c26c
#endif
Packit Service a8c26c
Packit Service a8c26c
#if _mem_name_exception
Packit Service a8c26c
Packit Service a8c26c
#undef	error
Packit Service a8c26c
Packit Service a8c26c
#if _BLD_shell && defined(__EXPORT__)
Packit Service a8c26c
#define extern			__EXPORT__
Packit Service a8c26c
#endif
Packit Service a8c26c
Packit Service a8c26c
#ifndef DOMAIN
Packit Service a8c26c
#define DOMAIN			_DOMAIN
Packit Service a8c26c
#endif
Packit Service a8c26c
#ifndef OVERFLOW
Packit Service a8c26c
#define OVERFLOW		_OVERFLOW
Packit Service a8c26c
#endif
Packit Service a8c26c
#ifndef SING
Packit Service a8c26c
#define SING			_SING
Packit Service a8c26c
#endif
Packit Service a8c26c
Packit Service a8c26c
    extern int matherr(struct exception *ep)
Packit Service a8c26c
    {
Packit Service a8c26c
	const char *message;
Packit Service a8c26c
	switch(ep->type)
Packit Service a8c26c
	{
Packit Service a8c26c
#ifdef DOMAIN
Packit Service a8c26c
	    case DOMAIN:
Packit Service a8c26c
		message = ERROR_dictionary(e_domain);
Packit Service a8c26c
		break;
Packit Service a8c26c
#endif
Packit Service a8c26c
#ifdef OVERFLOW
Packit Service a8c26c
	    case OVERFLOW:
Packit Service a8c26c
		message = ERROR_dictionary(e_overflow);
Packit Service a8c26c
		break;
Packit Service a8c26c
#endif
Packit Service a8c26c
#ifdef SING
Packit Service a8c26c
	    case SING:
Packit Service a8c26c
		message = ERROR_dictionary(e_singularity);
Packit Service a8c26c
		break;
Packit Service a8c26c
#endif
Packit Service a8c26c
	    default:
Packit Service a8c26c
		return(1);
Packit Service a8c26c
	}
Packit Service a8c26c
	level=0;
Packit Service a8c26c
	errormsg(SH_DICT,ERROR_exit(1),message,ep->name);
Packit Service a8c26c
	return(0);
Packit Service a8c26c
    }
Packit Service a8c26c
Packit Service a8c26c
#undef	extern
Packit Service a8c26c
Packit Service a8c26c
#endif /* _mem_name_exception */