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