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 >
Text File  |  1988-09-02  |  11KB  |  488 lines

  1. /*    SC    A Spreadsheet Calculator
  2.  *        Expression interpreter and assorted support routines.
  3.  *
  4.  *        original by James Gosling, September 1982
  5.  *        modified by Mark Weiser and Bruce Israel, 
  6.  *            University of Maryland
  7.  */
  8.  
  9. #include "sc.h"
  10. #include <stdio.h>
  11. #include "interpret.h"
  12. #define DEFCOLDELIM ':'
  13.  
  14. char *malloc();
  15.  
  16. double eval(e)
  17. struct enode *e;
  18. {
  19.     double h;
  20.     if (e==0) return 0;
  21.     switch (e->op) {
  22.        case K_ABS: h=eval(e->e.o.left); return(h<(double)0?-h:h);
  23.        case K_ACOS:    return(acos(eval(e->e.o.left)));
  24.        case K_ASIN:    return(asin(eval(e->e.o.left)));
  25.        case K_ATAN:    return(atan(eval(e->e.o.left)));
  26.        case K_CEIL:    return(ceil(eval(e->e.o.left)));
  27.        case K_COS:        return(cos(eval(e->e.o.left)));
  28.        case K_EXP:        return(exp(eval(e->e.o.left)));
  29.        case K_FLOOR:    return(floor(eval(e->e.o.left)));
  30.        case K_HYPOT:    return(hypot(eval(e->e.o.left)));
  31.        case K_LN:    return(log(eval(e->e.o.left)));
  32.        case K_LOG:    return(log10(eval(e->e.o.left)));
  33.        case K_SIN:    return(sin(eval(e->e.o.left)));
  34.        case K_SQRT:    return(sqrt(eval(e->e.o.left)));
  35.        case K_TAN:    return(tan(eval(e->e.o.left)));
  36.     case '+':    return (eval(e->e.o.left) + eval(e->e.o.right));
  37.     case '-':    return (eval(e->e.o.left) - eval(e->e.o.right));
  38.     case '*':    return (eval(e->e.o.left) * eval(e->e.o.right));
  39.     case '/':     {    double denom = eval (e->e.o.right);
  40.             return denom ? eval(e->e.o.left) / denom : 0; }
  41.     case '<':    return (eval(e->e.o.left) < eval(e->e.o.right));
  42.     case '=':    return (eval(e->e.o.left) == eval(e->e.o.right));
  43.     case '>':    return (eval(e->e.o.left) > eval(e->e.o.right));
  44.     case '&':    return (eval(e->e.o.left) && eval(e->e.o.right));
  45.     case '|':    return (eval(e->e.o.left) || eval(e->e.o.right));
  46.     case '?':    return eval(e->e.o.left) ? eval(e->e.o.right->e.o.left)
  47.                          : eval(e->e.o.right->e.o.right);
  48.     case 'm':    return (-eval(e->e.o.right));
  49.     case 'f':    return (eval(e->e.o.right));
  50.     case '~':    return (!eval(e->e.o.right));
  51.     case 'k':    return (e->e.k);
  52.     case 'v':    return (e->e.v->v);
  53.     case 'p':    return (executeprogram(e));
  54.     case O_REDUCE('+'):
  55.         {    register r,c;
  56.         register struct ent *p;
  57.         register double v = 0;
  58.         register maxr, maxc;
  59.         register minr, minc;
  60.         maxr = ((struct ent *) e->e.o.right) -> row;
  61.         maxc = ((struct ent *) e->e.o.right) -> col;
  62.         minr = ((struct ent *) e->e.o.left) -> row;
  63.         minc = ((struct ent *) e->e.o.left) -> col;
  64.         if (minr>maxr) r = maxr, maxr = minr, minr = r;
  65.         if (minc>maxc) c = maxc, maxc = minc, minc = c;
  66.         for (r = minr; r<=maxr; r++)
  67.             for (c = minc; c<=maxc; c++)
  68.             if ((p = tbl[r][c]) && p->flags&is_valid)
  69.                 v += p->v;
  70.         return v;
  71.         }
  72.     }
  73. }
  74.  
  75. #define MAXPROP 7
  76.  
  77. EvalAll () {
  78.     int lastct,repct;
  79.     
  80.     repct = 0;
  81.  
  82.     while ((lastct = RealEvalAll()) && (repct++ <= MAXPROP));
  83.  
  84.     repct--;
  85. }
  86.  
  87. int RealEvalAll () {
  88.     register i,j;
  89.     int chgct = 0;
  90.     register struct ent *p;
  91.     for (i=0; i<=maxrow; i++)
  92.     for (j=0; j<=maxcol; j++)
  93.         if ((p=tbl[i][j]) && p->expr) {
  94.         double v;
  95.         v = eval (p->expr);
  96.         if (v != p->v) {
  97.             p->v = v; chgct++;
  98.             p->flags |= (is_changed|is_valid);
  99.         }
  100.         }
  101.     return(chgct);
  102. }
  103.  
  104. struct enode *new(op,a1,a2)
  105. struct enode *a1, *a2; {
  106.     register struct enode *p = (struct enode *) malloc (sizeof (struct enode));
  107.     p->op = op;
  108.     switch (op) {
  109.     case O_VAR: p->e.v = (struct ent *) a1; break;
  110.     case O_CONST: p->e.k = *(double *)a1; break;
  111.     default: p->e.o.left = a1; p->e.o.right = a2;
  112.     }
  113.     return p;
  114. }
  115.  
  116. let (v, e)
  117. struct ent *v;
  118. struct enode *e; {
  119.     efree (v->expr);
  120.     if (constant(e)) {
  121.     v->v = eval(e);
  122.     v->expr = 0;
  123.     efree(e);
  124.     } else
  125.     v->expr = e;
  126.     v->flags |= (is_changed|is_valid);
  127.     changed++;
  128.     modflg++;
  129. }
  130.  
  131. clearent (v)
  132. struct ent *v; {
  133.     label(v,"",-1);
  134.     v->v = 0;
  135.     v->expr = 0;
  136.     v->flags |= (is_changed);
  137.     v->flags &= ~(is_valid);
  138.     changed++;
  139.     modflg++;
  140. }
  141.  
  142. constant(e)
  143. register struct enode *e; {
  144.     return e==0 || e->op == O_CONST 
  145.     || (e->op != O_VAR
  146.      && e->op != 'p'
  147.      && (e->op&~0177) != O_REDUCE(0)
  148.      && constant (e->e.o.left)
  149.      && constant(e->e.o.right));
  150. }
  151.  
  152. efree (e)
  153. struct enode *e; {
  154.     if (e) {
  155.     if (e->op == 'p')
  156.         { pfree (e); }
  157.     else {
  158.         if (e->op != O_VAR && e->op !=O_CONST 
  159.             && (e->op&~0177) != O_REDUCE(0))
  160.         {
  161.             efree (e->e.o.left);
  162.             efree (e->e.o.right);
  163.         }
  164.         free (e);
  165.     }
  166.     }
  167. }
  168.  
  169. label (v, s, flushdir)
  170. register struct ent *v;
  171. register char *s; {
  172.     if (v) {
  173.     if (flushdir==0 && v->flags&is_valid) {
  174.         register struct ent *tv;
  175.         if (v->col>0 && ((tv=lookat(v->row,v->col-1))->flags&is_valid)==0)
  176.         v = tv, flushdir = 1;
  177.         else if (((tv=lookat (v->row,v->col+1))->flags&is_valid)==0)
  178.         v = tv, flushdir = -1;
  179.         else flushdir = -1;
  180.     }
  181.     if (v->label) free(v->label);
  182.     if (s && s[0]) {
  183.         v->label = (char *) malloc (strlen(s)+1);
  184.         strcpy (v->label, s);
  185.     } else v->label = 0;
  186.     v->flags |= is_lchanged;
  187.     if (flushdir<0) v->flags |= is_leftflush;
  188.     else v->flags &= ~is_leftflush;
  189.     FullUpdate++;
  190.     modflg++;
  191.     }
  192. }
  193.  
  194.  
  195. decodev (v)
  196. register struct ent *v;
  197. {
  198.     if (v)
  199.         sprintf (line+linelim,"r%dc%d",v->row,v->col);
  200.     else
  201.         sprintf (line+linelim,"VAR?");
  202.         
  203.     linelim += strlen (line+linelim);
  204. }
  205.  
  206.  
  207. decompile(e, priority)
  208. register struct enode *e;
  209. {
  210.     if (e) 
  211.     {
  212.         int mypriority;
  213.         switch (e->op)
  214.         {
  215.             default: mypriority = 99; break;
  216.             case '?': mypriority = 1; break;
  217.             case ':': mypriority = 2; break;
  218.             case '|': mypriority = 3; break;
  219.             case '&': mypriority = 4; break;
  220.             case '<': case '=': case '>': mypriority = 6; break;
  221.             case '+': case '-': mypriority = 8; break;
  222.             case '*': case '/': mypriority = 10; break;
  223.         }
  224.         if (mypriority<priority)
  225.             line[linelim++] = '(';
  226.             
  227.         switch (e->op)
  228.         {
  229.             case 'f':
  230.                 {
  231.                     register char *s;
  232.                     for (s="fixed "; line[linelim++] = *s++;);
  233.     
  234.                     linelim--;
  235.                     decompile (e->e.o.right, 30);
  236.                     break;
  237.                 }
  238.                 
  239.             case 's':
  240.                 {
  241.                     char *s;
  242.                     line[linelim++]='"';
  243.                     for(s=e->e.o.left; *s; line[linelim++] = *s++);
  244.                     line[linelim++]='"';
  245.                     break;
  246.                 }
  247.                 
  248.             case 'm':    
  249.                 line[linelim++] = '-';
  250.                 decompile (e->e.o.right, 30);
  251.                 break;
  252.                 
  253.             case '~':
  254.                 line[linelim++] = '~';
  255.                 decompile (e->e.o.right, 30);
  256.                 break;
  257.                 
  258.             case 'v':
  259.                 decodev (e->e.v);
  260.                 break;
  261.                 
  262.             case 'k':    
  263.                 sprintf (line+linelim,"%g",e->e.k);
  264.                 linelim += strlen (line+linelim);
  265.                 break;
  266.                 
  267.             case O_REDUCE('+'):
  268.             case O_REDUCE('*'):
  269.                 line[linelim++] = e->op&0177;
  270.                 line[linelim++] = '/';
  271.                 decodev (e->e.o.left);
  272.                 line[linelim++] = ':';
  273.                 decodev (e->e.o.right);
  274.                 break;
  275.                 
  276.             case 'p':
  277.                 {
  278.                     int i;
  279.                     char *cptr;
  280.                     struct lnode *ptr;
  281.                     
  282.                     line[linelim++] = 'e';
  283.                     line[linelim++] = 'x';
  284.                     line[linelim++] = 'e';
  285.                     line[linelim++] = 'c';
  286.                     line[linelim++] = '(';
  287.                     line[linelim++] = '"';
  288.                     cptr = (char *)(e->e.o.left);
  289.                     while (*cptr)
  290.                         line[linelim++] = *cptr++;
  291.                         
  292.                     line[linelim++] = '"';
  293.                     line[linelim++] = ',';
  294.                     ptr = (struct lnode *)(e->e.o.right);
  295.                     decompile ( ptr->lptr[0] );
  296.                     for( i=1; i<ptr->num; i+=1)
  297.                     {
  298.                         line[linelim++] = ',';
  299.                         decompile ( ptr->lptr[i] );
  300.                     }
  301.                     
  302.                     line[linelim++] = ')';
  303.                     break;
  304.                 }
  305.                 
  306.             case K_ABS:    case K_ACOS: case K_ASIN: case K_ATAN: case K_CEIL:
  307.             case K_COS:    case K_EXP: case K_FLOOR: case K_HYPOT: case K_LOG:
  308.             case K_LN:    case K_SIN:    case K_SQRT: case K_TAN:
  309.                 print_func(e->op);
  310.                 decompile(e->e.o.left, 99);
  311.                 break;
  312.                 
  313.             default:    
  314.                 decompile (e->e.o.left, mypriority);
  315.                 line[linelim++] = e->op;
  316.                 decompile (e->e.o.right, mypriority+1);
  317.                 break;
  318.         }
  319.         
  320.         if (mypriority<priority) 
  321.             line[linelim++] = ')';
  322.             
  323.     } 
  324.     else
  325.          line[linelim++] = '?';
  326. }
  327.  
  328. editv (row, col) {
  329.     sprintf (line, "let r%dc%d = ", row, col);
  330.     linelim = strlen(line);
  331.     editexp(row,col);
  332. }
  333.  
  334. editexp(row,col) {
  335.     register struct ent *p;
  336.     p = lookat (row, col);
  337.     if (p->flags&is_valid)
  338.     if (p->expr) {
  339.         decompile (p->expr);
  340.         line[linelim] = 0;
  341.     } else {
  342.         sprintf (line+linelim, "%g", p->v);
  343.         linelim += strlen (line+linelim);
  344.     }
  345. }
  346.  
  347. edits (row, col) {
  348.     register struct ent *p = lookat (row, col);
  349.     sprintf (line, "%sstring r%dc%d = \"",
  350.             ((p->flags&is_leftflush) ? "left" : "right"),
  351.             row, col);
  352.     linelim = strlen(line);
  353.     sprintf (line+linelim, "%s", p->label);
  354.     linelim += strlen (line+linelim);
  355. }
  356.  
  357. printfile (fname) {
  358.     FILE *f = fopen(fname, "w");
  359.     char pline[1000];
  360.     int plinelim;
  361.     register row, col;
  362.     register struct ent **p;
  363.     if (f==0)
  364.     {
  365.         error ("Can't create %s", fname);
  366.         return;
  367.     }
  368.     
  369.     for (row=0;row<=maxrow; row++)
  370.     {
  371.         register c = 0;
  372.         plinelim = 0;
  373.         for (p = &tbl[row][col=0]; col<=maxcol; col++, p++)
  374.         {
  375.             if (*p)
  376.             {
  377.                 char *s;
  378.                 while (plinelim<c) 
  379.                     pline[plinelim++] = ' ';
  380.                     
  381.                 plinelim = c;
  382.                 if ((*p)->flags&is_valid)
  383.                 {
  384.                     char h[80];
  385.                     
  386.                     sprintf (h,"%%%d.%df",fwidth[col],precision[col]);
  387.                     sprintf (pline+plinelim,h, (*p)->v);
  388.                     plinelim += strlen (pline+plinelim);
  389.                 }
  390.                 
  391.                 if (s = (*p)->label)
  392.                 {
  393.                     register char *d;
  394.                     d = pline+((*p)->flags&is_leftflush
  395.                         ? c : c-strlen(s)+fwidth[col]);
  396.                     while (d>pline+plinelim) pline[plinelim++] = ' ';
  397.                     if (d<pline)
  398.                         d = pline;
  399.                         
  400.                     while (*s)
  401.                         *d++ = *s++;
  402.                         
  403.                     if (d-pline>plinelim) 
  404.                         plinelim = d-pline;
  405.                 }
  406.             }
  407.             c += fwidth [col];
  408.         }
  409.         {
  410.             char h[80];
  411.             sprintf (h,"%%.%ds\n", plinelim);
  412.             fprintf (f,h, pline);
  413.         }
  414.     }
  415.     fclose (f);
  416. }
  417.  
  418. tblprintfile (fname)
  419. {
  420.     FILE *f = fopen(fname, "w");
  421.     register row, col;
  422.     register struct ent **p;
  423.     char coldelim = DEFCOLDELIM;
  424.  
  425.     if (f==0)
  426.     {
  427.         error ("Can't create %s", fname);
  428.         return;
  429.     }
  430.     
  431.     for (row=0;row<=maxrow; row++) 
  432.     {
  433.         register c = 0;
  434.         for (p = &tbl[row][col=0]; col<=maxcol; col++, p++)
  435.         {
  436.             if (*p)
  437.             {
  438.                 char *s;
  439.                 if ((*p)->flags&is_valid)
  440.                 {
  441.                     char h[80];
  442.                     sprintf (h,"%%.%df",precision[col]);
  443.                     fprintf (f,h, (*p)->v);
  444.                 }
  445.                 else
  446.                 if (s = (*p)->label)
  447.                 {
  448.                     fprintf (f,"%s",s);
  449.                 }
  450.                 else
  451.                     fprintf(f," ");
  452.                     
  453.             }
  454.             else
  455.                 fprintf(f," ");
  456.                 
  457.             fprintf(f,"%c",coldelim);
  458.         }
  459.         fprintf (f,"\n");
  460.     }
  461.     fclose (f);
  462. }
  463.  
  464. struct enode *copye (e, Rdelta, Cdelta)
  465. register struct enode *e; {
  466.     register struct enode *ret;
  467.     if (e==0) ret = 0;
  468.     else {
  469.         ret = (struct enode *) malloc (sizeof (struct enode));
  470.         *ret = *e;
  471.         switch (ret->op) {
  472.             case 'v':
  473.                 ret->e.v = lookat (ret->e.v->row+Rdelta, ret->e.v->col+Cdelta);
  474.                 break;
  475.             case 'k':
  476.                 break;
  477.             case 'f':
  478.                 ret->e.o.right = copye (ret->e.o.right,0,0);
  479.                 break;
  480.             default:
  481.                 ret->e.o.right = copye (ret->e.o.right,Rdelta,Cdelta);
  482.                 ret->e.o.left = copye (ret->e.o.left,Rdelta,Cdelta);
  483.             break;
  484.         }
  485.     }
  486.     return ret;
  487. }
  488.