home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
EFFO
/
forum7.lzh
/
C
/
VC
/
interpret.c
< prev
next >
Wrap
Text File
|
1988-09-02
|
11KB
|
488 lines
/* SC A Spreadsheet Calculator
* Expression interpreter and assorted support routines.
*
* original by James Gosling, September 1982
* modified by Mark Weiser and Bruce Israel,
* University of Maryland
*/
#include "sc.h"
#include <stdio.h>
#include "interpret.h"
#define DEFCOLDELIM ':'
char *malloc();
double eval(e)
struct enode *e;
{
double h;
if (e==0) return 0;
switch (e->op) {
case K_ABS: h=eval(e->e.o.left); return(h<(double)0?-h:h);
case K_ACOS: return(acos(eval(e->e.o.left)));
case K_ASIN: return(asin(eval(e->e.o.left)));
case K_ATAN: return(atan(eval(e->e.o.left)));
case K_CEIL: return(ceil(eval(e->e.o.left)));
case K_COS: return(cos(eval(e->e.o.left)));
case K_EXP: return(exp(eval(e->e.o.left)));
case K_FLOOR: return(floor(eval(e->e.o.left)));
case K_HYPOT: return(hypot(eval(e->e.o.left)));
case K_LN: return(log(eval(e->e.o.left)));
case K_LOG: return(log10(eval(e->e.o.left)));
case K_SIN: return(sin(eval(e->e.o.left)));
case K_SQRT: return(sqrt(eval(e->e.o.left)));
case K_TAN: return(tan(eval(e->e.o.left)));
case '+': return (eval(e->e.o.left) + eval(e->e.o.right));
case '-': return (eval(e->e.o.left) - eval(e->e.o.right));
case '*': return (eval(e->e.o.left) * eval(e->e.o.right));
case '/': { double denom = eval (e->e.o.right);
return denom ? eval(e->e.o.left) / denom : 0; }
case '<': return (eval(e->e.o.left) < eval(e->e.o.right));
case '=': return (eval(e->e.o.left) == eval(e->e.o.right));
case '>': return (eval(e->e.o.left) > eval(e->e.o.right));
case '&': return (eval(e->e.o.left) && eval(e->e.o.right));
case '|': return (eval(e->e.o.left) || eval(e->e.o.right));
case '?': return eval(e->e.o.left) ? eval(e->e.o.right->e.o.left)
: eval(e->e.o.right->e.o.right);
case 'm': return (-eval(e->e.o.right));
case 'f': return (eval(e->e.o.right));
case '~': return (!eval(e->e.o.right));
case 'k': return (e->e.k);
case 'v': return (e->e.v->v);
case 'p': return (executeprogram(e));
case O_REDUCE('+'):
{ register r,c;
register struct ent *p;
register double v = 0;
register maxr, maxc;
register minr, minc;
maxr = ((struct ent *) e->e.o.right) -> row;
maxc = ((struct ent *) e->e.o.right) -> col;
minr = ((struct ent *) e->e.o.left) -> row;
minc = ((struct ent *) e->e.o.left) -> col;
if (minr>maxr) r = maxr, maxr = minr, minr = r;
if (minc>maxc) c = maxc, maxc = minc, minc = c;
for (r = minr; r<=maxr; r++)
for (c = minc; c<=maxc; c++)
if ((p = tbl[r][c]) && p->flags&is_valid)
v += p->v;
return v;
}
}
}
#define MAXPROP 7
EvalAll () {
int lastct,repct;
repct = 0;
while ((lastct = RealEvalAll()) && (repct++ <= MAXPROP));
repct--;
}
int RealEvalAll () {
register i,j;
int chgct = 0;
register struct ent *p;
for (i=0; i<=maxrow; i++)
for (j=0; j<=maxcol; j++)
if ((p=tbl[i][j]) && p->expr) {
double v;
v = eval (p->expr);
if (v != p->v) {
p->v = v; chgct++;
p->flags |= (is_changed|is_valid);
}
}
return(chgct);
}
struct enode *new(op,a1,a2)
struct enode *a1, *a2; {
register struct enode *p = (struct enode *) malloc (sizeof (struct enode));
p->op = op;
switch (op) {
case O_VAR: p->e.v = (struct ent *) a1; break;
case O_CONST: p->e.k = *(double *)a1; break;
default: p->e.o.left = a1; p->e.o.right = a2;
}
return p;
}
let (v, e)
struct ent *v;
struct enode *e; {
efree (v->expr);
if (constant(e)) {
v->v = eval(e);
v->expr = 0;
efree(e);
} else
v->expr = e;
v->flags |= (is_changed|is_valid);
changed++;
modflg++;
}
clearent (v)
struct ent *v; {
label(v,"",-1);
v->v = 0;
v->expr = 0;
v->flags |= (is_changed);
v->flags &= ~(is_valid);
changed++;
modflg++;
}
constant(e)
register struct enode *e; {
return e==0 || e->op == O_CONST
|| (e->op != O_VAR
&& e->op != 'p'
&& (e->op&~0177) != O_REDUCE(0)
&& constant (e->e.o.left)
&& constant(e->e.o.right));
}
efree (e)
struct enode *e; {
if (e) {
if (e->op == 'p')
{ pfree (e); }
else {
if (e->op != O_VAR && e->op !=O_CONST
&& (e->op&~0177) != O_REDUCE(0))
{
efree (e->e.o.left);
efree (e->e.o.right);
}
free (e);
}
}
}
label (v, s, flushdir)
register struct ent *v;
register char *s; {
if (v) {
if (flushdir==0 && v->flags&is_valid) {
register struct ent *tv;
if (v->col>0 && ((tv=lookat(v->row,v->col-1))->flags&is_valid)==0)
v = tv, flushdir = 1;
else if (((tv=lookat (v->row,v->col+1))->flags&is_valid)==0)
v = tv, flushdir = -1;
else flushdir = -1;
}
if (v->label) free(v->label);
if (s && s[0]) {
v->label = (char *) malloc (strlen(s)+1);
strcpy (v->label, s);
} else v->label = 0;
v->flags |= is_lchanged;
if (flushdir<0) v->flags |= is_leftflush;
else v->flags &= ~is_leftflush;
FullUpdate++;
modflg++;
}
}
decodev (v)
register struct ent *v;
{
if (v)
sprintf (line+linelim,"r%dc%d",v->row,v->col);
else
sprintf (line+linelim,"VAR?");
linelim += strlen (line+linelim);
}
decompile(e, priority)
register struct enode *e;
{
if (e)
{
int mypriority;
switch (e->op)
{
default: mypriority = 99; break;
case '?': mypriority = 1; break;
case ':': mypriority = 2; break;
case '|': mypriority = 3; break;
case '&': mypriority = 4; break;
case '<': case '=': case '>': mypriority = 6; break;
case '+': case '-': mypriority = 8; break;
case '*': case '/': mypriority = 10; break;
}
if (mypriority<priority)
line[linelim++] = '(';
switch (e->op)
{
case 'f':
{
register char *s;
for (s="fixed "; line[linelim++] = *s++;);
linelim--;
decompile (e->e.o.right, 30);
break;
}
case 's':
{
char *s;
line[linelim++]='"';
for(s=e->e.o.left; *s; line[linelim++] = *s++);
line[linelim++]='"';
break;
}
case 'm':
line[linelim++] = '-';
decompile (e->e.o.right, 30);
break;
case '~':
line[linelim++] = '~';
decompile (e->e.o.right, 30);
break;
case 'v':
decodev (e->e.v);
break;
case 'k':
sprintf (line+linelim,"%g",e->e.k);
linelim += strlen (line+linelim);
break;
case O_REDUCE('+'):
case O_REDUCE('*'):
line[linelim++] = e->op&0177;
line[linelim++] = '/';
decodev (e->e.o.left);
line[linelim++] = ':';
decodev (e->e.o.right);
break;
case 'p':
{
int i;
char *cptr;
struct lnode *ptr;
line[linelim++] = 'e';
line[linelim++] = 'x';
line[linelim++] = 'e';
line[linelim++] = 'c';
line[linelim++] = '(';
line[linelim++] = '"';
cptr = (char *)(e->e.o.left);
while (*cptr)
line[linelim++] = *cptr++;
line[linelim++] = '"';
line[linelim++] = ',';
ptr = (struct lnode *)(e->e.o.right);
decompile ( ptr->lptr[0] );
for( i=1; i<ptr->num; i+=1)
{
line[linelim++] = ',';
decompile ( ptr->lptr[i] );
}
line[linelim++] = ')';
break;
}
case K_ABS: case K_ACOS: case K_ASIN: case K_ATAN: case K_CEIL:
case K_COS: case K_EXP: case K_FLOOR: case K_HYPOT: case K_LOG:
case K_LN: case K_SIN: case K_SQRT: case K_TAN:
print_func(e->op);
decompile(e->e.o.left, 99);
break;
default:
decompile (e->e.o.left, mypriority);
line[linelim++] = e->op;
decompile (e->e.o.right, mypriority+1);
break;
}
if (mypriority<priority)
line[linelim++] = ')';
}
else
line[linelim++] = '?';
}
editv (row, col) {
sprintf (line, "let r%dc%d = ", row, col);
linelim = strlen(line);
editexp(row,col);
}
editexp(row,col) {
register struct ent *p;
p = lookat (row, col);
if (p->flags&is_valid)
if (p->expr) {
decompile (p->expr);
line[linelim] = 0;
} else {
sprintf (line+linelim, "%g", p->v);
linelim += strlen (line+linelim);
}
}
edits (row, col) {
register struct ent *p = lookat (row, col);
sprintf (line, "%sstring r%dc%d = \"",
((p->flags&is_leftflush) ? "left" : "right"),
row, col);
linelim = strlen(line);
sprintf (line+linelim, "%s", p->label);
linelim += strlen (line+linelim);
}
printfile (fname) {
FILE *f = fopen(fname, "w");
char pline[1000];
int plinelim;
register row, col;
register struct ent **p;
if (f==0)
{
error ("Can't create %s", fname);
return;
}
for (row=0;row<=maxrow; row++)
{
register c = 0;
plinelim = 0;
for (p = &tbl[row][col=0]; col<=maxcol; col++, p++)
{
if (*p)
{
char *s;
while (plinelim<c)
pline[plinelim++] = ' ';
plinelim = c;
if ((*p)->flags&is_valid)
{
char h[80];
sprintf (h,"%%%d.%df",fwidth[col],precision[col]);
sprintf (pline+plinelim,h, (*p)->v);
plinelim += strlen (pline+plinelim);
}
if (s = (*p)->label)
{
register char *d;
d = pline+((*p)->flags&is_leftflush
? c : c-strlen(s)+fwidth[col]);
while (d>pline+plinelim) pline[plinelim++] = ' ';
if (d<pline)
d = pline;
while (*s)
*d++ = *s++;
if (d-pline>plinelim)
plinelim = d-pline;
}
}
c += fwidth [col];
}
{
char h[80];
sprintf (h,"%%.%ds\n", plinelim);
fprintf (f,h, pline);
}
}
fclose (f);
}
tblprintfile (fname)
{
FILE *f = fopen(fname, "w");
register row, col;
register struct ent **p;
char coldelim = DEFCOLDELIM;
if (f==0)
{
error ("Can't create %s", fname);
return;
}
for (row=0;row<=maxrow; row++)
{
register c = 0;
for (p = &tbl[row][col=0]; col<=maxcol; col++, p++)
{
if (*p)
{
char *s;
if ((*p)->flags&is_valid)
{
char h[80];
sprintf (h,"%%.%df",precision[col]);
fprintf (f,h, (*p)->v);
}
else
if (s = (*p)->label)
{
fprintf (f,"%s",s);
}
else
fprintf(f," ");
}
else
fprintf(f," ");
fprintf(f,"%c",coldelim);
}
fprintf (f,"\n");
}
fclose (f);
}
struct enode *copye (e, Rdelta, Cdelta)
register struct enode *e; {
register struct enode *ret;
if (e==0) ret = 0;
else {
ret = (struct enode *) malloc (sizeof (struct enode));
*ret = *e;
switch (ret->op) {
case 'v':
ret->e.v = lookat (ret->e.v->row+Rdelta, ret->e.v->col+Cdelta);
break;
case 'k':
break;
case 'f':
ret->e.o.right = copye (ret->e.o.right,0,0);
break;
default:
ret->e.o.right = copye (ret->e.o.right,Rdelta,Cdelta);
ret->e.o.left = copye (ret->e.o.left,Rdelta,Cdelta);
break;
}
}
return ret;
}