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