home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / EFFO / pd7.lzh / SRC / interp.c < prev    next >
Text File  |  1990-05-06  |  49KB  |  1,845 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.  *              More mods by Alan Silverstein, 3-4/88, see list of changes.
  10.  *              $Revision: 6.1 $
  11.  */
  12.  
  13. #include <math.h>
  14. #include <signal.h>
  15. #include <setjmp.h>
  16. #include <stdio.h>
  17.  
  18. extern int errno;               /* set by math functions */
  19. #if defined(BSD42) | defined(OSK)
  20. #  include <strings.h>
  21. #  ifdef OSK
  22. #        include <time.h>
  23. #  else
  24. #    include <sys/time.h>
  25. #  endif
  26. #  ifndef strchr
  27. #  define strchr rindex
  28. #endif
  29. #else
  30. #  include <time.h>
  31. #  ifndef SYSIII
  32. #    include <string.h>
  33. #  endif
  34. #endif
  35.  
  36. #include <curses.h>
  37. #include "sc.h"
  38.  
  39. #if defined(BSD42) || defined(BSD43)
  40. char *re_comp();
  41. #endif
  42. #if defined(SYSV2) || defined(SYSV3)
  43. char *regcmp();
  44. char *regex();
  45. #endif
  46.  
  47. #ifdef SIGVOID
  48.     void quit();
  49. #else
  50.     int quit();
  51. #endif
  52.  
  53. /* Use this structure to save the the last 'g' command */
  54.  
  55. struct go_save {
  56.         int g_type;
  57.         double g_n;
  58.         char *g_s;
  59.         int  g_row;
  60.         int  g_col;
  61. } gs;
  62.  
  63. /* g_type can be: */
  64.  
  65. #define G_NONE 0                        /* Starting value - must be 0*/
  66. #define G_NUM 1
  67. #define G_STR 2
  68. #define G_CELL 3
  69.  
  70. extern FILE *popen();
  71.  
  72. jmp_buf fpe_save;
  73. int     exprerr;           /* Set by eval() and seval() if expression errors */
  74. double  prescale = 1.0;    /* Prescale for constants in let() */
  75. int     extfunc  = 0;      /* Enable/disable external functions */
  76. int     loading = 0;       /* Set when readfile() is active */
  77. double fn1_eval();
  78. double fn2_eval();
  79.  
  80. #ifndef PI
  81. #define PI (double)3.14159265358979323846
  82. #endif
  83. #define dtr(x) ((x)*(PI/(double)180.0))
  84. #define rtd(x) ((x)*(180.0/(double)PI))
  85.  
  86. #ifdef OSK
  87. double atan2(e1,e2)
  88. {
  89.   return(atan(e1/e2));
  90. }
  91. #endif
  92.  
  93. double finfunc(fun,v1,v2,v3)
  94. int fun;
  95. double v1,v2,v3;
  96. {
  97.         double answer,p;
  98.  
  99.         p = fn2_eval(pow, 1 + v2, v3);
  100.  
  101.         switch(fun)
  102.         {
  103.         case PV:
  104.                 answer = v1 * (1 - 1/p) / v2;
  105.                 break;
  106.         case FV:
  107.                 answer = v1 * (p - 1) / v2;
  108.                 break;
  109.         case PMT:
  110.                 answer = v1 * v2 / (1 - 1/p);
  111.                 break;
  112.         }
  113.         return(answer);
  114. }
  115.  
  116. char *
  117. dostindex( val, minr, minc, maxr, maxc)
  118. double val;
  119. int minr, minc, maxr, maxc;
  120. {
  121.     register r,c;
  122.     register struct ent *p;
  123.     char *pr;
  124.     int x;
  125.  
  126.     x = (int) val;
  127.     r = minr; c = minc;
  128.     p = 0;
  129.     if ( minr == maxr ) { /* look along the row */
  130.         c = minc + x - 1;
  131.         if (c <= maxc && c >=minc)
  132.             p = tbl[r][c];
  133.     } else if ( minc == maxc ) { /* look down the column */
  134.         r = minr + x - 1;
  135.         if (r <= maxr && r >=minr)
  136.             p = tbl[r][c];
  137.     } else {
  138.         error ("range specified to @stindex");
  139.         return(0);
  140.     }
  141.     if (p && p->label) {
  142.         pr = xmalloc((unsigned)(strlen(p->label)+1));
  143.         (void)strcpy(pr, p->label);
  144.         return (pr);
  145.      } else
  146.         return(0);
  147. }
  148.  
  149. double
  150. doindex( val, minr, minc, maxr, maxc)
  151. double val;
  152. int minr, minc, maxr, maxc;
  153. {
  154.     double v;
  155.     register r,c;
  156.     register struct ent *p;
  157.     int x;
  158.  
  159.     x = (int) val;
  160.     v = 0;
  161.     r = minr; c = minc;
  162.     if ( minr == maxr ) { /* look along the row */
  163.         c = minc + x - 1;
  164.         if (c <= maxc && c >=minc
  165.                 && (p = tbl[r][c] ) && p->flags&is_valid )
  166.                                         return p->v;
  167.         }
  168.     else if ( minc == maxc ){ /* look down the column */
  169.         r = minr + x - 1;
  170.         if (r <= maxr && r >=minr
  171.                 && (p = tbl[r][c] ) && p->flags&is_valid )
  172.                                         return p->v;
  173.         }
  174.     else error(" range specified to @index");
  175.     return v;
  176. }
  177.  
  178. double
  179. dolookupn( val, minr, minc, maxr, maxc)
  180. double val;
  181. int minr, minc, maxr, maxc;
  182. {
  183.     double v;
  184.     register r,c;
  185.     register struct ent *p;
  186.  
  187.     v = 0;
  188.     r = minr; c = minc;
  189.     if ( minr == maxr ) { /* look along the row */
  190.         for ( c = minc; c <= maxc; c++) {
  191.                 if ( (p = tbl[r][c] ) && p->flags&is_valid ) {
  192.                         if(p->v <= val) {
  193.                                 p = tbl[r+1][c];
  194.                                 if ( p && p->flags&is_valid)
  195.                                         v = p->v;
  196.                                 }
  197.                         else return v;
  198.                         }
  199.                 }
  200.         }
  201.     else if ( minc == maxc ){ /* look down the column */
  202.         for ( r = minr; r <= maxr; r++) {
  203.                 if ( (p = tbl[r][c] ) && p->flags&is_valid ) {
  204.                         if(p->v <= val) {
  205.                                 p = tbl[r][c+1];
  206.                                 if ( p && p->flags&is_valid)
  207.                                         v = p->v;
  208.                                 }
  209.                         else return v;
  210.                         }
  211.                 }
  212.         }
  213.     else error(" range specified to @lookup");
  214.     return v;
  215. }
  216.  
  217. double
  218. dolookups(s, minr, minc, maxr, maxc)
  219. char *s;
  220. int minr, minc, maxr, maxc;
  221. {
  222.     double v;
  223.     register r,c;
  224.     register struct ent *p;
  225.  
  226.     v = 0;
  227.     r = minr; c = minc;
  228.     if ( minr == maxr ) { /* look along the row */
  229.         for ( c = minc; c <= maxc; c++) {
  230.             if ( (p = tbl[r][c] ) && p->label) {
  231.                 if(strcmp(s,p->label) == 0) {
  232.                     p = tbl[r+1][c];
  233.                     xfree(s);
  234.                     if ( p && p->flags & is_valid)
  235.                         return(p->v);
  236.                 }
  237.             }
  238.         }
  239.     } else if ( minc == maxc ) { /* look down the column */
  240.         for ( r = minr; r <= maxr; r++) {
  241.             if ( (p = tbl[r][c] ) && p->label) {
  242.                 if(strcmp(s,p->label) == 0) {
  243.                     p = tbl[r][c+1];
  244.                     xfree(s);
  245.                     if ( p && p->flags & is_valid)
  246.                         return(p->v);
  247.                 }
  248.             }
  249.         }
  250.     } else error(" range specified to @lookup");
  251.     xfree(s);
  252.     return v;
  253. }
  254.  
  255. double
  256. dosum(minr, minc, maxr, maxc)
  257. int minr, minc, maxr, maxc;
  258. {
  259.     double v;
  260.     register r,c;
  261.     register struct ent *p;
  262.  
  263.     v = 0;
  264.     for (r = minr; r<=maxr; r++)
  265.         for (c = minc; c<=maxc; c++)
  266.             if ((p = tbl[r][c]) && p->flags&is_valid)
  267.                 v += p->v;
  268.     return v;
  269. }
  270.  
  271. double
  272. doprod(minr, minc, maxr, maxc)
  273. int minr, minc, maxr, maxc;
  274. {
  275.     double v;
  276.     register r,c;
  277.     register struct ent *p;
  278.  
  279.     v = 1;
  280.     for (r = minr; r<=maxr; r++)
  281.         for (c = minc; c<=maxc; c++)
  282.             if ((p = tbl[r][c]) && p->flags&is_valid)
  283.                 v *= p->v;
  284.     return v;
  285. }
  286.  
  287. double
  288. doavg(minr, minc, maxr, maxc)
  289. int minr, minc, maxr, maxc;
  290. {
  291.     double v;
  292.     register r,c,count;
  293.     register struct ent *p;
  294.  
  295.     v = 0;
  296.     count = 0;
  297.     for (r = minr; r<=maxr; r++)
  298.         for (c = minc; c<=maxc; c++)
  299.             if ((p = tbl[r][c]) && p->flags&is_valid) {
  300.                 v += p->v;
  301.                 count++;
  302.             }
  303.  
  304.     if (count == 0)
  305.         return ((double) 0);
  306.  
  307.     return (v / (double)count);
  308. }
  309.  
  310. double
  311. dostddev(minr, minc, maxr, maxc)
  312. int minr, minc, maxr, maxc;
  313. {
  314.     double lp, rp, v, nd;
  315.     register r,c,n;
  316.     register struct ent *p;
  317.  
  318.     n = 0;
  319.     lp = 0;
  320.     rp = 0;
  321.     for (r = minr; r<=maxr; r++)
  322.         for (c = minc; c<=maxc; c++)
  323.             if ((p = tbl[r][c]) && p->flags&is_valid) {
  324.                 v = p->v;
  325.                 lp += v*v;
  326.                 rp += v;
  327.                 n++;
  328.             }
  329.  
  330.     if ((n == 0) || (n == 1))
  331.         return ((double) 0);
  332.     nd = (double)n;
  333.     return (sqrt((nd*lp-rp*rp)/(nd*(nd-1))));
  334. }
  335.  
  336. double
  337. domax(minr, minc, maxr, maxc)
  338. int minr, minc, maxr, maxc;
  339. {
  340.     double v;
  341.     register r,c,count;
  342.     register struct ent *p;
  343.  
  344.     count = 0;
  345.     for (r = minr; r<=maxr; r++)
  346.         for (c = minc; c<=maxc; c++)
  347.             if ((p = tbl[r][c]) && p->flags&is_valid) {
  348.                 if (!count) {
  349.                     v = p->v;
  350.                     count++;
  351.                 } else if (p->v > v)
  352.                     v = p->v;
  353.             }
  354.  
  355.     if (count == 0)
  356.         return ((double) 0);
  357.  
  358.     return (v);
  359. }
  360.  
  361. double
  362. domin(minr, minc, maxr, maxc)
  363. int minr, minc, maxr, maxc;
  364. {
  365.     double v;
  366.     register r,c,count;
  367.     register struct ent *p;
  368.  
  369.     count = 0;
  370.     for (r = minr; r<=maxr; r++)
  371.         for (c = minc; c<=maxc; c++)
  372.             if ((p = tbl[r][c]) && p->flags&is_valid) {
  373.                 if (!count) {
  374.                     v = p->v;
  375.                     count++;
  376.                 } else if (p->v < v)
  377.                     v = p->v;
  378.             }
  379.  
  380.     if (count == 0)
  381.         return ((double) 0);
  382.  
  383.     return (v);
  384. }
  385.  
  386. double
  387. dotime(which, when)
  388. int which;
  389. double when;
  390. {
  391.         long time();
  392.  
  393.         static long t_cache;
  394.         static struct tm *tp;
  395.         long tloc;
  396.  
  397.         if (which == NOW)
  398.             return (double)time((long *)0);
  399.  
  400.         tloc = (long)when;
  401.  
  402.         if (tloc != t_cache) {
  403.             tp = localtime(&tloc);
  404.             tp->tm_mon += 1;
  405.             tp->tm_year += 1900;
  406.             t_cache = tloc;
  407.         }
  408.  
  409.         switch (which) {
  410.                 case HOUR: return((double)(tp->tm_hour));
  411.                 case MINUTE: return((double)(tp->tm_min));
  412.                 case SECOND: return((double)(tp->tm_sec));
  413.                 case MONTH: return((double)(tp->tm_mon));
  414.                 case DAY: return((double)(tp->tm_mday));
  415.                 case YEAR: return((double)(tp->tm_year));
  416.         }
  417.         /* Safety net */
  418.         return (0.0);
  419. }
  420.  
  421. double
  422. doston(s)
  423. char *s;
  424. {
  425.     char *strtof();
  426.     double v;
  427.  
  428.     if (!s)
  429.         return((double)0.0);
  430.  
  431.     (void)strtof(s, &v);
  432.     xfree(s);
  433.     return(v);
  434. }
  435.  
  436. double
  437. doeqs(s1, s2)
  438. char *s1, *s2;
  439. {
  440.     double v;
  441.  
  442.     if (!s1 && !s2)
  443.         return(1.0);
  444.  
  445.     if (!s1 || !s2)
  446.         v = 0.0;
  447.     else if (strcmp(s1, s2) == 0)
  448.         v = 1.0;
  449.     else
  450.         v = 0.0;
  451.  
  452.     if (s1)
  453.         xfree(s1);
  454.  
  455.     if (s2)
  456.         xfree(s2);
  457.  
  458.     return(v);
  459. }
  460.  
  461.  
  462. /*
  463.  * Given a string representing a column name and a value which is a column
  464.  * number, return a pointer to the selected cell's entry, if any, else 0.  Use
  465.  * only the integer part of the column number.  Always free the string.
  466.  */
  467.  
  468. struct ent *
  469. getent (colstr, rowdoub)
  470.     char *colstr;
  471.     double rowdoub;
  472. {
  473.     int collen;         /* length of string */
  474.     int row, col;       /* integer values   */
  475.     struct ent *ep = 0; /* selected entry   */
  476.  
  477.     if (((row = (int) floor (rowdoub)) >= 0)
  478.      && (row < MAXROWS)                         /* in range */
  479.      && ((collen = strlen (colstr)) <= 2)       /* not too long */
  480.      && ((col = atocol (colstr, collen)) >= 0)
  481.      && (col < MAXCOLS))                        /* in range */
  482.     {
  483.         ep = tbl [row] [col];
  484.     }
  485.  
  486.     xfree (colstr);
  487.     return (ep);
  488. }
  489.  
  490.  
  491. /*
  492.  * Given a string representing a column name and a value which is a column
  493.  * number, return the selected cell's numeric value, if any.
  494.  */
  495.  
  496. double
  497. donval (colstr, rowdoub)
  498.     char *colstr;
  499.     double rowdoub;
  500. {
  501.     struct ent *ep;
  502.  
  503.     return (((ep = getent (colstr, rowdoub)) && ((ep -> flags) & is_valid)) ?
  504.             (ep -> v) : 0);
  505. }
  506.  
  507.  
  508. /*
  509.  *      The list routines (e.g. dolmax) are called with an LMAX enode.
  510.  *      The left pointer is a chain of ELIST nodes, the right pointer
  511.  *      is a value.
  512.  */
  513. double
  514. dolmax(ep)
  515. struct enode *ep;
  516. {
  517.         register int count = 0;
  518.         register double maxval = 0; /* Assignment to shut up lint */
  519.         register struct enode *p;
  520.         register double v;
  521.  
  522.         for (p = ep; p; p = p->e.o.left) {
  523.                 v = eval(p->e.o.right);
  524.                 if (!count || v > maxval) {
  525.                         maxval = v; count++;
  526.                 }
  527.         }
  528.         if (count) return maxval;
  529.         else return 0.0;
  530. }
  531.  
  532. double
  533. dolmin(ep)
  534. struct enode *ep;
  535. {
  536.         register int count = 0;
  537.         register double minval = 0; /* Assignment to shut up lint */
  538.         register struct enode *p;
  539.         register double v;
  540.  
  541.         for (p = ep; p; p = p->e.o.left) {
  542.                 v = eval(p->e.o.right);
  543.                 if (!count || v < minval) {
  544.                         minval = v; count++;
  545.                 }
  546.         }
  547.         if (count) return minval;
  548.         else return 0.0;
  549. }
  550.  
  551. double
  552. eval(e)
  553. register struct enode *e;
  554. {
  555.  
  556.     if (e==0) return 0;
  557.     switch (e->op) {
  558.         case '+':       return (eval(e->e.o.left) + eval(e->e.o.right));
  559.         case '-':       return (eval(e->e.o.left) - eval(e->e.o.right));
  560.         case '*':       return (eval(e->e.o.left) * eval(e->e.o.right));
  561.         case '/':       return (eval(e->e.o.left) / eval(e->e.o.right));
  562.         case '%':     { double num, denom;
  563.                         num = floor(eval(e->e.o.left));
  564.                         denom = floor(eval (e->e.o.right));
  565.                         return denom ? num - floor(num/denom)*denom : 0; }
  566.         case '^':       return (fn2_eval(pow,eval(e->e.o.left),eval(e->e.o.right)));
  567.         case '<':       return (eval(e->e.o.left) < eval(e->e.o.right));
  568.         case '=':       return (eval(e->e.o.left) == eval(e->e.o.right));
  569.         case '>':       return (eval(e->e.o.left) > eval(e->e.o.right));
  570.         case '&':       return (eval(e->e.o.left) && eval(e->e.o.right));
  571.         case '|':       return (eval(e->e.o.left) || eval(e->e.o.right));
  572.         case '?':       return eval(e->e.o.left) ? eval(e->e.o.right->e.o.left)
  573.                                                 : eval(e->e.o.right->e.o.right);
  574.         case 'm':       return (-eval(e->e.o.right));
  575.         case 'f':       return (eval(e->e.o.right));
  576.         case '~':       return (eval(e->e.o.right) == 0.0);
  577.         case 'k':       return (e->e.k);
  578.         case 'v':       return (e->e.v.vp->v);
  579.         case INDEX:
  580.         case LOOKUP:
  581.                     {   register r,c;
  582.                 register maxr, maxc;
  583.                 register minr, minc;
  584.                 maxr = e->e.o.right->e.r.right.vp -> row;
  585.                 maxc = e->e.o.right->e.r.right.vp -> col;
  586.                 minr = e->e.o.right->e.r.left.vp -> row;
  587.                 minc = e->e.o.right->e.r.left.vp -> col;
  588.                 if (minr>maxr) r = maxr, maxr = minr, minr = r;
  589.                 if (minc>maxc) c = maxc, maxc = minc, minc = c;
  590.                 switch(e->op){
  591.                 case LOOKUP:
  592.                 if (etype(e->e.o.left) == NUM)
  593.                     return dolookupn(eval(e->e.o.left), minr, minc, maxr, maxc);
  594.                 else
  595.                     return dolookups(seval(e->e.o.left),minr, minc, maxr, maxc);
  596.                 case INDEX:
  597.                 return doindex(eval(e->e.o.left), minr, minc, maxr, maxc);
  598.                 }
  599.                 }
  600.         case REDUCE | '+':
  601.         case REDUCE | '*':
  602.         case REDUCE | 'a':
  603.         case REDUCE | 's':
  604.         case REDUCE | MAX:
  605.         case REDUCE | MIN:
  606.             {   register r,c;
  607.                 register maxr, maxc;
  608.                 register minr, minc;
  609.                 maxr = e->e.r.right.vp -> row;
  610.                 maxc = e->e.r.right.vp -> col;
  611.                 minr = e->e.r.left.vp -> row;
  612.                 minc = e->e.r.left.vp -> col;
  613.                 if (minr>maxr) r = maxr, maxr = minr, minr = r;
  614.                 if (minc>maxc) c = maxc, maxc = minc, minc = c;
  615.                 switch (e->op) {
  616.                     case REDUCE | '+': return dosum(minr, minc, maxr, maxc);
  617.                     case REDUCE | '*': return doprod(minr, minc, maxr, maxc);
  618.                     case REDUCE | 'a': return doavg(minr, minc, maxr, maxc);
  619.                     case REDUCE | 's': return dostddev(minr, minc, maxr, maxc);
  620.                     case REDUCE | MAX: return domax(minr, minc, maxr, maxc);
  621.                     case REDUCE | MIN: return domin(minr, minc, maxr, maxc);
  622.                 }
  623.             }
  624.         case ACOS:       return (fn1_eval( acos, eval(e->e.o.right)));
  625.         case ASIN:       return (fn1_eval( asin, eval(e->e.o.right)));
  626.         case ATAN:       return (fn1_eval( atan, eval(e->e.o.right)));
  627.         case ATAN2:      return (fn2_eval( atan2, eval(e->e.o.left), eval(e->e.o.right)));
  628.         case CEIL:       return (fn1_eval( ceil, eval(e->e.o.right)));
  629.         case COS:        return (fn1_eval( cos, eval(e->e.o.right)));
  630.         case EXP:        return (fn1_eval( exp, eval(e->e.o.right)));
  631.         case FABS:       return (fn1_eval( fabs, eval(e->e.o.right)));
  632.         case FLOOR:      return (fn1_eval( floor, eval(e->e.o.right)));
  633.         case HYPOT:      return (fn2_eval( hypot, eval(e->e.o.left), eval(e->e.o.right)));
  634.         case LOG:        return (fn1_eval( log, eval(e->e.o.right)));
  635.         case LOG10:      return (fn1_eval( log10, eval(e->e.o.right)));
  636.         case POW:        return (fn2_eval( pow, eval(e->e.o.left), eval(e->e.o.right)));
  637.         case SIN:        return (fn1_eval( sin, eval(e->e.o.right)));
  638.         case SQRT:       return (fn1_eval( sqrt, eval(e->e.o.right)));
  639.         case TAN:        return (fn1_eval( tan, eval(e->e.o.right)));
  640.         case DTR:        return (dtr(eval(e->e.o.right)));
  641.         case RTD:        return (rtd(eval(e->e.o.right)));
  642.         case RND:        {
  643.                             double temp;
  644.                             temp = eval(e->e.o.right);
  645.                             return(temp-floor(temp) < 0.5 ?
  646.                                              floor(temp) : ceil(temp));
  647.                          }
  648.         case FV:
  649.         case PV:
  650.         case PMT:       return(finfunc(e->op,eval(e->e.o.left),
  651.                                    eval(e->e.o.right->e.o.left),
  652.                                       eval(e->e.o.right->e.o.right)));
  653.         case HOUR:       return (dotime(HOUR, eval(e->e.o.right)));
  654.         case MINUTE:     return (dotime(MINUTE, eval(e->e.o.right)));
  655.         case SECOND:     return (dotime(SECOND, eval(e->e.o.right)));
  656.         case MONTH:      return (dotime(MONTH, eval(e->e.o.right)));
  657.         case DAY:        return (dotime(DAY, eval(e->e.o.right)));
  658.         case YEAR:       return (dotime(YEAR, eval(e->e.o.right)));
  659.         case NOW:        return (dotime(NOW, (double)0.0));
  660.         case STON:       return (doston(seval(e->e.o.right)));
  661.         case EQS:        return (doeqs(seval(e->e.o.right),seval(e->e.o.left)));
  662.         case LMAX:       return dolmax(e);
  663.         case LMIN:       return dolmin(e);
  664.         case NVAL:       return (donval(seval(e->e.o.left),eval(e->e.o.right)));
  665.         default:         error ("Illegal numeric expression");
  666.                          exprerr = 1;
  667.                          return((double)0.0);
  668.     }
  669. #ifdef sequent
  670.     return((double)0.0);        /* Quiet a questionable compiler complaint */
  671. #endif
  672. }
  673.  
  674. #ifdef SIGVOID
  675. void
  676. #endif
  677. eval_fpe() /* Trap for FPE errors in eval */
  678. {
  679. #ifdef OSK
  680.         sigmask(0);
  681. #endif
  682.         longjmp(fpe_save, 1);
  683. }
  684.  
  685. double fn1_eval(fn, arg)
  686. double (*fn)();
  687. double arg;
  688. {
  689.         double res;
  690.         errno = 0;
  691.         res = (*fn)(arg);
  692.         if(errno)
  693.           eval_fpe();
  694.  
  695.         return res;
  696. }
  697.  
  698. double fn2_eval(fn, arg1, arg2)
  699. double (*fn)();
  700. double arg1, arg2;
  701. {
  702.         double res;
  703.         errno = 0;
  704.         res = (*fn)(arg1, arg2);
  705.         if(errno)
  706.             eval_fpe();
  707.  
  708.         return res;
  709. }
  710.  
  711. /*
  712.  * Rules for string functions:
  713.  * Take string arguments which they xfree.
  714.  * All returned strings are assumed to be xalloced.
  715.  */
  716.  
  717. char *
  718. docat(s1, s2)
  719. register char *s1, *s2;
  720. {
  721.     register char *p;
  722.     char *arg1, *arg2;
  723.  
  724.     if (!s1 && !s2)
  725.         return(0);
  726.     arg1 = s1 ? s1 : "";
  727.     arg2 = s2 ? s2 : "";
  728.     p = xmalloc((unsigned)(strlen(arg1)+strlen(arg2)+1));
  729.     (void) strcpy(p, arg1);
  730.     (void) strcat(p, arg2);
  731.     if (s1)
  732.         xfree(s1);
  733.     if (s2)
  734.         xfree(s2);
  735.     return(p);
  736. }
  737.  
  738. char *
  739. dodate(tloc)
  740. long tloc;
  741. {
  742.     char *tp;
  743.     char *p;
  744.  
  745.     tp = ctime(&tloc);
  746.     tp[24] = 0;
  747.     p = xmalloc((unsigned)25);
  748.     (void) strcpy(p, tp);
  749.     return(p);
  750. }
  751.  
  752.  
  753. char *
  754. dofmt(fmtstr, v)
  755. char *fmtstr;
  756. double v;
  757. {
  758.     char buff[1024];
  759.     char *p;
  760.  
  761.     if (!fmtstr)
  762.         return(0);
  763.     (void)sprintf(buff, fmtstr, v);
  764.     p = xmalloc((unsigned)(strlen(buff)+1));
  765.     (void) strcpy(p, buff);
  766.     xfree(fmtstr);
  767.     return(p);
  768. }
  769.  
  770.  
  771. /*
  772.  * Given a command name and a value, run the command with the given value and
  773.  * read and return its first output line (only) as an allocated string, always
  774.  * a copy of prevstr, which is set appropriately first unless external
  775.  * functions are disabled, in which case the previous value is used.  The
  776.  * handling of prevstr and freeing of command is tricky.  Returning an
  777.  * allocated string in all cases, even if null, insures cell expressions are
  778.  * written to files, etc.
  779.  */
  780.  
  781. #ifdef VMS
  782. char *
  783. doext(command, value)
  784. char *command;
  785. double value;
  786. {
  787.     error("Warning: External functions unavailable on VMS");
  788.     if (command)
  789.         xfree(command);
  790.     return (strcpy (xmalloc((unsigned) 1), "\0"));
  791. }
  792.  
  793. #else /* VMS */
  794.  
  795. char *
  796. doext (command, value)
  797. char   *command;
  798. double value;
  799. {
  800.     static char *prevstr = 0;   /* previous result */
  801.     char buff[1024];            /* command line/return, not permanently alloc */
  802.  
  803.     if (!prevstr) {
  804.         prevstr = xmalloc((unsigned)1);
  805.         *prevstr = 0;
  806.     }
  807.     if (!extfunc)    {
  808.         error ("Warning: external functions disabled; using %s value",
  809.                 prevstr ? "previous" : "null");
  810.  
  811.         if (command) xfree (command);
  812.     } else {
  813.         if (prevstr) xfree (prevstr);           /* no longer needed */
  814.         prevstr = 0;
  815.  
  816.         if ((! command) || (! *command)) {
  817.             error ("Warning: external function given null command name");
  818.             if (command) xfree (command);
  819.         } else {
  820.             FILE *pp;
  821.  
  822.             (void) sprintf (buff, "%s %g", command, value); /* build cmd line */
  823.             xfree (command);
  824.  
  825.             error ("Running external function...");
  826.             (void) refresh();
  827.  
  828.             if ((pp = popen (buff, "r")) == (FILE *) NULL)      /* run it */
  829.                 error ("Warning: running \"%s\" failed", buff);
  830.             else {
  831.                 if (fgets (buff, 1024, pp) == NULL)     /* one line */
  832.                     error ("Warning: external function returned nothing");
  833.                 else {
  834.                     char *cp;
  835.  
  836.                     error ("");                         /* erase notice */
  837.                     buff[1023] = 0;
  838.  
  839.                     if (cp = strchr (buff, '\n'))       /* contains newline */
  840.                         *cp = 0;                        /* end string there */
  841.  
  842.                     (void) strcpy (prevstr =
  843.                          xmalloc ((unsigned) (strlen (buff) + 1)), buff);
  844.                          /* save alloc'd copy */
  845.                 }
  846.                 (void) pclose (pp);
  847.  
  848.             } /* else */
  849.         } /* else */
  850.     } /* else */
  851.     return (strcpy (xmalloc ((unsigned) (strlen (prevstr) + 1)), prevstr));
  852. }
  853.  
  854. #endif /* VMS */
  855.  
  856.  
  857. /*
  858.  * Given a string representing a column name and a value which is a column
  859.  * number, return the selected cell's string value, if any.  Even if none,
  860.  * still allocate and return a null string so the cell has a label value so
  861.  * the expression is saved in a file, etc.
  862.  */
  863.  
  864. char *
  865. dosval (colstr, rowdoub)
  866.     char *colstr;
  867.     double rowdoub;
  868. {
  869.     struct ent *ep;
  870.     char *label;
  871.  
  872.     label = (ep = getent (colstr, rowdoub)) ? (ep -> label) : "";
  873.     return (strcpy (xmalloc ((unsigned) (strlen (label) + 1)), label));
  874. }
  875.  
  876.  
  877. /*
  878.  * Substring:  Note that v1 and v2 are one-based to users, but zero-based
  879.  * when calling this routine.
  880.  */
  881.  
  882. char *
  883. dosubstr(s, v1, v2)
  884. char *s;
  885. register int v1,v2;
  886. {
  887.     register char *s1, *s2;
  888.     char *p;
  889.  
  890.     if (!s)
  891.         return(0);
  892.  
  893.     if (v2 >= strlen (s))               /* past end */
  894.         v2 =  strlen (s) - 1;           /* to end   */
  895.  
  896.     if (v1 < 0 || v1 > v2) {            /* out of range, return null string */
  897.         xfree(s);
  898.         p = xmalloc((unsigned)1);
  899.         p[0] = 0;
  900.         return(p);
  901.     }
  902.     s2 = p = xmalloc((unsigned)(v2-v1+2));
  903.     s1 = &s[v1];
  904.     for(; v1 <= v2; s1++, s2++, v1++)
  905.         *s2 = *s1;
  906.     *s2 = 0;
  907.     xfree(s);
  908.     return(p);
  909. }
  910.  
  911. char *
  912. seval(se)
  913. register struct enode *se;
  914. {
  915.     register char *p;
  916.  
  917.     if (se==0) return 0;
  918.     switch (se->op) {
  919.         case O_SCONST: p = xmalloc((unsigned)(strlen(se->e.s)+1));
  920.                      (void) strcpy(p, se->e.s);
  921.                      return(p);
  922.         case O_VAR:    {
  923.                         struct ent *ep;
  924.                         ep = se->e.v.vp;
  925.  
  926.                         if (!ep->label)
  927.                             return(0);
  928.                         p = xmalloc((unsigned)(strlen(ep->label)+1));
  929.                         (void) strcpy(p, ep->label);
  930.                         return(p);
  931.                      }
  932.         case '#':    return(docat(seval(se->e.o.left), seval(se->e.o.right)));
  933.         case 'f':    return(seval(se->e.o.right));
  934.         case '?':    return(eval(se->e.o.left) ? seval(se->e.o.right->e.o.left)
  935.                                              : seval(se->e.o.right->e.o.right));
  936.         case DATE:   return(dodate((long)(eval(se->e.o.right))));
  937.         case FMT:    return(dofmt(seval(se->e.o.left), eval(se->e.o.right)));
  938.         case STINDEX:
  939.                 {       register r,c;
  940.                 register maxr, maxc;
  941.                 register minr, minc;
  942.                 maxr = se->e.o.right->e.r.right.vp -> row;
  943.                 maxc = se->e.o.right->e.r.right.vp -> col;
  944.                 minr = se->e.o.right->e.r.left.vp -> row;
  945.                 minc = se->e.o.right->e.r.left.vp -> col;
  946.                 if (minr>maxr) r = maxr, maxr = minr, minr = r;
  947.                 if (minc>maxc) c = maxc, maxc = minc, minc = c;
  948.                 return dostindex(eval(se->e.o.left), minr, minc, maxr, maxc);
  949.                 }
  950.         case EXT:    return(doext(seval(se->e.o.left), eval(se->e.o.right)));
  951.         case SVAL:   return(dosval(seval(se->e.o.left), eval(se->e.o.right)));
  952.         case SUBSTR: return(dosubstr(seval(se->e.o.left),
  953.                             (int)eval(se->e.o.right->e.o.left) - 1,
  954.                             (int)eval(se->e.o.right->e.o.right) - 1));
  955.         default:
  956.                      error ("Illegal string expression");
  957.                      exprerr = 1;
  958.                      return(0);
  959.         }
  960. }
  961.  
  962. /*
  963.  * The graph formed by cell expressions which use other cells's values is not
  964.  * evaluated "bottom up".  The whole table is merely re-evaluated cell by cell,
  965.  * top to bottom, left to right, in RealEvalAll().  Each cell's expression uses
  966.  * constants in other cells.  However, RealEvalAll() notices when a cell gets a
  967.  * new numeric or string value, and reports if this happens for any cell.
  968.  * EvalAll() repeats calling RealEvalAll() until there are no changes or the
  969.  * evaluation count expires.
  970.  */
  971.  
  972. int propagation = 10;   /* max number of times to try calculation */
  973.  
  974. setiterations(i)
  975.         int i;
  976.         {
  977.         if(i<1){
  978.                 error("iteration count must be at least 1");
  979.                 propagation = 1;
  980.                 }
  981.         else propagation = i;
  982.         }
  983.  
  984. EvalAll () {
  985.       int lastcnt, repct = 0;
  986.  
  987.      while ((lastcnt = RealEvalAll()) && (repct++ <= propagation));
  988.      if((propagation>1)&& (lastcnt >0 ))
  989.             error("Still changing after %d iterations",propagation-1);
  990. }
  991.  
  992. /*
  993.  * Evaluate all cells which have expressions and alter their numeric or string
  994.  * values.  Return the number of cells which changed.
  995.  */
  996.  
  997. int
  998. RealEvalAll () {
  999.     register int i,j;
  1000.     int chgct = 0;
  1001.     register struct ent *p;
  1002. #ifndef OSK
  1003.     (void) signal(SIGFPE, eval_fpe);
  1004. #endif
  1005.     if(calc_order == BYROWS ) {
  1006.     for (i=0; i<=maxrow; i++)
  1007.         for (j=0; j<=maxcol; j++)
  1008.             if ((p=tbl[i][j]) && p->expr) RealEvalOne(p,i,j, &chgct);
  1009.     }
  1010.     else if ( calc_order == BYCOLS ) {
  1011.     for (j=0; j<=maxcol; j++)
  1012.         for (i=0; i<=maxrow; i++)
  1013.             if ((p=tbl[i][j]) && p->expr) RealEvalOne(p,i,j, &chgct);
  1014.     }
  1015.     else error("Internal error calc_order");
  1016. #ifndef OSK
  1017.     (void) signal(SIGFPE, quit);
  1018. #endif
  1019.     return(chgct);
  1020. }
  1021.  
  1022. RealEvalOne(p, i , j, chgct)
  1023. register struct ent *p;
  1024. int i, j, *chgct;
  1025. {
  1026.         if (p->flags & is_strexpr) {
  1027.             char *v;
  1028.             if (setjmp(fpe_save)) {
  1029.                 error("Floating point exception %s", v_name( i, j));
  1030.                 v = "";
  1031.             } else {
  1032.                 v = seval(p->expr);
  1033.             }
  1034.             if (!v && !p->label) /* Everything's fine */
  1035.                 return(0);
  1036.             if (!p->label || !v || strcmp(v, p->label) != 0) {
  1037.                 (*chgct)++;
  1038.                 p->flags |= is_changed;
  1039.             }
  1040.             if(p->label)
  1041.                 xfree(p->label);
  1042.             p->label = v;
  1043.         } else {
  1044.             double v;
  1045.             if (setjmp(fpe_save)) {
  1046.                 error("Floating point exception %s", v_name( i, j));
  1047.                 v = 0.0;
  1048.             } else {
  1049.                 v = eval (p->expr);
  1050.             }
  1051.             if (v != p->v) {
  1052.                 p->v = v; (*chgct)++;
  1053.                 p->flags |= is_changed|is_valid;
  1054.             }
  1055.         }
  1056. }
  1057.  
  1058. struct enode *
  1059. new(op, a1, a2)
  1060. struct enode *a1, *a2;
  1061. {
  1062.     register struct enode *p;
  1063.     p = (struct enode *) xmalloc ((unsigned)sizeof (struct enode));
  1064.     p->op = op;
  1065.     p->e.o.left = a1;
  1066.     p->e.o.right = a2;
  1067.     return p;
  1068. }
  1069.  
  1070. struct enode *
  1071. new_var(op, a1)
  1072. struct ent_ptr a1;
  1073. {
  1074.     register struct enode *p;
  1075.     p = (struct enode *) xmalloc ((unsigned)sizeof (struct enode));
  1076.     p->op = op;
  1077.     p->e.v = a1;
  1078.     return p;
  1079. }
  1080.  
  1081. struct enode *
  1082. new_range(op, a1)
  1083. struct range_s a1;
  1084. {
  1085.     register struct enode *p;
  1086.     p = (struct enode *) xmalloc ((unsigned)sizeof (struct enode));
  1087.     p->op = op;
  1088.     p->e.r = a1;
  1089.     return p;
  1090. }
  1091.  
  1092. struct enode *
  1093. new_const(op, a1)
  1094. double a1;
  1095. {
  1096.     register struct enode *p;
  1097.     p = (struct enode *) xmalloc ((unsigned)sizeof (struct enode));
  1098.     p->op = op;
  1099.     p->e.k = a1;
  1100.     return p;
  1101. }
  1102.  
  1103. struct enode *
  1104. new_str(s)
  1105. char *s;
  1106. {
  1107.     register struct enode *p;
  1108.  
  1109.     p = (struct enode *) xmalloc ((unsigned)sizeof(struct enode));
  1110.     p->op = O_SCONST;
  1111.     p->e.s = s;
  1112.     return(p);
  1113. }
  1114.  
  1115. void copy(dv1, dv2, v1, v2)
  1116. struct ent *dv1, *dv2, *v1, *v2;
  1117. {
  1118.     int minsr, minsc;
  1119.     int maxsr, maxsc;
  1120.     int mindr, mindc;
  1121.     int maxdr, maxdc;
  1122.     int vr, vc;
  1123.     int r, c;
  1124.  
  1125.     mindr = dv1->row;
  1126.     mindc = dv1->col;
  1127.     maxdr = dv2->row;
  1128.     maxdc = dv2->col;
  1129.     if (mindr>maxdr) r = maxdr, maxdr = mindr, mindr = r;
  1130.     if (mindc>maxdc) c = maxdc, maxdc = mindc, mindc = c;
  1131.     maxsr = v2->row;
  1132.     maxsc = v2->col;
  1133.     minsr = v1->row;
  1134.     minsc = v1->col;
  1135.     if (minsr>maxsr) r = maxsr, maxsr = minsr, minsr = r;
  1136.     if (minsc>maxsc) c = maxsc, maxsc = minsc, minsc = c;
  1137.     if (maxdr >= MAXROWS  ||
  1138.            maxdc >= MAXCOLS) {
  1139.         error ("The table can't be any bigger");
  1140.         return;
  1141.     }
  1142.     erase_area(mindr, mindc, maxdr, maxdc);
  1143.     if (minsr == maxsr && minsc == maxsc) {
  1144.         /* Source is a single cell */
  1145.         for(vr = mindr; vr <= maxdr; vr++)
  1146.             for (vc = mindc; vc <= maxdc; vc++)
  1147.                 copyrtv(vr, vc, minsr, minsc, maxsr, maxsc);
  1148.     } else if (minsr == maxsr) {
  1149.         /* Source is a single row */
  1150.         for (vr = mindr; vr <= maxdr; vr++)
  1151.             copyrtv(vr, mindc, minsr, minsc, maxsr, maxsc);
  1152.     } else if (minsc == maxsc) {
  1153.         /* Source is a single column */
  1154.         for (vc = mindc; vc <= maxdc; vc++)
  1155.             copyrtv(mindr, vc, minsr, minsc, maxsr, maxsc);
  1156.     } else {
  1157.         /* Everything else */
  1158.         copyrtv(mindr, mindc, minsr, minsc, maxsr, maxsc);
  1159.     }
  1160.     sync_refs();
  1161. }
  1162.  
  1163. copyrtv(vr, vc, minsr, minsc, maxsr, maxsc)
  1164. int vr, vc, minsr, minsc, maxsr, maxsc;
  1165. {
  1166.     register struct ent *p;
  1167.     register struct ent *n;
  1168.     register int sr, sc;
  1169.     register int dr, dc;
  1170.  
  1171.     for (dr=vr, sr=minsr; sr<=maxsr; sr++, dr++)
  1172.         for (dc=vc, sc=minsc; sc<=maxsc; sc++, dc++) {
  1173.             n = lookat (dr, dc);
  1174.             (void) clearent(n);
  1175.             if (p = tbl[sr][sc])
  1176.                 copyent( n, p, dr - sr, dc - sc);
  1177.         }
  1178. }
  1179.  
  1180. eraser(v1, v2)
  1181. struct ent *v1, *v2;
  1182. {
  1183.         FullUpdate++;
  1184.         flush_saved();
  1185.         erase_area(v1->row, v1->col, v2->row, v2->col);
  1186.         sync_refs();
  1187. }
  1188.  
  1189. /* Goto subroutines */
  1190.  
  1191. g_free()
  1192. {
  1193.     switch (gs.g_type) {
  1194.     case G_STR: xfree(gs.g_s); break;
  1195.     default: break;
  1196.     }
  1197.     gs.g_type = G_NONE;
  1198. }
  1199.  
  1200. go_last()
  1201. {
  1202.     switch (gs.g_type) {
  1203.     case G_NONE:
  1204.                 error("Nothing to repeat"); break;
  1205.     case G_NUM:
  1206.                 num_search(gs.g_n);
  1207.                 break;
  1208.     case  G_CELL:
  1209.                 moveto(gs.g_row, gs.g_col);
  1210.                 break;
  1211.     case  G_STR:
  1212.                 gs.g_type = G_NONE;     /* Don't free the string */
  1213.                 str_search(gs.g_s);
  1214.                 break;
  1215.  
  1216.     default: error("go_last: internal error");
  1217.     }
  1218. }
  1219.  
  1220. moveto(row, col)
  1221. int row, col;
  1222. {
  1223.     currow = row;
  1224.     curcol = col;
  1225.     g_free();
  1226.     gs.g_type = G_CELL;
  1227.     gs.g_row = currow;
  1228.     gs.g_col = curcol;
  1229. }
  1230.  
  1231. num_search(n)
  1232. double n;
  1233. {
  1234.     register struct ent *p;
  1235.     register int r,c;
  1236.  
  1237.     g_free();
  1238.     gs.g_type = G_NUM;
  1239.     gs.g_n = n;
  1240.  
  1241.     r = currow;
  1242.     c = curcol;
  1243.     do {
  1244.         if (c < maxcol)
  1245.             c++;
  1246.         else {
  1247.             if (r < maxrow) {
  1248.                 while(++r < maxrow && row_hidden[r]) /* */;
  1249.                 c = 0;
  1250.             } else {
  1251.                 r = 0;
  1252.                 c = 0;
  1253.             }
  1254.         }
  1255.         if (r == currow && c == curcol) {
  1256.             error("Number not found");
  1257.             return(0);
  1258.         }
  1259.         p = tbl[r][c];
  1260.     } while(col_hidden[c] || !p || p && (!(p->flags & is_valid)
  1261.                                         || (p->flags&is_valid) && p->v != n));
  1262.     currow = r;
  1263.     curcol = c;
  1264. }
  1265.  
  1266.  
  1267. str_search(s)
  1268. char *s;
  1269. {
  1270.     register struct ent *p;
  1271.     register int r,c;
  1272.     char *tmp;
  1273.  
  1274. #if defined(BSD42) || defined(BSD43)
  1275.     if ((tmp = re_comp(s)) != (char *)0) {
  1276.         xfree(s);
  1277.         error(tmp);
  1278.         return(0);
  1279.     }
  1280. #endif
  1281. #if defined(SYSV2) || defined(SYSV3)
  1282.     if ((tmp = regcmp(s, (char *)0)) == (char *)0) {
  1283.         xfree(s);
  1284.         error("Invalid search string");
  1285.         return(0);
  1286.     }
  1287. #endif
  1288.     g_free();
  1289.     gs.g_type = G_STR;
  1290.     gs.g_s = s;
  1291.     r = currow;
  1292.     c = curcol;
  1293.     do {
  1294.         if (c < maxcol)
  1295.             c++;
  1296.         else {
  1297.             if (r < maxrow) {
  1298.                 while(++r < maxrow && row_hidden[r]) /* */;
  1299.                 c = 0;
  1300.             } else {
  1301.                 r = 0;
  1302.                 c = 0;
  1303.             }
  1304.         }
  1305.         if (r == currow && c == curcol) {
  1306.             error("String not found");
  1307. #if defined(SYSV2) || defined(SYSV3)
  1308.             free(tmp);
  1309. #endif
  1310.             return(0);
  1311.         }
  1312.         p = tbl[r][c];
  1313.     } while(col_hidden[c] || !p || p && (!(p->label)
  1314. #if defined(BSD42) || defined(BSD43)
  1315.                                         || (re_exec(p->label) == 0)));
  1316. #else
  1317. #if defined(SYSV2) || defined(SYSV3)
  1318.                                        || (regex(tmp, p->label) == (char *)0)));
  1319. #else
  1320.                                        || (strcmp(s, p->label) != 0)));
  1321. #endif
  1322. #endif
  1323.     currow = r;
  1324.     curcol = c;
  1325. #if defined(SYSV2) || defined(SYSV3)
  1326.     free(tmp);
  1327. #endif
  1328. }
  1329.  
  1330. fill (v1, v2, start, inc)
  1331. struct ent *v1, *v2;
  1332. double start, inc;
  1333. {
  1334.     register r,c;
  1335.     register struct ent *n;
  1336.     int maxr, maxc;
  1337.     int minr, minc;
  1338.  
  1339.     maxr = v2->row;
  1340.     maxc = v2->col;
  1341.     minr = v1->row;
  1342.     minc = v1->col;
  1343.     if (minr>maxr) r = maxr, maxr = minr, minr = r;
  1344.     if (minc>maxc) c = maxc, maxc = minc, minc = c;
  1345.     if (maxr >= MAXROWS) maxr = MAXROWS-1;
  1346.     if (maxc >= MAXCOLS) maxc = MAXCOLS-1;
  1347.     if (minr < 0) minr = 0;
  1348.     if (minr < 0) minr = 0;
  1349.  
  1350.     FullUpdate++;
  1351.     if( calc_order == BYROWS ) {
  1352.     for (r = minr; r<=maxr; r++)
  1353.         for (c = minc; c<=maxc; c++) {
  1354.             n = lookat (r, c);
  1355.             (void) clearent(n);
  1356.             n->v = start;
  1357.             start += inc;
  1358.             n->flags |= (is_changed|is_valid);
  1359.         }
  1360.     }
  1361.     else if ( calc_order == BYCOLS ) {
  1362.     for (c = minc; c<=maxc; c++)
  1363.         for (r = minr; r<=maxr; r++) {
  1364.             n = lookat (r, c);
  1365.             (void) clearent(n);
  1366.             n->v = start;
  1367.             start += inc;
  1368.             n->flags |= (is_changed|is_valid);
  1369.         }
  1370.     }
  1371.     else error(" Internal error calc_order");
  1372. }
  1373.  
  1374. void let (v, e)
  1375. struct ent *v;
  1376. struct enode *e;
  1377. {
  1378.     double val;
  1379.  
  1380.     exprerr = 0;
  1381. #ifndef OSK
  1382.     (void) signal(SIGFPE, eval_fpe);
  1383. #endif
  1384.     if (setjmp(fpe_save)) {
  1385.         error ("Floating point exception in cell %s", v_name(v->row, v->col));
  1386.         val = 0.0;
  1387.     } else {
  1388.         val = eval(e);
  1389.     }
  1390. #ifndef OSK
  1391.     (void) signal(SIGFPE, quit);
  1392. #endif
  1393.     if (exprerr) {
  1394.         efree(e);
  1395.         return;
  1396.     }
  1397.     if (constant(e)) {
  1398.         if (!loading)
  1399.             v->v = val * prescale;
  1400.         else
  1401.             v->v = val;
  1402.         if (!(v->flags & is_strexpr)) {
  1403.             efree (v->expr);
  1404.             v->expr = 0;
  1405.         }
  1406.         efree(e);
  1407.         v->flags |= (is_changed|is_valid);
  1408.         changed++;
  1409.         modflg++;
  1410.         return;
  1411.     }
  1412.     efree (v->expr);
  1413.     v->expr = e;
  1414.     v->flags |= (is_changed|is_valid);
  1415.     v->flags &= ~is_strexpr;
  1416.     changed++;
  1417.     modflg++;
  1418. }
  1419.  
  1420. void slet (v, se, flushdir)
  1421. struct ent *v;
  1422. struct enode *se;
  1423. int flushdir;
  1424. {
  1425.     char *p;
  1426.  
  1427.     exprerr = 0;
  1428. #ifndef OSK
  1429.     (void) signal(SIGFPE, eval_fpe);
  1430. #endif
  1431.     if (setjmp(fpe_save)) {
  1432.         error ("Floating point exception in cell %s", v_name(v->row, v->col));
  1433.         p = "";
  1434.     } else {
  1435.         p = seval(se);
  1436.     }
  1437. #ifndef OSK
  1438.     (void) signal(SIGFPE, quit);
  1439. #endif
  1440.     if (exprerr) {
  1441.         efree(se);
  1442.         return;
  1443.     }
  1444.     if (constant(se)) {
  1445.         label(v, p, flushdir);
  1446.         if (p)
  1447.             xfree(p);
  1448.         efree(se);
  1449.         if (v->flags & is_strexpr) {
  1450.             efree (v->expr);
  1451.             v->expr = 0;
  1452.             v->flags &= ~is_strexpr;
  1453.         }
  1454.         return;
  1455.     }
  1456.     efree (v->expr);
  1457.     v->expr = se;
  1458.     v->flags |= (is_changed|is_strexpr);
  1459.     if (flushdir<0) v->flags |= is_leftflush;
  1460.     else v->flags &= ~is_leftflush;
  1461.     FullUpdate++;
  1462.     changed++;
  1463.     modflg++;
  1464. }
  1465.  
  1466. void hide_row(arg)
  1467. int arg;
  1468. {
  1469.     if (arg < 0) {
  1470.         error("Invalid Range");
  1471.         return;
  1472.     }
  1473.     if (arg > MAXROWS-2) {
  1474.         error("You can't hide the last row");
  1475.         return;
  1476.     }
  1477.     FullUpdate++;
  1478.     row_hidden[arg] = 1;
  1479. }
  1480.  
  1481. void hide_col(arg)
  1482. int arg;
  1483. {
  1484.     if (arg < 0) {
  1485.         error("Invalid Range");
  1486.         return;
  1487.     }
  1488.     if (arg > MAXCOLS-2) {
  1489.         error("You can't hide the last col");
  1490.         return;
  1491.     }
  1492.     FullUpdate++;
  1493.     col_hidden[arg] = 1;
  1494. }
  1495.  
  1496. clearent (v)
  1497. struct ent *v;
  1498. {
  1499.     if (!v)
  1500.         return(0);
  1501.     label(v,"",-1);
  1502.     v->v = 0;
  1503.     if (v->expr)
  1504.         efree(v->expr);
  1505.     v->expr = 0;
  1506.     v->flags |= (is_changed);
  1507.     v->flags &= ~(is_valid);
  1508.     changed++;
  1509.     modflg++;
  1510. }
  1511.  
  1512. /*
  1513.  * Say if an expression is a constant (return 1) or not.
  1514.  */
  1515.  
  1516. constant (e)
  1517.     register struct enode *e;
  1518. {
  1519.     return ((e == 0)
  1520.          || ((e -> op) == O_CONST)
  1521.          || ((e -> op) == O_SCONST)
  1522.          || (((e -> op) != O_VAR)
  1523.           && (((e -> op) & REDUCE) != REDUCE)
  1524.           && constant (e -> e.o.left)
  1525.           && constant (e -> e.o.right)
  1526.           && (e -> op != EXT)    /* functions look like constants but aren't */
  1527.           && (e -> op != NVAL)
  1528.           && (e -> op != SVAL)
  1529.           && (e -> op != NOW)));
  1530. }
  1531.  
  1532. efree (e)
  1533. register struct enode *e;
  1534. {
  1535.     if (e) {
  1536.         if (e->op != O_VAR && e->op !=O_CONST && e->op != O_SCONST
  1537.                 && (e->op & REDUCE) != REDUCE) {
  1538.             efree(e->e.o.left);
  1539.             efree(e->e.o.right);
  1540.         }
  1541.         if (e->op == O_SCONST && e->e.s)
  1542.             xfree(e->e.s);
  1543.         xfree ((char *)e);
  1544.     }
  1545. }
  1546.  
  1547. label (v, s, flushdir)
  1548. register struct ent *v;
  1549. register char *s;
  1550. {
  1551.     if (v) {
  1552.         if (flushdir==0 && v->flags&is_valid) {
  1553.             register struct ent *tv;
  1554.             if (v->col>0 && ((tv=lookat(v->row,v->col-1))->flags&is_valid)==0)
  1555.                 v = tv, flushdir = 1;
  1556.             else if (((tv=lookat (v->row,v->col+1))->flags&is_valid)==0)
  1557.                 v = tv, flushdir = -1;
  1558.             else flushdir = -1;
  1559.         }
  1560.         if (v->label) xfree((char *)(v->label));
  1561.         if (s && s[0]) {
  1562.             v->label = xmalloc ((unsigned)(strlen(s)+1));
  1563.             (void) strcpy (v->label, s);
  1564.         } else
  1565.             v->label = 0;
  1566.         if (flushdir<0) v->flags |= is_leftflush;
  1567.         else v->flags &= ~is_leftflush;
  1568.         FullUpdate++;
  1569.         modflg++;
  1570.     }
  1571. }
  1572.  
  1573. decodev (v)
  1574. struct ent_ptr v;
  1575. {
  1576.         register struct range *r;
  1577.  
  1578.         if (!v.vp) (void)sprintf (line+linelim,"VAR?");
  1579.         else if (r = find_range((char *)0, 0, v.vp, v.vp))
  1580.             (void)sprintf(line+linelim, "%s", r->r_name);
  1581.         else
  1582.             (void)sprintf (line+linelim, "%s%s%s%d",
  1583.                         v.vf & FIX_COL ? "$" : "",
  1584.                         coltoa(v.vp->col),
  1585.                         v.vf & FIX_ROW ? "$" : "",
  1586.                         v.vp->row);
  1587.         linelim += strlen (line+linelim);
  1588. }
  1589.  
  1590. char *
  1591. coltoa(col)
  1592. int col;
  1593. {
  1594.     static char rname[3];
  1595.     register char *p = rname;
  1596.  
  1597.     if (col > 25) {
  1598.         *p++ = col/26 + 'A' - 1;
  1599.         col %= 26;
  1600.     }
  1601.     *p++ = col+'A';
  1602.     *p = 0;
  1603.     return(rname);
  1604. }
  1605.  
  1606. /*
  1607.  *      To make list elements come out in the same order
  1608.  *      they were entered, we must do a depth-first eval
  1609.  *      of the ELIST tree
  1610.  */
  1611. static
  1612. void decompile_list(p)
  1613. struct enode *p;
  1614. {
  1615.         if (!p) return;
  1616.         decompile_list(p->e.o.left);    /* depth first */
  1617.         decompile(p->e.o.right, 0);
  1618.         line[linelim++] = ',';
  1619. }
  1620.  
  1621. decompile(e, priority)
  1622. register struct enode *e; {
  1623.     register char *s;
  1624.     if (e) {
  1625.         int mypriority;
  1626.         switch (e->op) {
  1627.         default: mypriority = 99; break;
  1628.         case '?': mypriority = 1; break;
  1629.         case ':': mypriority = 2; break;
  1630.         case '|': mypriority = 3; break;
  1631.         case '&': mypriority = 4; break;
  1632.         case '<': case '=': case '>': mypriority = 6; break;
  1633.         case '+': case '-': case '#': mypriority = 8; break;
  1634.         case '*': case '/': case '%': mypriority = 10; break;
  1635.         case '^': mypriority = 12; break;
  1636.         }
  1637.         if (mypriority<priority) line[linelim++] = '(';
  1638.         switch (e->op) {
  1639.         case 'f':       for (s="fixed "; line[linelim++] = *s++;);
  1640.                         linelim--;
  1641.                         decompile (e->e.o.right, 30);
  1642.                         break;
  1643.         case 'm':       line[linelim++] = '-';
  1644.                         decompile (e->e.o.right, 30);
  1645.                         break;
  1646.         case '~':       line[linelim++] = '~';
  1647.                         decompile (e->e.o.right, 30);
  1648.                         break;
  1649.         case 'v':       decodev (e->e.v);
  1650.                         break;
  1651.         case 'k':       (void)sprintf (line+linelim,"%.15g",e->e.k);
  1652.                         linelim += strlen (line+linelim);
  1653.                         break;
  1654.         case '$':       (void)sprintf (line+linelim, "\"%s\"", e->e.s);
  1655.                         linelim += strlen(line+linelim);
  1656.                         break;
  1657.  
  1658.         case REDUCE | '+': range_arg( "@sum(", e); break;
  1659.         case REDUCE | '*': range_arg( "@prod(", e); break;
  1660.         case REDUCE | 'a': range_arg( "@avg(", e); break;
  1661.         case REDUCE | 's': range_arg( "@stddev(", e); break;
  1662.         case REDUCE | MAX: range_arg( "@max(", e); break;
  1663.         case REDUCE | MIN: range_arg( "@min(", e); break;
  1664.  
  1665.         case ACOS:      one_arg( "@acos(", e); break;
  1666.         case ASIN:      one_arg( "@asin(", e); break;
  1667.         case ATAN:      one_arg( "@atan(", e); break;
  1668.         case ATAN2:     two_arg( "@atan2(", e); break;
  1669.         case CEIL:      one_arg( "@ceil(", e); break;
  1670.         case COS:       one_arg( "@cos(", e); break;
  1671.         case EXP:       one_arg( "@exp(", e); break;
  1672.         case FABS:      one_arg( "@fabs(", e); break;
  1673.         case FLOOR:     one_arg( "@floor(", e); break;
  1674.         case HYPOT:     two_arg( "@hypot(", e); break;
  1675.         case LOG:       one_arg( "@ln(", e); break;
  1676.         case LOG10:     one_arg( "@log(", e); break;
  1677.         case POW:       two_arg( "@pow(", e); break;
  1678.         case SIN:       one_arg( "@sin(", e); break;
  1679.         case SQRT:      one_arg( "@sqrt(", e); break;
  1680.         case TAN:       one_arg( "@tan(", e); break;
  1681.         case DTR:       one_arg( "@dtr(", e); break;
  1682.         case RTD:       one_arg( "@rtd(", e); break;
  1683.         case RND:       one_arg( "@rnd(", e); break;
  1684.         case HOUR:      one_arg( "@hour(", e); break;
  1685.         case MINUTE:    one_arg( "@minute(", e); break;
  1686.         case SECOND:    one_arg( "@second(", e); break;
  1687.         case MONTH:     one_arg( "@month(", e); break;
  1688.         case DAY:       one_arg( "@day(", e); break;
  1689.         case YEAR:      one_arg( "@year(", e); break;
  1690.         case DATE:      one_arg( "@date(", e); break;
  1691.         case STON:      one_arg( "@ston(", e); break;
  1692.         case FMT:       two_arg( "@fmt(", e); break;
  1693.         case EQS:       two_arg( "@eqs(", e); break;
  1694.         case NOW:       for ( s = "@now"; line[linelim++] = *s++;);
  1695.                         linelim--;
  1696.                         break;
  1697.         case LMAX:      list_arg("@max(", e); break;
  1698.         case LMIN:      list_arg("@min(", e); break;
  1699.         case FV:        three_arg("@fv(", e); break;
  1700.         case PV:        three_arg("@pv(", e); break;
  1701.         case PMT:       three_arg("@pmt(", e); break;
  1702.         case NVAL:      two_arg("@nval(", e); break;
  1703.         case SVAL:      two_arg("@sval(", e); break;
  1704.         case EXT:       two_arg("@ext(", e); break;
  1705.         case SUBSTR:    three_arg("@substr(", e); break;
  1706.         case STINDEX:   index_arg("@stindex(", e); break;
  1707.         case INDEX:     index_arg("@index(", e); break;
  1708.         case LOOKUP:    index_arg("@lookup(", e); break;
  1709.  
  1710.         default:        decompile (e->e.o.left, mypriority);
  1711.                         line[linelim++] = e->op;
  1712.                         decompile (e->e.o.right, mypriority+1);
  1713.                         break;
  1714.  
  1715.         }
  1716.         if (mypriority<priority) line[linelim++] = ')';
  1717.     } else line[linelim++] = '?';
  1718. }
  1719.  
  1720. index_arg(s, e)
  1721. char *s;
  1722. struct enode *e;
  1723. {
  1724.     for (; line[linelim++] = *s++;);
  1725.     linelim--;
  1726.     decompile( e-> e.o.left, 0 );
  1727.     range_arg(", ", e->e.o.right);
  1728. }
  1729.  
  1730. list_arg(s, e)
  1731. char *s;
  1732. struct enode *e;
  1733. {
  1734.     for (; line[linelim++] = *s++;);
  1735.     linelim--;
  1736.  
  1737.     decompile (e->e.o.right, 0);
  1738.     line[linelim++] = ',';
  1739.     decompile_list(e->e.o.left);
  1740.     line[linelim - 1] = ')';
  1741. }
  1742.  
  1743. one_arg(s, e)
  1744. char *s;
  1745. struct enode *e;
  1746. {
  1747.     for (; line[linelim++] = *s++;);
  1748.     linelim--;
  1749.     decompile (e->e.o.right, 0);
  1750.     line[linelim++] = ')';
  1751. }
  1752.  
  1753. two_arg(s,e)
  1754. char *s;
  1755. struct enode *e;
  1756. {
  1757.     for (; line[linelim++] = *s++;);
  1758.     linelim--;
  1759.     decompile (e->e.o.left, 0);
  1760.     line[linelim++] = ',';
  1761.     decompile (e->e.o.right, 0);
  1762.     line[linelim++] = ')';
  1763. }
  1764.  
  1765. three_arg(s,e)
  1766. char *s;
  1767. struct enode *e;
  1768. {
  1769.     for (; line[linelim++] = *s++;);
  1770.     linelim--;
  1771.     decompile (e->e.o.left, 0);
  1772.     line[linelim++] = ',';
  1773.     decompile (e->e.o.right->e.o.left, 0);
  1774.     line[linelim++] = ',';
  1775.     decompile (e->e.o.right->e.o.right, 0);
  1776.     line[linelim++] = ')';
  1777. }
  1778.  
  1779. range_arg(s,e)
  1780. char *s;
  1781. struct enode *e;
  1782. {
  1783.     struct range *r;
  1784.  
  1785.     for (; line[linelim++] = *s++;);
  1786.     linelim--;
  1787.     if (r = find_range((char *)0, 0, e->e.r.left.vp,
  1788.                              e->e.r.right.vp)) {
  1789.         (void)sprintf(line+linelim, "%s", r->r_name);
  1790.         linelim += strlen(line+linelim);
  1791.     } else {
  1792.         decodev (e->e.r.left);
  1793.         line[linelim++] = ':';
  1794.         decodev (e->e.r.right);
  1795.     }
  1796.     line[linelim++] = ')';
  1797. }
  1798.  
  1799. editv (row, col)
  1800. int row, col;
  1801. {
  1802.     register struct ent *p;
  1803.  
  1804.     p = lookat (row, col);
  1805.     (void)sprintf (line, "let %s = ", v_name(row, col));
  1806.     linelim = strlen(line);
  1807.     if (p->flags & is_strexpr || p->expr == 0) {
  1808.         (void)sprintf (line+linelim, "%.15g", p->v);
  1809.         linelim += strlen (line+linelim);
  1810.     } else {
  1811.         editexp(row,col);
  1812.     }
  1813. }
  1814.  
  1815. editexp(row,col)
  1816. int row, col;
  1817. {
  1818.     register struct ent *p;
  1819.  
  1820.     p = lookat (row, col);
  1821.     decompile (p->expr, 0);
  1822.     line[linelim] = 0;
  1823. }
  1824.  
  1825. edits (row, col)
  1826. int row, col;
  1827. {
  1828.     register struct ent *p;
  1829.  
  1830.     p = lookat (row, col);
  1831.     (void)sprintf (line, "%sstring %s = ",
  1832.                         ((p->flags&is_leftflush) ? "left" : "right"),
  1833.                         v_name(row, col));
  1834.     linelim = strlen(line);
  1835.     if (p->flags & is_strexpr && p->expr) {
  1836.         editexp(row, col);
  1837.     } else if (p->label) {
  1838.         (void)sprintf (line+linelim, "\"%s\"", p->label);
  1839.         linelim += strlen (line+linelim);
  1840.     } else {
  1841.         (void)sprintf (line+linelim, "\"");
  1842.         linelim += 1;
  1843.     }
  1844. }
  1845.