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