home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / sp_sheet / viscalc / interp.c < prev    next >
C/C++ Source or Header  |  1985-11-19  |  15KB  |  616 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.  *              More mods Robert Bond, 12/86
  9.  *        Major mods to run on VMS and AMIGA, 1/17/87
  10.  */
  11.  
  12. #include "sc.h"
  13. #define DEFCOLDELIM ':'
  14.  
  15. char *malloc();
  16.  
  17. double dosum(minr, minc, maxr, maxc)
  18. int minr, minc, maxr, maxc;
  19. {
  20.     double v;
  21.     register r,c;
  22.     register struct ent *p;
  23.  
  24.     v = 0;
  25.     for (r = minr; r<=maxr; r++)
  26.     for (c = minc; c<=maxc; c++)
  27.         if ((p = tbl[r][c]) && p->flags&is_valid)
  28.         v += p->v;
  29.     return v;
  30. }
  31.  
  32. double doprod(minr, minc, maxr, maxc)
  33. int minr, minc, maxr, maxc;
  34. {
  35.     double v;
  36.     register r,c;
  37.     register struct ent *p;
  38.  
  39.     v = 1;
  40.     for (r = minr; r<=maxr; r++)
  41.     for (c = minc; c<=maxc; c++)
  42.         if ((p = tbl[r][c]) && p->flags&is_valid)
  43.         v *= p->v;
  44.     return v;
  45. }
  46.  
  47. double doavg(minr, minc, maxr, maxc)
  48. int minr, minc, maxr, maxc;
  49. {
  50.     double v;
  51.     register r,c,count;
  52.     register struct ent *p;
  53.  
  54.     v = 0;
  55.     count = 0;
  56.     for (r = minr; r<=maxr; r++)
  57.     for (c = minc; c<=maxc; c++)
  58.         if ((p = tbl[r][c]) && p->flags&is_valid) {
  59.         v += p->v;
  60.         count++;
  61.         }
  62.  
  63.     return (v / (double)count);
  64. }
  65.  
  66. double eval(e)
  67. register struct enode *e; {
  68.     if (e==0) return 0;
  69.     switch (e->op) {
  70.     case '+':    return (eval(e->e.o.left) + eval(e->e.o.right));
  71.     case '-':    return (eval(e->e.o.left) - eval(e->e.o.right));
  72.     case '*':    return (eval(e->e.o.left) * eval(e->e.o.right));
  73.     case '/':     {    double denom = eval (e->e.o.right);
  74.             return denom ? eval(e->e.o.left) / denom : 0; }
  75.     case '<':    return (eval(e->e.o.left) < eval(e->e.o.right));
  76.     case '=':    return (eval(e->e.o.left) == eval(e->e.o.right));
  77.     case '>':    return (eval(e->e.o.left) > eval(e->e.o.right));
  78.     case '&':    return (eval(e->e.o.left) != 0.0 &&
  79.                    eval(e->e.o.right) != 0.0) ? 1.0 : 0.0;
  80.     case '|':    return (eval(e->e.o.left) != 0.0 ||
  81.                    eval(e->e.o.right) != 0.0) ? 1.0 : 0.0;
  82.     case '?':    return eval(e->e.o.left) ? eval(e->e.o.right->e.o.left)
  83.                          : eval(e->e.o.right->e.o.right);
  84.     case 'm':    return (-eval(e->e.o.right));
  85.     case 'f':    return (eval(e->e.o.right));
  86.     case '~':    return (!eval(e->e.o.right));
  87.     case 'k':    return (e->e.k);
  88.     case 'v':    return (e->e.v->v);
  89.     case O_REDUCE('+'):
  90.      case O_REDUCE('*'):
  91.      case O_REDUCE('a'):
  92.         {
  93. #ifdef TOS
  94.             register r,c;
  95.         int maxr, maxc;
  96.         int minr, minc;
  97. #else
  98.             register r,c;
  99.         register maxr, maxc;
  100.         register minr, minc;
  101. #endif
  102.         maxr = ((struct ent *) e->e.o.right) -> row;
  103.         maxc = ((struct ent *) e->e.o.right) -> col;
  104.         minr = ((struct ent *) e->e.o.left) -> row;
  105.         minc = ((struct ent *) e->e.o.left) -> col;
  106.         if (minr>maxr) r = maxr, maxr = minr, minr = r;
  107.         if (minc>maxc) c = maxc, maxc = minc, minc = c;
  108.             switch (e->op) {
  109.                 case O_REDUCE('+'): return dosum(minr, minc, maxr, maxc);
  110.                  case O_REDUCE('*'): return doprod(minr, minc, maxr, maxc);
  111.                  case O_REDUCE('a'): return doavg(minr, minc, maxr, maxc);
  112.         }
  113.         }
  114.     }
  115. }
  116.  
  117. #define MAXPROP 7
  118.  
  119. EvalAll () {
  120.     int lastct,repct = 0;
  121.  
  122.     while ((lastct = RealEvalAll()) && (repct++ <= MAXPROP));
  123.  
  124.     repct--;
  125. }
  126.  
  127. int RealEvalAll () {
  128.     register i,j;
  129.     int chgct = 0;
  130.     register struct ent *p;
  131.     for (i=0; i<=maxrow; i++)
  132.     for (j=0; j<=maxcol; j++)
  133.         if ((p=tbl[i][j]) && p->expr) {
  134.         double v = eval (p->expr);
  135.         if (v != p->v) {
  136.             p->v = v; chgct++;
  137.             p->flags |= (is_changed|is_valid);
  138.         }
  139.         }
  140.     return(chgct);
  141. }
  142.  
  143. struct enode *new(op,a1,a2)
  144. struct enode *a1, *a2; {
  145.     register struct enode *p = (struct enode *) malloc (sizeof (struct enode));
  146.     p->op = op;
  147.     switch (op) {
  148.     case O_VAR: p->e.v = (struct ent *) a1; break;
  149.     case O_CONST: p->e.k = *(double *)&a1; break;
  150.     default: p->e.o.left = a1; p->e.o.right = a2;
  151.     }
  152.     return p;
  153. }
  154.  
  155. copy (dv, v1, v2)
  156. struct ent *dv, *v1, *v2;
  157. {
  158.     register r,c;
  159.     register struct ent *p;
  160.     register struct ent *n;
  161.     register deltar, deltac;
  162.     int maxr, maxc;
  163.     int minr, minc;
  164.     int dr, dc;
  165.  
  166.     dr = dv->row;
  167.     dc = dv->col;
  168.     maxr = v2->row;
  169.     maxc = v2->col;
  170.     minr = v1->row;
  171.     minc = v1->col;
  172.     if (minr>maxr) r = maxr, maxr = minr, minr = r;
  173.     if (minc>maxc) c = maxc, maxc = minc, minc = c;
  174.     if (dr+maxr-minr >= MAXROWS  || 
  175.            dc+maxc-minc >= MAXCOLS) {
  176.     error ("The table can't be any bigger");
  177.     return;
  178.     }
  179.     deltar = dr-minr;
  180.     deltac = dc-minc;
  181.     FullUpdate++;
  182.     for (r = minr; r<=maxr; r++)
  183.     for (c = minc; c<=maxc; c++) {
  184.         n = lookat (r+deltar, c+deltac);
  185.         clearent(n);
  186.         if (p = tbl[r][c]) {
  187.         n -> v = p -> v;
  188.         n -> flags = p -> flags;
  189.         n -> expr = copye(p->expr, deltar, deltac);
  190.         n -> label = 0;
  191.         if (p -> label) {
  192.             n -> label = (char *)
  193.                  malloc (strlen (p -> label) + 1);
  194.             strcpy (n -> label, p -> label);
  195.         }
  196.         }
  197.     }
  198. }
  199.  
  200. let (v, e)
  201. struct ent *v;
  202. struct enode *e; {
  203.     efree (v->expr);
  204.     if (constant(e)) {
  205.     v->v = eval(e);
  206.     v->expr = 0;
  207.     efree(e);
  208.     } else
  209.     v->expr = e;
  210.     v->flags |= (is_changed|is_valid);
  211.     changed++;
  212.     modflg++;
  213. }
  214.  
  215. clearent (v)
  216. struct ent *v; {
  217.     if (!v)
  218.     return;
  219.     label(v,"",-1);
  220.     v->v = 0;
  221.     if (v->expr)
  222.     efree(v->expr);
  223.     v->expr = 0;
  224.     v->flags |= (is_changed);
  225.     v->flags &= ~(is_valid);
  226.     changed++;
  227.     modflg++;
  228. }
  229.  
  230. constant(e)
  231. register struct enode *e; {
  232.     return e==0 || e->op == O_CONST 
  233.     || (e->op != O_VAR
  234.      && (e->op&~0177) != O_REDUCE(0)
  235.      && constant (e->e.o.left)
  236.      && constant(e->e.o.right));
  237. }
  238.  
  239. efree (e)
  240. register struct enode *e; {
  241.     if (e) {
  242.     if (e->op != O_VAR && e->op !=O_CONST && (e->op&~0177) != O_REDUCE(0)) {
  243.         efree (e->e.o.left);
  244.         efree (e->e.o.right);
  245.     }
  246.     free (e);
  247.     }
  248. }
  249.  
  250. label (v, s, flushdir)
  251. register struct ent *v;
  252. register char *s; {
  253.     if (v) {
  254.     if (flushdir==0 && v->flags&is_valid) {
  255.         register struct ent *tv;
  256.         if (v->col>0 && ((tv=lookat(v->row,v->col-1))->flags&is_valid)==0)
  257.         v = tv, flushdir = 1;
  258.         else if (((tv=lookat (v->row,v->col+1))->flags&is_valid)==0)
  259.         v = tv, flushdir = -1;
  260.         else flushdir = -1;
  261.     }
  262.     if (v->label) free(v->label);
  263.     if (s && s[0]) {
  264.         v->label = (char *) malloc (strlen(s)+1);
  265.         strcpy (v->label, s);
  266.     } else v->label = 0;
  267.     v->flags |= is_lchanged;
  268.     if (flushdir<0) v->flags |= is_leftflush;
  269.     else v->flags &= ~is_leftflush;
  270.     FullUpdate++;
  271.     modflg++;
  272.     }
  273. }
  274.  
  275. decodev (v)
  276. register struct ent *v; {
  277.     if (v) sprintf (line+linelim, "%s%d", coltoa(v->col), v->row);
  278.     else sprintf (line+linelim,"VAR?");
  279.     linelim += strlen (line+linelim);
  280. }
  281.  
  282. char *
  283. coltoa(col)
  284. int col;
  285. {
  286.     static char rname[3];
  287.     register char *p = rname;
  288.  
  289.     if (col < 0 || col > 25*26) 
  290.     debug("coltoa: invalid col: %d", col);
  291.  
  292.     if (col > 25) {
  293.     *p++ = col/26 + 'A' - 1;
  294.     col %= 26;
  295.     }
  296.     *p++ = col+'A';
  297.     *p = 0;
  298.     return(rname);
  299. }
  300.  
  301. decompile(e, priority)
  302. register struct enode *e; {
  303.     register char *s;
  304.     if (e) {
  305.     int mypriority;
  306.     switch (e->op) {
  307.     default: mypriority = 99; break;
  308.     case '?': mypriority = 1; break;
  309.     case ':': mypriority = 2; break;
  310.     case '|': mypriority = 3; break;
  311.     case '&': mypriority = 4; break;
  312.     case '<': case '=': case '>': mypriority = 6; break;
  313.     case '+': case '-': mypriority = 8; break;
  314.     case '*': case '/': mypriority = 10; break;
  315.     }
  316.     if (mypriority<priority) line[linelim++] = '(';
  317.     switch (e->op) {
  318.     case 'f':    { 
  319.                 for (s="fixed "; line[linelim++] = *s++;);
  320.                 linelim--;
  321.                 decompile (e->e.o.right, 30);
  322.                 break;
  323.             }
  324.     case 'm':    line[linelim++] = '-';
  325.             decompile (e->e.o.right, 30);
  326.             break;
  327.     case '~':    line[linelim++] = '~';
  328.             decompile (e->e.o.right, 30);
  329.             break;
  330.     case 'v':    decodev (e->e.v);
  331.             break;
  332.     case 'k':    sprintf (line+linelim,"%.8g",e->e.k);
  333.             linelim += strlen (line+linelim);
  334.             break;
  335.     case O_REDUCE('+'):
  336.             for (s="@sum("; line[linelim++] = *s++;);
  337.             goto more;
  338.     case O_REDUCE('*'):
  339.             for (s="@prod("; line[linelim++] = *s++;);
  340.             goto more;
  341.     case O_REDUCE('a'):
  342.             for (s="@avg("; line[linelim++] = *s++;);
  343.     more:        linelim--;
  344.             decodev (e->e.o.left);
  345.             line[linelim++] = ':';
  346.             decodev (e->e.o.right);
  347.             line[linelim++] = ')';
  348.             break;
  349.  
  350.     default:    decompile (e->e.o.left, mypriority);
  351.             line[linelim++] = e->op;
  352.             decompile (e->e.o.right, mypriority+1);
  353.             break;
  354.     }
  355.     if (mypriority<priority) line[linelim++] = ')';
  356.     } else line[linelim++] = '?';
  357. }
  358.  
  359. editv (row, col) {
  360.     sprintf (line, "let %s%d = ", coltoa(col), row);
  361.     linelim = strlen(line);
  362.     editexp(row,col);
  363. }
  364.  
  365. editexp(row,col) {
  366.     register struct ent *p;
  367.     p = lookat (row, col);
  368.     if (p->flags&is_valid)
  369.     if (p->expr) {
  370.         decompile (p->expr);
  371.         line[linelim] = 0;
  372.     } else {
  373.         sprintf (line+linelim, "%.8g", p->v);
  374.         linelim += strlen (line+linelim);
  375.     }
  376. }
  377.  
  378. edits (row, col) {
  379.     register struct ent *p = lookat (row, col);
  380.     sprintf (line, "%sstring %s%d = \"",
  381.             ((p->flags&is_leftflush) ? "left" : "right"),
  382.             coltoa(col), row);
  383.     linelim = strlen(line);
  384.     sprintf (line+linelim, "%s", p->label);
  385.     linelim += strlen (line+linelim);
  386. }
  387.  
  388. printfile (fname) {
  389.     FILE *f = fopen(fname, "w");
  390.     char pline[1000];
  391.     int plinelim;
  392.     register row, col;
  393.     register struct ent **p;
  394.     if (f==0) {
  395.     error ("Can't create %s", fname);
  396.     return;
  397.     }
  398.     for (row=0;row<=maxrow; row++) {
  399.     register c = 0;
  400.     plinelim = 0;
  401.     for (p = &tbl[row][col=0]; col<=maxcol; col++, p++) {
  402.         if (*p) {
  403.         char *s;
  404.         while (plinelim<c) pline[plinelim++] = ' ';
  405.         plinelim = c;
  406.         if ((*p)->flags&is_valid) {
  407.             sprintf (pline+plinelim,"%*.*f",fwidth[col],precision[col],
  408.                 (*p)->v);
  409.             plinelim += strlen (pline+plinelim);
  410.         }
  411.         if (s = (*p)->label) {
  412.             register char *d;
  413.             d = pline+((*p)->flags&is_leftflush
  414.             ? c : c-strlen(s)+fwidth[col]);
  415.             while (d>pline+plinelim) pline[plinelim++] = ' ';
  416.             if (d<pline) d = pline;
  417.             while (*s) *d++ = *s++;
  418.             if (d-pline>plinelim) plinelim = d-pline;
  419.         }
  420.         }
  421.         c += fwidth [col];
  422.     }
  423.     fprintf (f,"%.*s\n",plinelim,pline);
  424.     }
  425.     fclose (f);
  426. }
  427.  
  428. tblprintfile (fname) {
  429.     FILE *f = fopen(fname, "w");
  430.     char pline[1000];
  431.     int plinelim;
  432.     register row, col;
  433.     register struct ent **p;
  434.     char coldelim = DEFCOLDELIM;
  435.  
  436.     if (f==0) {
  437.     error ("Can't create %s", fname);
  438.     return;
  439.     }
  440.     for (row=0;row<=maxrow; row++) {
  441.     register c = 0;
  442.     plinelim = 0;
  443.     for (p = &tbl[row][col=0]; col<=maxcol; col++, p++) {
  444.         if (*p) {
  445.         char *s;
  446.         if ((*p)->flags&is_valid) {
  447.             fprintf (f,"%.*f",precision[col],
  448.                 (*p)->v);
  449.         }
  450.         if (s = (*p)->label) {
  451.                 fprintf (f,"%s",s);
  452.         }
  453.         }
  454.         fprintf(f,"%c",coldelim);
  455.     }
  456.     fprintf (f,"\n",pline);
  457.     }
  458.     fclose (f);
  459. }
  460.  
  461. struct enode *copye (e, Rdelta, Cdelta)
  462. register struct enode *e; {
  463.     register struct enode *ret;
  464.     if (e==0) ret = 0;
  465.     else {
  466.     ret = (struct enode *) malloc (sizeof (struct enode));
  467.     ret->op = e->op;
  468.     switch (ret->op) {
  469.     case 'v':
  470.         ret->e.v = lookat (e->e.v->row+Rdelta, e->e.v->col+Cdelta);
  471.         break;
  472.     case 'k':
  473.         ret->e.k = e->e.k;
  474.         break;
  475.     case 'f':
  476.         ret->e.o.right = copye (e->e.o.right,0,0);
  477.         ret->e.o.left = 0;
  478.          break;
  479.      case O_REDUCE('+'):
  480.      case O_REDUCE('*'):
  481.      case O_REDUCE('a'):
  482.          ret->e.o.right = (struct enode *) lookat (
  483.                    ((struct ent *)e->e.o.right)->row+Rdelta,
  484.                    ((struct ent *)e->e.o.right)->col+Cdelta
  485.             );
  486.          ret->e.o.left = (struct enode *) lookat (
  487.                    ((struct ent *)e->e.o.left)->row+Rdelta,
  488.                    ((struct ent *)e->e.o.left)->col+Cdelta
  489.             );
  490.         break;
  491.     default:
  492.         ret->e.o.right = copye (e->e.o.right,Rdelta,Cdelta);
  493.         ret->e.o.left = copye (e->e.o.left,Rdelta,Cdelta);
  494.         break;
  495.     }
  496.     }
  497.     return ret;
  498. }
  499.  
  500. /*
  501.  * sync_refs and sync_ref are used to remove references to
  502.  * deleted struct ents.  Note that the deleted structure must still
  503.  * be hanging around before the call, but not referenced by an entry
  504.  * in tbl.  Thus the free_ent, fix_ent calls in sc.c
  505.  */
  506.  
  507. sync_refs () {
  508.     register i,j;
  509.     register struct ent *p;
  510.     for (i=0; i<=maxrow; i++)
  511.     for (j=0; j<=maxcol; j++)
  512.         if ((p=tbl[i][j]) && p->expr)
  513.         sync_ref(p->expr);
  514. }
  515.  
  516.  
  517. sync_ref(e)
  518. register struct enode *e;
  519. {
  520.     if (e==0)
  521.     return;
  522.     else {
  523.     switch (e->op) {
  524.     case 'v':
  525.         e->e.v = lookat(e->e.v->row, e->e.v->col);
  526.         break;
  527.     case 'k':
  528.         break;
  529.      case O_REDUCE('+'):
  530.      case O_REDUCE('*'):
  531.      case O_REDUCE('a'):
  532.          e->e.o.right = (struct enode *) lookat (
  533.                    ((struct ent *)e->e.o.right)->row,
  534.                    ((struct ent *)e->e.o.right)->col
  535.             );
  536.          e->e.o.left = (struct enode *) lookat (
  537.                    ((struct ent *)e->e.o.left)->row,
  538.                    ((struct ent *)e->e.o.left)->col
  539.             );
  540.         break;
  541.     default:
  542.         sync_ref(e->e.o.right);
  543.         sync_ref(e->e.o.left);
  544.         break;
  545.     }
  546.     }
  547. }
  548.  
  549. hiderow(arg)
  550. {
  551.     register int r1;
  552.     register int r2;
  553.  
  554.     r1 = currow;
  555.     r2 = r1 + arg - 1;
  556.     if (r1 < 0 || r1 > r2) {
  557.     error("Invalid Range");
  558.     return;
  559.     }
  560.     if (r2 > MAXROWS-2) {
  561.     error("You can't hide the last row");
  562.     return;
  563.     }
  564.     FullUpdate++;
  565.     while (r1 <= r2)
  566.     hidden_row[r1++] = 1;
  567. }
  568.  
  569. hidecol(arg)
  570. {
  571.     register int c1;
  572.     register int c2;
  573.  
  574.     c1 = curcol;
  575.     c2 = c1 + arg - 1;
  576.     if (c1 < 0 || c1 > c2) {
  577.     error("Invalid Range");
  578.     return;
  579.     }
  580.     if (c2 > MAXCOLS-2) {
  581.     error("You can't hide the last col");
  582.     return;
  583.     }
  584.     FullUpdate++;
  585.     while (c1 <= c2)
  586.     hidden_col[c1++] = 1;
  587. }
  588.  
  589. showrow(r1, r2)
  590. {
  591.     if (r1 < 0 || r1 > r2) {
  592.     error("Invalid Range");
  593.     return;
  594.     }
  595.     if (r2 > MAXROWS-1) {
  596.     r2 = MAXROWS-1;
  597.     }
  598.     FullUpdate++;
  599.     while (r1 <= r2)
  600.     hidden_row[r1++] = 0;
  601. }
  602.  
  603. showcol(c1, c2)
  604. {
  605.     if (c1 < 0 || c1 > c2) {
  606.     error("Invalid Range");
  607.     return;
  608.     }
  609.     if (c2 > MAXCOLS-1) {
  610.     c2 = MAXCOLS-1;
  611.     }
  612.     FullUpdate++;
  613.     while (c1 <= c2)
  614.     hidden_col[c1++] = 0;
  615. }
  616.