home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 2 / goldfish_vol2_cd1.bin / files / biz / misc / asc / interp.c < prev    next >
C/C++ Source or Header  |  1993-11-04  |  56KB  |  2,493 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.21 $
  11.  */
  12.  
  13. #define DEBUGDTS 1        /* REMOVE ME */
  14.      
  15. #include <sys/types.h>
  16. #ifdef aiws
  17. #undef _C_func            /* Fixes for undefined symbols on AIX */
  18. #endif
  19.  
  20. #ifdef IEEE_MATH
  21. #include <ieeefp.h>
  22. #endif /* IEEE_MATH */
  23.  
  24. #include <math.h>
  25. #include <signal.h>
  26. #include <setjmp.h>
  27. #include <stdio.h>
  28. #include <ctype.h>
  29.  
  30. extern int errno;        /* set by math functions */
  31. #ifdef BSD42
  32. #include <strings.h>
  33. #include <sys/time.h>
  34. #ifndef strchr
  35. #define strchr index
  36. #endif
  37. #else
  38. #include <time.h>
  39. #ifndef SYSIII
  40. #include <string.h>
  41. #endif
  42. #endif
  43.  
  44. #include <curses.h>
  45. #include "sc.h"
  46.  
  47. #if defined(RE_COMP)
  48. char *re_comp();
  49. #endif
  50. #if defined(REGCMP)
  51. char *regcmp();
  52. char *regex();
  53. #endif
  54.  
  55. #ifdef SIGVOID
  56.     void doquit();
  57. #else
  58.     int doquit();
  59. #endif
  60.  
  61. /* Use this structure to save the the last 'g' command */
  62. struct go_save {
  63.     int g_type;
  64.     double g_n;
  65.     char *g_s;
  66.     int  g_row;
  67.     int  g_col;
  68.     int  errsearch;
  69. } gs;
  70.  
  71. /* g_type can be: */
  72. #define G_NONE 0            /* Starting value - must be 0*/
  73. #define G_NUM 1
  74. #define G_STR 2
  75. #define G_CELL 3
  76.  
  77. #define ISVALID(r,c)    ((r)>=0 && (r)<maxrows && (c)>=0 && (c)<maxcols)
  78.  
  79. extern FILE *popen();
  80.  
  81. jmp_buf fpe_save;
  82. int    exprerr;    /* Set by eval() and seval() if expression errors */
  83. double  prescale = 1.0;    /* Prescale for constants in let() */
  84. int    extfunc  = 0;    /* Enable/disable external functions */
  85. int     loading = 0;    /* Set when readfile() is active */
  86. int    gmyrow, gmycol;    /* globals used to implement @myrow, @mycol cmds */
  87.  
  88. /* a linked list of free [struct enodes]'s, uses .e.o.left as the pointer */
  89. struct enode *freeenodes = NULL;
  90.  
  91. char    *seval();
  92. double    dolookup();
  93. double    eval();
  94. double    fn1_eval();
  95. double    fn1_seval();
  96. double    fn2_eval();
  97. int    RealEvalAll();
  98. int    constant();
  99. void    RealEvalOne();
  100. void    copyrtv();
  101. void    decompile();
  102. void    index_arg();
  103. void    list_arg();
  104. void    one_arg();
  105. void    range_arg();
  106. void    three_arg();
  107. void    two_arg();
  108. void    two_arg_index();
  109.  
  110. double    rint();
  111. int    cellerror = CELLOK;    /* is there an error in this cell */
  112.  
  113. #ifndef PI
  114. #define PI (double)3.14159265358979323846
  115. #endif
  116. #define dtr(x) ((x)*(PI/(double)180.0))
  117. #define rtd(x) ((x)*(180.0/(double)PI))
  118.  
  119. double finfunc(fun,v1,v2,v3)
  120. int fun;
  121. double v1,v2,v3;
  122. {
  123.      double answer,p;
  124.  
  125.      p = fn2_eval(pow, 1 + v2, v3);
  126.  
  127.      switch(fun)
  128.      {
  129.      case PV:
  130.         if (v2)
  131.             answer = v1 * (1 - 1/p) / v2;
  132.         else
  133.         {    cellerror = CELLERROR;
  134.             answer = (double)0;
  135.         }
  136.          break;
  137.      case FV:
  138.         if (v2)
  139.             answer = v1 * (p - 1) / v2;
  140.         else
  141.         {    cellerror = CELLERROR;
  142.             answer = (double)0;
  143.         }
  144.          break;
  145.      case PMT:
  146.         /* CHECK IF ~= 1 - 1/1 */
  147.         if (p && p != (double)1)
  148.             answer = v1 * v2 / (1 - 1/p);
  149.         else
  150.         {    cellerror = CELLERROR;
  151.             answer = (double)0;
  152.         }
  153.         
  154.          break;
  155.     default:
  156.         error("Unknown function in finfunc");
  157.         cellerror = CELLERROR;
  158.         return((double)0);
  159.     }
  160.     return(answer);
  161. }
  162.  
  163. char *
  164. dostindex( val, minr, minc, maxr, maxc)
  165. double val;
  166. int minr, minc, maxr, maxc;
  167. {
  168.     register r,c;
  169.     register struct ent *p;
  170.     char *pr;
  171.     int x;
  172.  
  173.     x = (int) val;
  174.     r = minr; c = minc;
  175.     p = (struct ent *)0;
  176.     if ( minr == maxr ) { /* look along the row */
  177.     c = minc + x - 1;
  178.     if (c <= maxc && c >=minc)
  179.         p = *ATBL(tbl, r, c);
  180.     } else if ( minc == maxc ) { /* look down the column */
  181.     r = minr + x - 1;
  182.     if (r <= maxr && r >=minr)
  183.         p = *ATBL(tbl, r, c);
  184.     } else {
  185.     error ("range specified to @stindex");
  186.     cellerror = CELLERROR;
  187.     return((char *)0);
  188.     }
  189.  
  190.     if (p && p->label) {
  191.     pr = scxmalloc((unsigned)(strlen(p->label)+1));
  192.     (void) strcpy(pr, p->label);
  193.     if (p->cellerror)
  194.         cellerror = CELLINVALID;
  195.     return (pr);
  196.      } else
  197.     return((char *)0);
  198. }
  199.  
  200. double
  201. doindex( val, minr, minc, maxr, maxc)
  202. double val;
  203. int minr, minc, maxr, maxc;
  204. {
  205.     double v;
  206.     register r,c;
  207.     register struct ent *p;
  208.     int x;
  209.  
  210.     x = (int) val;
  211.     v = (double)0;
  212.     r = minr; c = minc;
  213.     if ( minr == maxr ) { /* look along the row */
  214.     c = minc + x - 1;
  215.     if (c <= maxc && c >=minc 
  216.         && (p = *ATBL(tbl, r, c)) && p->flags&is_valid )
  217.     {    if (p->cellerror)
  218.             cellerror = CELLINVALID;
  219.         return p->v;
  220.     }
  221.     }
  222.     else if ( minc == maxc ){ /* look down the column */
  223.     r = minr + x - 1;
  224.     if (r <= maxr && r >=minr 
  225.         && (p = *ATBL(tbl, r, c)) && p->flags&is_valid )
  226.     {    if (p->cellerror)
  227.             cellerror = CELLINVALID;
  228.         return p->v;
  229.     }
  230.     }
  231.     else {
  232.     error(" range specified to @index");
  233.     cellerror = CELLERROR;
  234.     }
  235.     return v;
  236. }
  237.  
  238. double
  239. dolookup( val, minr, minc, maxr, maxc, offr, offc)
  240. struct enode * val;
  241. int minr, minc, maxr, maxc, offr, offc;
  242. {
  243.     double v, ret = (double)0;
  244.     register r,c;
  245.     register struct ent *p = (struct ent *)0;
  246.     int incr,incc,fndr,fndc;
  247.     char *s;
  248.  
  249.     incr = (offc != 0); incc = (offr != 0);
  250.     if (etype(val) == NUM) {
  251.     cellerror = CELLOK;
  252.     v = eval(val);
  253.     for (r = minr, c = minc; r <= maxr && c <= maxc; r+=incr, c+=incc) {
  254.         if ( (p = *ATBL(tbl, r, c)) && p->flags&is_valid ) {
  255.         if (p->v <= v) {
  256.             fndr = incc ? (minr + offr) : r;
  257.             fndc = incr ? (minc + offc) : c;
  258.             if (ISVALID(fndr,fndc))
  259.             p = *ATBL(tbl, fndr, fndc);
  260.             else {
  261.             error(" range specified to @[hv]lookup");
  262.             cellerror = CELLERROR;
  263.             }
  264.             if ( p && p->flags&is_valid)
  265.             {    if (p->cellerror)
  266.                 cellerror = CELLINVALID;
  267.             ret = p->v;
  268.             }
  269.         } else break;
  270.         }
  271.     }
  272.     } else {
  273.     cellerror = CELLOK;
  274.     s = seval(val);
  275.     for (r = minr, c = minc; r <= maxr && c <= maxc; r+=incr, c+=incc) {
  276.         if ( (p = *ATBL(tbl, r, c)) && p->label ) {
  277.         if (strcmp(p->label,s) == 0) {
  278.             fndr = incc ? (minr + offr) : r;
  279.             fndc = incr ? (minc + offc) : c;
  280.             if (ISVALID(fndr,fndc))
  281.             {    p = *ATBL(tbl, fndr, fndc);
  282.             if (p->cellerror)
  283.                 cellerror = CELLINVALID;
  284.             }
  285.             else {
  286.             error(" range specified to @[hv]lookup");
  287.             cellerror = CELLERROR;
  288.             }
  289.             break;
  290.         }
  291.         }
  292.     }
  293.     if ( p && p->flags&is_valid)
  294.         ret = p->v;
  295.     scxfree(s);
  296.     }
  297.     return ret;
  298. }
  299.  
  300. double
  301. docount(minr, minc, maxr, maxc)
  302. int minr, minc, maxr, maxc;
  303. {
  304.     int v;
  305.     register r,c;
  306.     register struct ent *p;
  307.  
  308.     v = 0;
  309.     for (r = minr; r<=maxr; r++)
  310.     for (c = minc; c<=maxc; c++)
  311.         if ((p = *ATBL(tbl, r, c)) && p->flags&is_valid)
  312.         {    if (p->cellerror)
  313.             cellerror = CELLINVALID;
  314.         v++;
  315.         }
  316.     return v;
  317. }
  318.  
  319. double
  320. dosum(minr, minc, maxr, maxc)
  321. int minr, minc, maxr, maxc;
  322. {
  323.     double v;
  324.     register r,c;
  325.     register struct ent *p;
  326.  
  327.     v = (double)0;
  328.     for (r = minr; r<=maxr; r++)
  329.     for (c = minc; c<=maxc; c++)
  330.         if ((p = *ATBL(tbl, r, c)) && p->flags&is_valid)
  331.         {    if (p->cellerror)
  332.             cellerror = CELLINVALID;
  333.         v += p->v;
  334.         }
  335.     return v;
  336. }
  337.  
  338. double
  339. doprod(minr, minc, maxr, maxc)
  340. int minr, minc, maxr, maxc;
  341. {
  342.     double v;
  343.     register r,c;
  344.     register struct ent *p;
  345.  
  346.     v = 1;
  347.     for (r = minr; r<=maxr; r++)
  348.     for (c = minc; c<=maxc; c++)
  349.         if ((p = *ATBL(tbl, r, c)) && p->flags&is_valid)
  350.         {    if (p->cellerror)
  351.             cellerror = CELLINVALID;
  352.         v *= p->v;
  353.         }
  354.     return v;
  355. }
  356.  
  357. double
  358. doavg(minr, minc, maxr, maxc)
  359. int minr, minc, maxr, maxc;
  360. {
  361.     double v;
  362.     register r,c,count;
  363.     register struct ent *p;
  364.  
  365.     v = (double)0;
  366.     count = 0;
  367.     for (r = minr; r<=maxr; r++)
  368.     for (c = minc; c<=maxc; c++)
  369.         if ((p = *ATBL(tbl, r, c)) && p->flags&is_valid) {
  370.         if (p->cellerror)
  371.             cellerror = CELLINVALID;
  372.  
  373.         v += p->v;
  374.         count++;
  375.         }
  376.  
  377.     if (count == 0) 
  378.     return ((double) 0);
  379.  
  380.     return (v / (double)count);
  381. }
  382.  
  383. double
  384. dostddev(minr, minc, maxr, maxc)
  385. int minr, minc, maxr, maxc;
  386. {
  387.     double lp, rp, v, nd;
  388.     register r,c,n;
  389.     register struct ent *p;
  390.  
  391.     n = 0;
  392.     lp = 0;
  393.     rp = 0;
  394.     for (r = minr; r<=maxr; r++)
  395.     for (c = minc; c<=maxc; c++)
  396.         if ((p = *ATBL(tbl, r, c)) && p->flags&is_valid) {
  397.         if (p->cellerror)
  398.             cellerror = CELLINVALID;
  399.  
  400.         v = p->v;
  401.         lp += v*v;
  402.         rp += v;
  403.         n++;
  404.         }
  405.  
  406.     if ((n == 0) || (n == 1)) 
  407.     return ((double) 0);
  408.     nd = (double)n;
  409.     return (sqrt((nd*lp-rp*rp)/(nd*(nd-1))));
  410. }
  411.  
  412. double
  413. domax(minr, minc, maxr, maxc)
  414. int minr, minc, maxr, maxc;
  415. {
  416.     double v = (double)0;
  417.     register r,c,count;
  418.     register struct ent *p;
  419.  
  420.     count = 0;
  421.     for (r = minr; r<=maxr; r++)
  422.     for (c = minc; c<=maxc; c++)
  423.         if ((p = *ATBL(tbl, r, c)) && p->flags&is_valid) {
  424.         if (p->cellerror)
  425.             cellerror = CELLINVALID;
  426.  
  427.         if (!count) {
  428.             v = p->v;
  429.             count++;
  430.         } else if (p->v > v)
  431.             v = p->v;
  432.         }
  433.  
  434.     if (count == 0) 
  435.     return ((double) 0);
  436.  
  437.     return (v);
  438. }
  439.  
  440. double
  441. domin(minr, minc, maxr, maxc)
  442. int minr, minc, maxr, maxc;
  443. {
  444.     double v = (double)0;
  445.     register r,c,count;
  446.     register struct ent *p;
  447.  
  448.     count = 0;
  449.     for (r = minr; r<=maxr; r++)
  450.     for (c = minc; c<=maxc; c++)
  451.         if ((p = *ATBL(tbl, r, c)) && p->flags&is_valid) {
  452.         if (p->cellerror)
  453.             cellerror = CELLINVALID;
  454.  
  455.         if (!count) {
  456.             v = p->v;
  457.             count++;
  458.         } else if (p->v < v)
  459.             v = p->v;
  460.         }
  461.  
  462.     if (count == 0) 
  463.     return ((double) 0);
  464.  
  465.     return (v);
  466. }
  467.  
  468. #define sec_min 60
  469. #define sec_hr  3600L
  470. #define sec_day 86400L
  471. #define sec_yr  31471200L     /* 364.25 days/yr */
  472. #define sec_mo  2622600L       /* sec_yr/12: sort of an average */
  473. int mdays[12]={ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
  474.  
  475. double
  476. dodts(mo, day, yr)
  477. int mo, day, yr;
  478. {
  479.     long trial;
  480.     register struct tm *tp; 
  481.     register int i;
  482.     register long jdate;
  483.  
  484.     mdays[1] = 28 + (yr%4 == 0);
  485.  
  486.     if (mo < 1 || mo > 12 || day < 1 || day > mdays[--mo] ||
  487.         yr > 1999 || yr < 1970) {
  488.     error("@dts: invalid argument");
  489.     cellerror = CELLERROR;
  490.     return(0.0);
  491.     }
  492.  
  493.     jdate = day-1;
  494.     for (i=0; i<mo; i++)
  495.         jdate += mdays[i];
  496.     for (i = 1970; i < yr; i++)
  497.         jdate += 365 + (i%4 == 0);
  498.  
  499.     trial = jdate * sec_day; 
  500.  
  501.     yr -= 1900;
  502.  
  503.     tp = localtime(&trial);
  504.  
  505.     if (tp->tm_year != yr) {
  506.         /*
  507.         * We may fail this test once a year because of time zone
  508.          * and daylight savings time errors.  This bounces the
  509.          * trial time past the boundary.  The error introduced is
  510.          * corrected below.
  511.          */
  512.         trial += sec_day*(yr - tp->tm_year);
  513.         tp = localtime(&trial);
  514.     }
  515.     if (tp->tm_mon != mo) {
  516.         /* We may fail this test once a month.  */
  517.         trial += sec_day*(mo - tp->tm_mon);
  518.         tp = localtime(&trial);
  519.     }
  520.     if (tp->tm_mday + tp->tm_hour + tp->tm_min + tp->tm_sec != day) {
  521.     trial -= (tp->tm_mday - day)*sec_day +  tp->tm_hour*sec_hr
  522.          + tp->tm_min*sec_min + tp->tm_sec;
  523.     }
  524.  
  525. #ifdef DEBUGDTS
  526.     tp = localtime(&trial);
  527.     if (tp->tm_mday + tp->tm_hour + tp->tm_min + tp->tm_sec + 
  528.     tp->tm_year + tp->tm_mon != yr+mo+day)
  529.     {    error("Dts broke down");
  530.         cellerror = CELLERROR;
  531.     }
  532. #endif
  533.  
  534.     return ((double)trial);
  535. }
  536.  
  537. double
  538. dotts(hr, min, sec)
  539. int hr, min, sec;
  540. {
  541.     if (hr < 0 || hr > 23 || min < 0 || min > 59 || sec < 0 || sec > 59) {
  542.     error ("@tts: Invalid argument");
  543.     cellerror = CELLERROR;
  544.     return ((double)0);
  545.     }
  546.     return ((double)(sec+min*60+hr*3600));
  547. }
  548.  
  549. double
  550. dotime(which, when)
  551. int which;
  552. double when;
  553. {
  554.     long time();
  555.  
  556.     static long t_cache;
  557.     static struct tm tm_cache;
  558.     struct tm *tp;
  559.     long tloc;
  560.  
  561.     if (which == NOW) 
  562.         return (double)time((long *)0);
  563.  
  564.     tloc = (long)when;
  565.  
  566.     if (tloc != t_cache) {
  567.         tp = localtime(&tloc);
  568.         tm_cache = *tp;
  569.         tm_cache.tm_mon += 1;
  570.         tm_cache.tm_year += 1900;
  571.         t_cache = tloc;
  572.     }
  573.  
  574.     switch (which) {
  575.         case HOUR: return((double)(tm_cache.tm_hour));
  576.         case MINUTE: return((double)(tm_cache.tm_min));
  577.         case SECOND: return((double)(tm_cache.tm_sec));
  578.         case MONTH: return((double)(tm_cache.tm_mon));
  579.         case DAY: return((double)(tm_cache.tm_mday));
  580.         case YEAR: return((double)(tm_cache.tm_year));
  581.     }
  582.     /* Safety net */
  583.     cellerror = CELLERROR;
  584.     return ((double)0);
  585. }
  586.  
  587. double
  588. doston(s)
  589. char *s;
  590. {
  591. #ifndef _AIX
  592.       char *strtof();
  593. #endif
  594.     double v;
  595.  
  596.     if (!s)
  597.     return((double)0);
  598.  
  599.     (void)strtof(s, &v);
  600.     scxfree(s);
  601.     return(v);
  602. }
  603.  
  604. double
  605. doeqs(s1, s2)
  606. char *s1, *s2;
  607. {
  608.     double v;
  609.  
  610.     if (!s1 && !s2)
  611.     return((double)1.0);
  612.  
  613.     if (!s1 || !s2)
  614.     v = 0.0;
  615.     else if (strcmp(s1, s2) == 0)
  616.     v = 1.0;
  617.     else
  618.     v = 0.0;
  619.  
  620.     if (s1)
  621.         scxfree(s1);
  622.  
  623.     if (s2)
  624.         scxfree(s2);
  625.  
  626.     return(v);
  627. }
  628.  
  629.  
  630. /*
  631.  * Given a string representing a column name and a value which is a column
  632.  * number, return a pointer to the selected cell's entry, if any, else NULL.
  633.  * Use only the integer part of the column number.  Always free the string.
  634.  */
  635.  
  636. struct ent *
  637. getent (colstr, rowdoub)
  638.     char *colstr;
  639.     double rowdoub;
  640. {
  641.     int collen;        /* length of string */
  642.     int row, col;    /* integer values   */
  643.     struct ent *p = (struct ent *)0;    /* selected entry   */
  644.  
  645.     if (!colstr)
  646.     {    cellerror = CELLERROR;
  647.     return((struct ent *)0);
  648.     }
  649.  
  650.     if (((row = (int) floor (rowdoub)) >= 0)
  651.      && (row < maxrows)                /* in range */
  652.      && ((collen = strlen (colstr)) <= 2)    /* not too long */
  653.      && ((col = atocol (colstr, collen)) >= 0)
  654.      && (col < maxcols))            /* in range */
  655.     {
  656.     p = *ATBL(tbl, row, col);
  657.     if ((p != NULL) && p->cellerror)
  658.         cellerror = CELLINVALID;
  659.     }
  660.     scxfree (colstr);
  661.     return (p);
  662. }
  663.  
  664.  
  665. /*
  666.  * Given a string representing a column name and a value which is a column
  667.  * number, return the selected cell's numeric value, if any.
  668.  */
  669.  
  670. double
  671. donval (colstr, rowdoub)
  672.     char *colstr;
  673.     double rowdoub;
  674. {
  675.     struct ent *ep;
  676.  
  677.     return (((ep = getent (colstr, rowdoub)) && ((ep -> flags) & is_valid)) ?
  678.         (ep -> v) : (double)0);
  679. }
  680.  
  681.  
  682. /*
  683.  *    The list routines (e.g. dolmax) are called with an LMAX enode.
  684.  *    The left pointer is a chain of ELIST nodes, the right pointer
  685.  *    is a value.
  686.  */
  687. double
  688. dolmax(ep)
  689. struct enode *ep;
  690. {
  691.     register int count = 0;
  692.     register double maxval = 0; /* Assignment to shut up lint */
  693.     register struct enode *p;
  694.     register double v;
  695.  
  696.     cellerror = CELLOK;
  697.     for (p = ep; p; p = p->e.o.left) {
  698.         v = eval(p->e.o.right);
  699.         if (!count || v > maxval) {
  700.             maxval = v; count++;
  701.         }
  702.     }
  703.     if (count) return maxval;
  704.     else return (double)0;
  705. }
  706.  
  707. double
  708. dolmin(ep)
  709. struct enode *ep;
  710. {
  711.     register int count = 0;
  712.     register double minval = 0; /* Assignment to shut up lint */
  713.     register struct enode *p;
  714.     register double v;
  715.  
  716.     cellerror = CELLOK;
  717.     for (p = ep; p; p = p->e.o.left) {
  718.         v = eval(p->e.o.right);
  719.         if (!count || v < minval) {
  720.             minval = v; count++;
  721.         }
  722.     }
  723.     if (count) return minval;
  724.     else return (double)0;
  725. }
  726.  
  727. double 
  728. eval(e)
  729. register struct enode *e;
  730. {
  731.     if (e == (struct enode *)0)
  732.     {    cellerror = CELLINVALID;
  733.     return (double)0;
  734.     }
  735.     switch (e->op) {
  736.     case '+':    return (eval(e->e.o.left) + eval(e->e.o.right));
  737.     case '-':    return (eval(e->e.o.left) - eval(e->e.o.right));
  738.     case '*':    return (eval(e->e.o.left) * eval(e->e.o.right));
  739.     case '/':     { double num, denom;
  740.             num = eval(e->e.o.left);
  741.             denom = eval(e->e.o.right);
  742.             if (denom)
  743. /*            if (1)    /* to test num div 0 */
  744.                 return(num/denom);
  745.             else
  746.             {    cellerror = CELLERROR;
  747.                 return((double) 0);
  748.             }
  749.     }
  750.     case '%':     {    double num, denom;
  751.             num = floor(eval(e->e.o.left));
  752.             denom = floor(eval (e->e.o.right));
  753.             if (denom)
  754.                 return(num - floor(num/denom)*denom);
  755.             else
  756.             {    cellerror = CELLERROR;
  757.                 return((double) 0);
  758.             }
  759.     }
  760.     case '^':    return (fn2_eval(pow,eval(e->e.o.left),eval(e->e.o.right)));
  761.     case '<':    return (eval(e->e.o.left) < eval(e->e.o.right));
  762.     case '=':    return (eval(e->e.o.left) == eval(e->e.o.right));
  763.     case '>':    return (eval(e->e.o.left) > eval(e->e.o.right));
  764.     case '&':    return (eval(e->e.o.left) && eval(e->e.o.right));
  765.     case '|':    return (eval(e->e.o.left) || eval(e->e.o.right));
  766.     case IF:
  767.     case '?':    return eval(e->e.o.left) ? eval(e->e.o.right->e.o.left)
  768.                         : eval(e->e.o.right->e.o.right);
  769.     case 'm':    return (-eval(e->e.o.right));
  770.     case 'f':    return (eval(e->e.o.right));
  771.     case '~':    return (eval(e->e.o.right) == 0.0);
  772.     case O_CONST:    return (e->e.k);
  773.     case O_VAR:    if (e->e.v.vp->cellerror)
  774.                 cellerror = CELLINVALID;
  775.             return (e->e.v.vp->v);
  776.     case INDEX:
  777.     case LOOKUP:
  778.     case HLOOKUP:
  779.     case VLOOKUP:
  780.         {    register r,c;
  781.         register maxr, maxc;
  782.         register minr, minc;
  783.         maxr = e->e.o.right->e.r.right.vp -> row;
  784.         maxc = e->e.o.right->e.r.right.vp -> col;
  785.         minr = e->e.o.right->e.r.left.vp -> row;
  786.         minc = e->e.o.right->e.r.left.vp -> col;
  787.         if (minr>maxr) r = maxr, maxr = minr, minr = r;
  788.         if (minc>maxc) c = maxc, maxc = minc, minc = c;
  789.         switch(e->op){
  790.         case LOOKUP:
  791.             return dolookup(e->e.o.left, minr, minc, maxr, maxc,
  792.                      minr==maxr, minc==maxc);
  793.         case HLOOKUP:
  794.                 return dolookup(e->e.o.left->e.o.left, minr,minc,maxr,maxc,
  795.             (int) eval(e->e.o.left->e.o.right), 0);
  796.         case VLOOKUP:
  797.                 return dolookup(e->e.o.left->e.o.left, minr,minc,maxr,maxc,
  798.             0, (int) eval(e->e.o.left->e.o.right));
  799.         case INDEX:
  800.             return doindex(eval(e->e.o.left), minr, minc, maxr, maxc);
  801.         }
  802.         }
  803.     case REDUCE | '+':
  804.      case REDUCE | '*':
  805.      case REDUCE | 'a':
  806.      case REDUCE | 'c':
  807.      case REDUCE | 's':
  808.     case REDUCE | MAX:
  809.     case REDUCE | MIN:
  810.         {    register r,c;
  811.         register maxr, maxc;
  812.         register minr, minc;
  813.         maxr = e->e.r.right.vp -> row;
  814.         maxc = e->e.r.right.vp -> col;
  815.         minr = e->e.r.left.vp -> row;
  816.         minc = e->e.r.left.vp -> col;
  817.         if (minr>maxr) r = maxr, maxr = minr, minr = r;
  818.         if (minc>maxc) c = maxc, maxc = minc, minc = c;
  819.             switch (e->op) {
  820.                 case REDUCE | '+': return dosum(minr, minc, maxr, maxc);
  821.                  case REDUCE | '*': return doprod(minr, minc, maxr, maxc);
  822.                  case REDUCE | 'a': return doavg(minr, minc, maxr, maxc);
  823.                  case REDUCE | 'c': return docount(minr, minc, maxr, maxc);
  824.                  case REDUCE | 's': return dostddev(minr, minc, maxr, maxc);
  825.                  case REDUCE | MAX: return domax(minr, minc, maxr, maxc);
  826.                  case REDUCE | MIN: return domin(minr, minc, maxr, maxc);
  827.         }
  828.         }
  829.     case ABS:     return (fn1_eval( fabs, eval(e->e.o.right)));
  830.     case ACOS:     return (fn1_eval( acos, eval(e->e.o.right)));
  831.     case ASIN:     return (fn1_eval( asin, eval(e->e.o.right)));
  832.     case ATAN:     return (fn1_eval( atan, eval(e->e.o.right)));
  833.     case ATAN2:     return (fn2_eval( atan2, eval(e->e.o.left), eval(e->e.o.right)));
  834.     case CEIL:     return (fn1_eval( ceil, eval(e->e.o.right)));
  835.     case COS:     return (fn1_eval( cos, eval(e->e.o.right)));
  836.     case EXP:     return (fn1_eval( exp, eval(e->e.o.right)));
  837.     case FABS:     return (fn1_eval( fabs, eval(e->e.o.right)));
  838.     case FLOOR:     return (fn1_eval( floor, eval(e->e.o.right)));
  839.     case HYPOT:     return (fn2_eval( hypot, eval(e->e.o.left), eval(e->e.o.right)));
  840.     case LOG:     return (fn1_eval( log, eval(e->e.o.right)));
  841.     case LOG10:     return (fn1_eval( log10, eval(e->e.o.right)));
  842.     case POW:     return (fn2_eval( pow, eval(e->e.o.left), eval(e->e.o.right)));
  843.     case SIN:     return (fn1_eval( sin, eval(e->e.o.right)));
  844.     case SQRT:     return (fn1_eval( sqrt, eval(e->e.o.right)));
  845.     case TAN:     return (fn1_eval( tan, eval(e->e.o.right)));
  846.     case DTR:     return (dtr(eval(e->e.o.right)));
  847.     case RTD:     return (rtd(eval(e->e.o.right)));
  848.     case RND:
  849.         if (rndinfinity)
  850.         {    double temp = eval(e->e.o.right);
  851.             return(temp-floor(temp) < 0.5 ?
  852.                     floor(temp) : ceil(temp));
  853.         }
  854.         else
  855.             return rint(eval(e->e.o.right));
  856.      case ROUND:
  857.         {    int prec = (int) eval(e->e.o.right);
  858.             double    scal = 1;
  859.             if (0 < prec)
  860.                 do scal *= 10; while (0 < --prec);
  861.             else if (prec < 0)
  862.                 do scal /= 10; while (++prec < 0);
  863.  
  864.             if (rndinfinity)
  865.             {    double temp = eval(e->e.o.left);
  866.                 temp *= scal;
  867.                 temp = ((temp-floor(temp)) < 0.5 ?
  868.                         floor(temp) : ceil(temp));
  869.                 return(temp / scal);
  870.             }
  871.             else
  872.                 return(rint(eval(e->e.o.left) * scal) / scal);
  873.         }
  874.     case FV:
  875.     case PV:
  876.     case PMT:    return(finfunc(e->op,eval(e->e.o.left),
  877.                    eval(e->e.o.right->e.o.left),
  878.                       eval(e->e.o.right->e.o.right)));
  879.     case HOUR:    return (dotime(HOUR, eval(e->e.o.right)));
  880.     case MINUTE:    return (dotime(MINUTE, eval(e->e.o.right)));
  881.     case SECOND:    return (dotime(SECOND, eval(e->e.o.right)));
  882.     case MONTH:    return (dotime(MONTH, eval(e->e.o.right)));
  883.     case DAY:    return (dotime(DAY, eval(e->e.o.right)));
  884.     case YEAR:    return (dotime(YEAR, eval(e->e.o.right)));
  885.     case NOW:    return (dotime(NOW, (double)0.0));
  886.     case DTS:    return (dodts((int)eval(e->e.o.left),
  887.                  (int)eval(e->e.o.right->e.o.left),
  888.                  (int)eval(e->e.o.right->e.o.right)));
  889.     case TTS:    return (dotts((int)eval(e->e.o.left),
  890.                  (int)eval(e->e.o.right->e.o.left),
  891.                  (int)eval(e->e.o.right->e.o.right)));
  892.     case STON:    return (doston(seval(e->e.o.right)));
  893.     case EQS:       return (doeqs(seval(e->e.o.right),seval(e->e.o.left)));
  894.     case LMAX:    return dolmax(e);
  895.     case LMIN:    return dolmin(e);
  896.     case NVAL:      return (donval(seval(e->e.o.left),eval(e->e.o.right)));
  897.     case MYROW:    return ((double) gmyrow);
  898.     case MYCOL:    return ((double) gmycol);
  899.     case NUMITER:    return ((double) repct);
  900.     default:    error ("Illegal numeric expression");
  901.             exprerr = 1;
  902.     }
  903.     cellerror = CELLERROR;
  904.     return((double)0.0);
  905. }
  906.  
  907. #ifdef SIGVOID
  908. void
  909. #else
  910. int
  911. #endif
  912. eval_fpe() /* Trap for FPE errors in eval */
  913. {
  914. #if defined(i386) && !defined(M_XENIX)
  915.     asm("    fnclex");
  916.     asm("    fwait");
  917. #else
  918. #ifdef IEEE_MATH
  919.     (void)fpsetsticky((fp_except)0);    /* Clear exception */
  920. #endif /* IEEE_MATH */
  921. #ifdef PC
  922.     _fpreset();
  923. #endif
  924. #endif
  925.     /* re-establish signal handler for next time */
  926.     (void) signal(SIGFPE, eval_fpe);
  927.     longjmp(fpe_save, 1);
  928. }
  929.  
  930. double fn1_eval(fn, arg)
  931. double (*fn)();
  932. double arg;
  933. {
  934.     double res;
  935.     errno = 0;
  936.     res = (*fn)(arg);
  937.     if(errno)
  938.         cellerror = CELLERROR;
  939.  
  940.     return res;
  941. }
  942.  
  943. double fn2_eval(fn, arg1, arg2)
  944. double (*fn)();
  945. double arg1, arg2;
  946. {
  947.     double res;
  948.     errno = 0;
  949.     res = (*fn)(arg1, arg2);
  950.     if(errno)
  951.         cellerror = CELLERROR;
  952.  
  953.     return res;
  954. }
  955.  
  956. /* 
  957.  * Rules for string functions:
  958.  * Take string arguments which they scxfree.
  959.  * All returned strings are assumed to be xalloced.
  960.  */
  961.  
  962. char *
  963. docat(s1, s2)
  964. register char *s1, *s2;
  965. {
  966.     register char *p;
  967.     char *arg1, *arg2;
  968.  
  969.     if (!s1 && !s2)
  970.     return((char *)0);
  971.     arg1 = s1 ? s1 : "";
  972.     arg2 = s2 ? s2 : "";
  973.     p = scxmalloc((unsigned)(strlen(arg1)+strlen(arg2)+1));
  974.     (void) strcpy(p, arg1);
  975.     (void) strcat(p, arg2);
  976.     if (s1)
  977.         scxfree(s1);
  978.     if (s2)
  979.         scxfree(s2);
  980.     return(p);
  981. }
  982.  
  983. char *
  984. dodate(tloc)
  985. long tloc;
  986. {
  987.     char *tp;
  988.     char *p;
  989.  
  990.     tp = ctime(&tloc);
  991.     tp[24] = '\0';
  992.     p = scxmalloc((unsigned)25);
  993.     (void) strcpy(p, tp);
  994.     return(p);
  995. }
  996.  
  997.  
  998. char *
  999. dofmt(fmtstr, v)
  1000. char *fmtstr;
  1001. double v;
  1002. {
  1003.     char buff[FBUFLEN];
  1004.     char *p;
  1005.  
  1006.     if (!fmtstr)
  1007.     return((char *)0);
  1008.     (void) sprintf(buff, fmtstr, v);
  1009.     p = scxmalloc((unsigned)(strlen(buff)+1));
  1010.     (void) strcpy(p, buff);
  1011.     scxfree(fmtstr);
  1012.     return(p);
  1013. }
  1014.  
  1015.  
  1016. /*
  1017.  * Given a command name and a value, run the command with the given value and
  1018.  * read and return its first output line (only) as an allocated string, always
  1019.  * a copy of prevstr, which is set appropriately first unless external
  1020.  * functions are disabled, in which case the previous value is used.  The
  1021.  * handling of prevstr and freeing of command is tricky.  Returning an
  1022.  * allocated string in all cases, even if null, insures cell expressions are
  1023.  * written to files, etc.
  1024.  */
  1025.  
  1026. #if defined(VMS) || defined(MSDOS)
  1027. char *
  1028. doext(command, value)
  1029. char *command;
  1030. double value;
  1031. {
  1032.     error("Warning: External functions unavailable on VMS");
  1033.     cellerror = CELLERROR;    /* not sure if this should be a cellerror */
  1034.     if (command)
  1035.     scxfree(command);
  1036.     return (strcpy (scxmalloc((unsigned) 1), "\0"));
  1037. }
  1038.  
  1039. #else /* VMS */
  1040.  
  1041. char *
  1042. doext (command, value)
  1043. char   *command;
  1044. double value;
  1045. {
  1046.     static char *prevstr = (char *)0;    /* previous result */
  1047.     static unsigned    prevlen = 0;
  1048.     char buff[FBUFLEN];        /* command line/return, not permanently alloc */
  1049.     extern char *strchr();
  1050.  
  1051.     if (!extfunc)    {
  1052.     error ("Warning: external functions disabled; using %s value",
  1053.         ((prevstr == NULL) || (*prevstr == '\0')) ?
  1054.             "null" : "previous");
  1055.  
  1056.     if (command) scxfree (command);
  1057.     } else {
  1058.     if ((! command) || (! *command)) {
  1059.         error ("Warning: external function given null command name");
  1060.         cellerror = CELLERROR;
  1061.         if (command) scxfree (command);
  1062.     } else {
  1063.         FILE *pp;
  1064.  
  1065.         (void) sprintf (buff, "%s %g", command, value); /* build cmd line */
  1066.         scxfree (command);
  1067.  
  1068.         error ("Running external function...");
  1069.         (void) refresh();
  1070.  
  1071.         if ((pp = popen (buff, "r")) == (FILE *) NULL) {    /* run it */
  1072.         error ("Warning: running \"%s\" failed", buff);
  1073.         cellerror = CELLERROR;
  1074.         }
  1075.         else {
  1076.         if (fgets (buff, sizeof(buff)-1, pp) == NULL)    /* one line */
  1077.             error ("Warning: external function returned nothing");
  1078.         else {
  1079.             char *cp;
  1080.  
  1081.             error ("");                /* erase notice */
  1082.             buff[sizeof(buff)-1] = '\0';
  1083.  
  1084.             if (cp = strchr (buff, '\n'))    /* contains newline */
  1085.             *cp = '\0';            /* end string there */
  1086.  
  1087.             if (strlen(buff) + 1 > prevlen)
  1088.             {    prevlen = strlen(buff) + 40;
  1089.             prevstr = scxrealloc(prevstr, prevlen);
  1090.             }
  1091.             (void) strcpy (prevstr, buff);
  1092.              /* save alloc'd copy */
  1093.         }
  1094.         (void) pclose (pp);
  1095.  
  1096.         } /* else */
  1097.     } /* else */
  1098.     } /* else */
  1099.     if (prevstr)
  1100.     return (strcpy (scxmalloc ((unsigned) (strlen (prevstr) + 1)), prevstr));
  1101.     else
  1102.     return (strcpy(scxmalloc((unsigned)1), ""));
  1103. }
  1104.  
  1105. #endif /* VMS */
  1106.  
  1107.  
  1108. /*
  1109.  * Given a string representing a column name and a value which is a column
  1110.  * number, return the selected cell's string value, if any.  Even if none,
  1111.  * still allocate and return a null string so the cell has a label value so
  1112.  * the expression is saved in a file, etc.
  1113.  */
  1114.  
  1115. char *
  1116. dosval (colstr, rowdoub)
  1117.     char *colstr;
  1118.     double rowdoub;
  1119. {
  1120.     struct ent *ep;
  1121.     char *llabel;
  1122.  
  1123.     llabel = (ep = getent (colstr, rowdoub)) ? (ep -> label) : "";
  1124.     return (strcpy (scxmalloc ((unsigned) (strlen (llabel) + 1)), llabel));
  1125. }
  1126.  
  1127.  
  1128. /*
  1129.  * Substring:  Note that v1 and v2 are one-based to users, but zero-based
  1130.  * when calling this routine.
  1131.  */
  1132.  
  1133. char *
  1134. dosubstr(s, v1, v2)
  1135. char *s;
  1136. register int v1,v2;
  1137. {
  1138.     register char *s1, *s2;
  1139.     char *p;
  1140.  
  1141.     if (!s)
  1142.     return((char *)0);
  1143.  
  1144.     if (v2 >= strlen (s))        /* past end */
  1145.     v2 =  strlen (s) - 1;        /* to end   */
  1146.  
  1147.     if (v1 < 0 || v1 > v2) {        /* out of range, return null string */
  1148.     scxfree(s);
  1149.     p = scxmalloc((unsigned)1);
  1150.     p[0] = '\0';
  1151.     return(p);
  1152.     }
  1153.     s2 = p = scxmalloc((unsigned)(v2-v1+2));
  1154.     s1 = &s[v1];
  1155.     for(; v1 <= v2; s1++, s2++, v1++)
  1156.     *s2 = *s1;
  1157.     *s2 = '\0';
  1158.     scxfree(s);
  1159.     return(p);
  1160. }
  1161.  
  1162. /*
  1163.  * character casing: make upper case, make lower case
  1164.  */
  1165.  
  1166. char *
  1167. docase( acase, s)
  1168. int acase;
  1169. char *s;
  1170. {
  1171.     char *p = s;
  1172.  
  1173.     if (s == NULL)
  1174.     return(NULL);
  1175.  
  1176.     if( acase == UPPER ) {
  1177.         while( *p != '\0' ) {
  1178.            if( islower(*p) )
  1179.         *p = toupper(*p);
  1180.        p++;
  1181.     }
  1182.     }
  1183.     else if ( acase == LOWER ) {
  1184.     while( *p != '\0' ) {
  1185.         if (isupper(*p))
  1186.         *p = tolower(*p);
  1187.         p++;
  1188.     }
  1189.     }
  1190.     return (s);
  1191. }
  1192.  
  1193. /*
  1194.  * make proper capitals of every word in a string
  1195.  * if the string has mixed case we say the string is lower
  1196.  *    and we will upcase only first letters of words
  1197.  * if the string is all upper we will lower rest of words.
  1198.  */
  1199.  
  1200. char *
  1201. docapital( s )
  1202. char *s;
  1203. {
  1204.     char *p;
  1205.     int skip = 1;
  1206.     int AllUpper = 1;
  1207.  
  1208.     if (s == NULL)
  1209.     return(NULL);
  1210.     for( p = s; *p != '\0' && AllUpper != 0; p++ )
  1211.     if( isalpha(*p) && islower(*p) )  AllUpper = 0;
  1212.     for (p = s; *p != '\0'; p++) {
  1213.     if (!isalnum(*p))
  1214.         skip = 1;
  1215.     else
  1216.     if (skip == 1) {
  1217.         skip = 0;
  1218.         if (islower(*p))
  1219.             *p = toupper(*p);
  1220.     }
  1221.     else    /* if the string was all upper before */
  1222.         if (isupper(*p) && AllUpper != 0)
  1223.         *p = tolower(*p);
  1224.     }
  1225.     return(s);
  1226. }
  1227.  
  1228. char *
  1229. seval(se)
  1230. register struct enode *se;
  1231. {
  1232.     register char *p;
  1233.  
  1234.     if (se == (struct enode *)0) return (char *)0;
  1235.     switch (se->op) {
  1236.     case O_SCONST: p = scxmalloc((unsigned)(strlen(se->e.s)+1));
  1237.              (void) strcpy(p, se->e.s);
  1238.              return(p);
  1239.     case O_VAR:    {
  1240.             struct ent *ep;
  1241.             ep = se->e.v.vp;
  1242.  
  1243.             if (!ep->label)
  1244.                 return((char *)0);
  1245.             p = scxmalloc((unsigned)(strlen(ep->label)+1));
  1246.             (void) strcpy(p, ep->label);
  1247.             return(p);
  1248.              }
  1249.     case '#':    return(docat(seval(se->e.o.left), seval(se->e.o.right)));
  1250.     case 'f':    return(seval(se->e.o.right));
  1251.     case IF:
  1252.     case '?':    return(eval(se->e.o.left) ? seval(se->e.o.right->e.o.left)
  1253.                          : seval(se->e.o.right->e.o.right));
  1254.     case DATE:   return(dodate((long)(eval(se->e.o.right))));
  1255.     case FMT:    return(dofmt(seval(se->e.o.left), eval(se->e.o.right)));
  1256.     case UPPER:  return(docase(UPPER, seval(se->e.o.right)));
  1257.     case LOWER:  return(docase(LOWER, seval(se->e.o.right)));
  1258.     case CAPITAL:return(docapital(seval(se->e.o.right)));
  1259.      case STINDEX:
  1260.          {    register r,c;
  1261.          register maxr, maxc;
  1262.          register minr, minc;
  1263.          maxr = se->e.o.right->e.r.right.vp -> row;
  1264.          maxc = se->e.o.right->e.r.right.vp -> col;
  1265.          minr = se->e.o.right->e.r.left.vp -> row;
  1266.          minc = se->e.o.right->e.r.left.vp -> col;
  1267.          if (minr>maxr) r = maxr, maxr = minr, minr = r;
  1268.          if (minc>maxc) c = maxc, maxc = minc, minc = c;
  1269.              return dostindex(eval(se->e.o.left), minr, minc, maxr, maxc);
  1270.         }
  1271.     case EXT:    return(doext(seval(se->e.o.left), eval(se->e.o.right)));
  1272.     case SVAL:   return(dosval(seval(se->e.o.left), eval(se->e.o.right)));
  1273.     case SUBSTR: return(dosubstr(seval(se->e.o.left),
  1274.                 (int)eval(se->e.o.right->e.o.left) - 1,
  1275.                 (int)eval(se->e.o.right->e.o.right) - 1));
  1276.     case COLTOA: return(strcpy(scxmalloc((unsigned)10),
  1277.                    coltoa((int)eval(se->e.o.right)+1)));
  1278.     default:
  1279.              error ("Illegal string expression");
  1280.              exprerr = 1;
  1281.              return(NULL);
  1282.     }
  1283. }
  1284.  
  1285. /*
  1286.  * The graph formed by cell expressions which use other cells's values is not
  1287.  * evaluated "bottom up".  The whole table is merely re-evaluated cell by cell,
  1288.  * top to bottom, left to right, in RealEvalAll().  Each cell's expression uses
  1289.  * constants in other cells.  However, RealEvalAll() notices when a cell gets a
  1290.  * new numeric or string value, and reports if this happens for any cell.
  1291.  * EvalAll() repeats calling RealEvalAll() until there are no changes or the
  1292.  * evaluation count expires.
  1293.  */
  1294.  
  1295. int propagation = 10;    /* max number of times to try calculation */
  1296. int repct = 1;        /* Make repct a global variable so that the 
  1297.                 function @numiter can access it */
  1298.  
  1299. void
  1300. setiterations(i)
  1301. int i;
  1302. {
  1303.     if(i<1) {
  1304.         error("iteration count must be at least 1");
  1305.         propagation = 1;
  1306.         }
  1307.     else propagation = i;
  1308. }
  1309.  
  1310. void
  1311. EvalAll () {
  1312.      int lastcnt;
  1313.   
  1314.      repct = 1;
  1315.      (void) signal(SIGFPE, eval_fpe);
  1316.  
  1317.      while ((lastcnt = RealEvalAll()) && (++repct <= propagation));
  1318.      if((propagation>1)&& (lastcnt >0 ))
  1319.          error("Still changing after %d iterations",propagation-1);
  1320.  
  1321.     (void) signal(SIGFPE, doquit);
  1322. }
  1323.  
  1324. /*
  1325.  * Evaluate all cells which have expressions and alter their numeric or string
  1326.  * values.  Return the number of cells which changed.
  1327.  */
  1328.  
  1329. int 
  1330. RealEvalAll () {
  1331.     register int i,j;
  1332.     int chgct = 0;
  1333.     register struct ent *p;
  1334.  
  1335.     if(calc_order == BYROWS ) {
  1336.     for (i=0; i<=maxrow; i++)
  1337.         for (j=0; j<=maxcol; j++)
  1338.         if ((p = *ATBL(tbl,i,j)) && !(p->flags&is_locked) && p->expr) RealEvalOne(p,i,j,&chgct);
  1339.     }
  1340.     else if ( calc_order == BYCOLS ) {
  1341.     for (j=0; j<=maxcol; j++)
  1342.     {   for (i=0; i<=maxrow; i++)
  1343.         if ((p = *ATBL(tbl,i,j)) && !(p->flags&is_locked) && p->expr) RealEvalOne(p,i,j,&chgct);
  1344.     }
  1345.     }
  1346.     else error("Internal error calc_order");
  1347.  
  1348.     return(chgct);
  1349. }
  1350.  
  1351. void
  1352. RealEvalOne(p, i, j, chgct)
  1353. register struct ent *p;
  1354. int i, j, *chgct;
  1355. {
  1356.     if (p->flags & is_strexpr) {
  1357.         char *v;
  1358.         if (setjmp(fpe_save)) {
  1359.         error("Floating point exception %s", v_name(i, j));
  1360.         cellerror = CELLERROR;
  1361.         v = "";
  1362.         } else {
  1363.         cellerror = CELLOK;
  1364.         v = seval(p->expr);
  1365.         }
  1366.         p->cellerror = cellerror;
  1367.         if (!v && !p->label) /* Everything's fine */
  1368.         return;
  1369.         if (!p->label || !v || strcmp(v, p->label) != 0 || cellerror) {
  1370.         (*chgct)++;
  1371.         p->flags |= is_changed;
  1372.         changed++;
  1373.         }
  1374.         if(p->label)
  1375.         scxfree(p->label);
  1376.         p->label = v;
  1377.     } else {
  1378.         double v;
  1379.         if (setjmp(fpe_save)) {
  1380.         error("Floating point exception %s", v_name(i, j));
  1381.         cellerror = CELLERROR;
  1382.         v = (double)0.0;
  1383.         } else {
  1384.         cellerror = CELLOK;
  1385.         gmyrow=i; gmycol=j;
  1386.         v = eval (p->expr);
  1387.         }
  1388.         if ((p->cellerror = cellerror) || (v != p->v)) {
  1389.         p->v = v;
  1390.         if (!cellerror)        /* don't keep eval'ing a error */
  1391.             (*chgct)++;
  1392.         p->flags |= is_changed|is_valid;
  1393.         changed++;
  1394.         }
  1395.     }
  1396. }
  1397.  
  1398. struct enode *
  1399. new(op, a1, a2)
  1400. int    op;
  1401. struct enode *a1, *a2;
  1402. {
  1403.     register struct enode *p;
  1404.     if (freeenodes)
  1405.     {    p = freeenodes;
  1406.     freeenodes = p->e.o.left;
  1407.     }
  1408.     else
  1409.     p = (struct enode *) scxmalloc ((unsigned)sizeof (struct enode));
  1410.     p->op = op;
  1411.     p->e.o.left = a1;
  1412.     p->e.o.right = a2;
  1413.     return p;
  1414. }
  1415.  
  1416. struct enode *
  1417. new_var(op, a1)
  1418. int    op;
  1419. struct ent_ptr a1;
  1420. {
  1421.     register struct enode *p;
  1422.     if (freeenodes)
  1423.     {    p = freeenodes;
  1424.     freeenodes = p->e.o.left;
  1425.     }
  1426.     else
  1427.     p = (struct enode *) scxmalloc ((unsigned)sizeof (struct enode));
  1428.     p->op = op;
  1429.     p->e.v = a1;
  1430.     return p;
  1431. }
  1432.  
  1433. struct enode *
  1434. new_range(op, a1)
  1435. int    op;
  1436. struct range_s a1;
  1437. {
  1438.     register struct enode *p;
  1439.     if (freeenodes)
  1440.     {    p = freeenodes;
  1441.     freeenodes = p->e.o.left;
  1442.     }
  1443.     else
  1444.     p = (struct enode *) scxmalloc ((unsigned)sizeof (struct enode));
  1445.     p->op = op;
  1446.     p->e.r = a1;
  1447.     return p;
  1448. }
  1449.  
  1450. struct enode *
  1451. new_const(op, a1)
  1452. int    op;
  1453. double a1;
  1454. {
  1455.     register struct enode *p;
  1456.     if (freeenodes)    /* reuse an already free'd enode */
  1457.     {    p = freeenodes;
  1458.     freeenodes = p->e.o.left;
  1459.     }
  1460.     else
  1461.     p = (struct enode *) scxmalloc ((unsigned)sizeof (struct enode));
  1462.     p->op = op;
  1463.     p->e.k = a1;
  1464.     return p;
  1465. }
  1466.  
  1467. struct enode *
  1468. new_str(s)
  1469. char *s;
  1470. {
  1471.     register struct enode *p;
  1472.  
  1473.     if (freeenodes)    /* reuse an already free'd enode */
  1474.     {    p = freeenodes;
  1475.     freeenodes = p->e.o.left;
  1476.     }
  1477.     else
  1478.     p = (struct enode *) scxmalloc ((unsigned)sizeof(struct enode));
  1479.     p->op = O_SCONST;
  1480.     p->e.s = s;
  1481.     return(p);
  1482. }
  1483.  
  1484. void
  1485. copy(dv1, dv2, v1, v2)
  1486. struct ent *dv1, *dv2, *v1, *v2;
  1487. {
  1488.     int minsr, minsc;
  1489.     int maxsr, maxsc;
  1490.     int mindr, mindc;
  1491.     int maxdr, maxdc;
  1492.     int vr, vc;
  1493.     int r, c;
  1494.  
  1495.     mindr = dv1->row;
  1496.     mindc = dv1->col;
  1497.     maxdr = dv2->row;
  1498.     maxdc = dv2->col;
  1499.     if (mindr>maxdr) r = maxdr, maxdr = mindr, mindr = r;
  1500.     if (mindc>maxdc) c = maxdc, maxdc = mindc, mindc = c;
  1501.     maxsr = v2->row;
  1502.     maxsc = v2->col;
  1503.     minsr = v1->row;
  1504.     minsc = v1->col;
  1505.     if (minsr>maxsr) r = maxsr, maxsr = minsr, minsr = r;
  1506.     if (minsc>maxsc) c = maxsc, maxsc = minsc, minsc = c;
  1507.     checkbounds(&maxdr, &maxdc);
  1508.  
  1509.     erase_area(mindr, mindc, maxdr, maxdc);
  1510.     if (minsr == maxsr && minsc == maxsc) {
  1511.     /* Source is a single cell */
  1512.     for(vr = mindr; vr <= maxdr; vr++)
  1513.         for (vc = mindc; vc <= maxdc; vc++)
  1514.         copyrtv(vr, vc, minsr, minsc, maxsr, maxsc);
  1515.     } else if (minsr == maxsr) {
  1516.     /* Source is a single row */
  1517.     for (vr = mindr; vr <= maxdr; vr++)
  1518.         copyrtv(vr, mindc, minsr, minsc, maxsr, maxsc);
  1519.     } else if (minsc == maxsc) {
  1520.     /* Source is a single column */
  1521.     for (vc = mindc; vc <= maxdc; vc++)
  1522.         copyrtv(mindr, vc, minsr, minsc, maxsr, maxsc);
  1523.     } else {
  1524.     /* Everything else */
  1525.     copyrtv(mindr, mindc, minsr, minsc, maxsr, maxsc);
  1526.     }
  1527.     sync_refs();
  1528. }
  1529.  
  1530. void
  1531. copyrtv(vr, vc, minsr, minsc, maxsr, maxsc)
  1532. int vr, vc, minsr, minsc, maxsr, maxsc;
  1533. {
  1534.     register struct ent *p;
  1535.     register struct ent *n;
  1536.     register int sr, sc;
  1537.     register int dr, dc;
  1538.  
  1539.     for (dr=vr, sr=minsr; sr<=maxsr; sr++, dr++)
  1540.     for (dc=vc, sc=minsc; sc<=maxsc; sc++, dc++) {
  1541.         if (p = *ATBL(tbl, sr, sc))
  1542.         {    n = lookat (dr, dc);
  1543.         if (n->flags&is_locked) continue;
  1544.         (void) clearent(n);
  1545.         copyent( n, p, dr - sr, dc - sc);
  1546.         }
  1547.         else
  1548.         if (n = *ATBL(tbl, dr, dc))
  1549.         (void) clearent(n);
  1550.     }
  1551. }
  1552.  
  1553. /* ERASE a Range of cells */
  1554. void
  1555. eraser(v1, v2)
  1556. struct ent *v1, *v2;
  1557. {
  1558.     FullUpdate++;
  1559.     flush_saved();
  1560.     erase_area(v1->row, v1->col, v2->row, v2->col);
  1561.     sync_refs();
  1562. }
  1563.  
  1564. /* Goto subroutines */
  1565.  
  1566. void
  1567. g_free()
  1568. {
  1569.     switch (gs.g_type) {
  1570.     case G_STR: scxfree(gs.g_s); break;
  1571.     default: break;
  1572.     }
  1573.     gs.g_type = G_NONE;
  1574.     gs.errsearch = 0;
  1575. }
  1576.  
  1577. /* repeat the last goto command */
  1578. void
  1579. go_last()
  1580. {
  1581.     switch (gs.g_type) {
  1582.     case G_NONE:
  1583.         error("Nothing to repeat"); break;
  1584.     case G_NUM:
  1585.         num_search(gs.g_n, gs.errsearch);
  1586.         break;
  1587.     case  G_CELL:
  1588.         moveto(gs.g_row, gs.g_col);
  1589.             break;
  1590.     case  G_STR: 
  1591.         gs.g_type = G_NONE;    /* Don't free the string */
  1592.                str_search(gs.g_s); 
  1593.            break;
  1594.  
  1595.     default: error("go_last: internal error");
  1596.     }
  1597. }
  1598.  
  1599. /* place the cursor on a given cell */
  1600. void
  1601. moveto(row, col)
  1602. int row, col;
  1603. {
  1604.     currow = row;
  1605.     curcol = col;
  1606.     g_free();
  1607.     gs.g_type = G_CELL;
  1608.     gs.g_row = currow;
  1609.     gs.g_col = curcol;
  1610. }
  1611.  
  1612. /*
  1613.  * 'goto' either a given number,'error', or 'invalid' starting at currow,curcol
  1614.  */
  1615. void
  1616. num_search(n, errsearch)
  1617. double n;
  1618. int    errsearch;
  1619. {
  1620.     register struct ent *p;
  1621.     register int r,c;
  1622.     int    endr, endc;
  1623.  
  1624.     g_free();
  1625.     gs.g_type = G_NUM;
  1626.     gs.g_n = n;
  1627.     gs.errsearch = errsearch;
  1628.  
  1629.     if (currow > maxrow)
  1630.     endr = maxrow ? maxrow-1 : 0;
  1631.     else
  1632.     endr = currow;
  1633.     if (curcol > maxcol)
  1634.     endc = maxcol ? maxcol-1 : 0;
  1635.     else
  1636.     endc = curcol;
  1637.     r = endr;
  1638.     c = endc;
  1639.     do {
  1640.     if (c < maxcol)
  1641.         c++;
  1642.     else {
  1643.         if (r < maxrow) {
  1644.         while(++r < maxrow && row_hidden[r]) /* */;
  1645.         c = 0;
  1646.         } else {
  1647.         r = 0;
  1648.         c = 0;
  1649.         }
  1650.     }
  1651.     if (r == endr && c == endc) {
  1652.         if (errsearch)
  1653.         error("no %s cell found", errsearch == CELLERROR ? "ERROR" :
  1654.               "INVALID");
  1655.         else
  1656.         error("Number not found");
  1657.         return;
  1658.     }
  1659.     p = *ATBL(tbl, r, c);
  1660.     } while (col_hidden[c] || !p || !(p->flags & is_valid)
  1661.     || (!errsearch && (p->v != n))
  1662.     || (errsearch && !((p->cellerror == errsearch) ||
  1663.         (p->cellerror == errsearch))));    /* CELLERROR vs CELLINVALID */
  1664.         
  1665.     currow = r;
  1666.     curcol = c;
  1667. }
  1668.  
  1669. /* 'goto' a cell containing a matching string */
  1670. void
  1671. str_search(s)
  1672. char *s;
  1673. {
  1674.     register struct ent *p;
  1675.     register int r,c;
  1676.     int    endr, endc;
  1677.     char *tmp;
  1678.  
  1679. #if defined(RE_COMP)
  1680.     if ((tmp = re_comp(s)) != (char *)0) {
  1681.     scxfree(s);
  1682.     error(tmp);
  1683.     return;
  1684.     }
  1685. #endif
  1686. #if defined(REGCMP)
  1687.     if ((tmp = regcmp(s, (char *)0)) == (char *)0) {
  1688.     scxfree(s);
  1689.     cellerror = CELLERROR;
  1690.     error("Invalid search string");
  1691.     return;
  1692.     }
  1693. #endif
  1694.     g_free();
  1695.     gs.g_type = G_STR;
  1696.     gs.g_s = s;
  1697.     if (currow > maxrow)
  1698.     endr = maxrow ? maxrow-1 : 0;
  1699.     else
  1700.     endr = currow;
  1701.     if (curcol > maxcol)
  1702.     endc = maxcol ? maxcol-1 : 0;
  1703.     else
  1704.     endc = curcol;
  1705.     r = endr;
  1706.     c = endc;
  1707.     do {
  1708.     if (c < maxcol)
  1709.         c++;
  1710.     else {
  1711.         if (r < maxrow) {
  1712.         while(++r < maxrow && row_hidden[r]) /* */;
  1713.         c = 0;
  1714.         } else {
  1715.         r = 0;
  1716.         c = 0;
  1717.         }
  1718.     }
  1719.     if (r == endr && c == endc) {
  1720.         error("String not found");
  1721. #if defined(REGCMP)
  1722.         free(tmp);
  1723. #endif
  1724.         return;
  1725.     }
  1726.     p = *ATBL(tbl, r, c);
  1727.     } while(col_hidden[c] || !p || !(p->label)
  1728. #if defined(RE_COMP)
  1729.                       || (re_exec(p->label) == 0));
  1730. #else
  1731. #if defined(REGCMP)
  1732.                 || (regex(tmp, p->label) == (char *)0));
  1733. #else
  1734.                     || (strcmp(s, p->label) != 0));
  1735. #endif
  1736. #endif
  1737.     currow = r;
  1738.     curcol = c;
  1739. #if defined(REGCMP)
  1740.     free(tmp);
  1741. #endif
  1742. }
  1743.  
  1744. /* fill a range with constants */
  1745. void
  1746. fill (v1, v2, start, inc)
  1747. struct ent *v1, *v2;
  1748. double start, inc;
  1749. {
  1750.     register r,c;
  1751.     register struct ent *n;
  1752.     int maxr, maxc;
  1753.     int minr, minc;
  1754.  
  1755.     maxr = v2->row;
  1756.     maxc = v2->col;
  1757.     minr = v1->row;
  1758.     minc = v1->col;
  1759.     if (minr>maxr) r = maxr, maxr = minr, minr = r;
  1760.     if (minc>maxc) c = maxc, maxc = minc, minc = c;
  1761.     checkbounds(&maxr, &maxc);
  1762.     if (minr < 0) minr = 0;
  1763.     if (minc < 0) minc = 0;
  1764.  
  1765.     FullUpdate++;
  1766.     if( calc_order == BYROWS ) {
  1767.     for (r = minr; r<=maxr; r++)
  1768.     for (c = minc; c<=maxc; c++) {
  1769.         n = lookat (r, c);
  1770.         if (n->flags&is_locked) continue;
  1771.         (void) clearent(n);
  1772.         n->v = start;
  1773.         start += inc;
  1774.         n->flags |= (is_changed|is_valid);
  1775.     }
  1776.     }
  1777.     else if ( calc_order == BYCOLS ) {
  1778.     for (c = minc; c<=maxc; c++)
  1779.     for (r = minr; r<=maxr; r++) {
  1780.         n = lookat (r, c);
  1781.         (void) clearent(n);
  1782.         n->v = start;
  1783.         start += inc;
  1784.         n->flags |= (is_changed|is_valid);
  1785.     }
  1786.     }
  1787.     else error(" Internal error calc_order");
  1788.     changed++;
  1789. }
  1790.  
  1791. /* lock a range of cells */
  1792.  
  1793. void
  1794. lock_cells (v1, v2)
  1795. struct ent *v1, *v2;
  1796. {
  1797.     register r,c;
  1798.     register struct ent *n;
  1799.     int maxr, maxc;
  1800.     int minr, minc;
  1801.  
  1802.     maxr = v2->row;
  1803.     maxc = v2->col;
  1804.     minr = v1->row;
  1805.     minc = v1->col;
  1806.     if (minr>maxr) r = maxr, maxr = minr, minr = r;
  1807.     if (minc>maxc) c = maxc, maxc = minc, minc = c;
  1808.     checkbounds(&maxr, &maxc);
  1809.     if (minr < 0) minr = 0;
  1810.     if (minc < 0) minc = 0;
  1811.  
  1812.     for (r = minr; r<=maxr; r++)
  1813.     for (c = minc; c<=maxc; c++) {
  1814.         n = lookat (r, c);
  1815.         n->flags |= is_locked;
  1816.     }
  1817. }
  1818.  
  1819. /* unlock a range of cells */
  1820.  
  1821. void
  1822. unlock_cells (v1, v2)
  1823. struct ent *v1, *v2;
  1824. {
  1825.     register r,c;
  1826.     register struct ent *n;
  1827.     int maxr, maxc;
  1828.     int minr, minc;
  1829.  
  1830.     maxr = v2->row;
  1831.     maxc = v2->col;
  1832.     minr = v1->row;
  1833.     minc = v1->col;
  1834.     if (minr>maxr) r = maxr, maxr = minr, minr = r;
  1835.     if (minc>maxc) c = maxc, maxc = minc, minc = c;
  1836.     checkbounds(&maxr, &maxc);
  1837.     if (minr < 0) minr = 0;
  1838.     if (minc < 0) minc = 0;
  1839.  
  1840.     for (r = minr; r<=maxr; r++)
  1841.     for (c = minc; c<=maxc; c++) {
  1842.         n = lookat (r, c);
  1843.         n->flags &= ~is_locked;
  1844.     }
  1845. }
  1846.  
  1847. /* set the numeric part of a cell */
  1848. void
  1849. let (v, e)
  1850. struct ent *v;
  1851. struct enode *e;
  1852. {
  1853.     double val;
  1854.     unsigned isconstant = constant(e);
  1855.  
  1856.     if (loading && !isconstant)
  1857.     val = (double)0.0;
  1858.     else
  1859.     {
  1860.     exprerr = 0;
  1861.     (void) signal(SIGFPE, eval_fpe);
  1862.     if (setjmp(fpe_save)) {
  1863.         error ("Floating point exception in cell %s", v_name(v->row, v->col));
  1864.         val = (double)0.0;
  1865.         cellerror = CELLERROR;
  1866.     } else {
  1867.         cellerror = CELLOK;
  1868.         val = eval(e);
  1869.     }
  1870.     if (v->cellerror != cellerror)
  1871.     {    v->flags |= is_changed;
  1872.         changed++;    modflg++;
  1873.         FullUpdate++;
  1874.         v->cellerror = cellerror;
  1875.     }
  1876.     (void) signal(SIGFPE, doquit);
  1877.     if (exprerr) {
  1878.         efree(e);
  1879.         return;
  1880.     }
  1881.     }
  1882.  
  1883.     if (isconstant) {
  1884.     /* prescale input unless it has a decimal */
  1885. #if defined(IEEE_MATH) && !defined(NO_FMOD)
  1886.     if (!loading && (prescale < (double)0.9999999) &&
  1887.                 (fmod(val, (double)1.0) == (double)0))
  1888. #else
  1889.     if (!loading && (prescale < (double)0.9999999) &&
  1890.             ((val - floor(val)) == (double)0))
  1891. #endif
  1892.         val *= prescale;
  1893.  
  1894.     v->v = val;
  1895.  
  1896.     if (!(v->flags & is_strexpr)) {
  1897.             efree(v->expr);
  1898.         v->expr = (struct enode *)0;
  1899.     }
  1900.     efree(e);
  1901.     }
  1902.     else
  1903.     {
  1904.     efree(v->expr);
  1905.     v->expr = e;
  1906.     v->flags &= ~is_strexpr;
  1907.     }
  1908.  
  1909.     changed++; modflg++;
  1910.     v->flags |= (is_changed|is_valid);
  1911. }
  1912.  
  1913. void
  1914. slet (v, se, flushdir)
  1915. struct ent *v;
  1916. struct enode *se;
  1917. int flushdir;
  1918. {
  1919.     char *p;
  1920.  
  1921.     exprerr = 0;
  1922.     (void) signal(SIGFPE, eval_fpe);
  1923.     if (setjmp(fpe_save)) {
  1924.     error ("Floating point exception in cell %s", v_name(v->row, v->col));
  1925.     cellerror = CELLERROR;
  1926.     p = "";
  1927.     } else {
  1928.     cellerror = CELLOK;
  1929.     p = seval(se);
  1930.     }
  1931.     if (v->cellerror != cellerror)
  1932.     {    v->flags |= is_changed;
  1933.     changed++;    modflg++;
  1934.     FullUpdate++;
  1935.     v->cellerror = cellerror;
  1936.     }
  1937.     (void) signal(SIGFPE, doquit);
  1938.     if (exprerr) {
  1939.     efree(se);
  1940.     return;
  1941.     }
  1942.     if (constant(se)) {
  1943.     label(v, p, flushdir);
  1944.     if (p)
  1945.         scxfree(p);
  1946.     efree(se);
  1947.     if (v->flags & is_strexpr) {
  1948.             efree(v->expr);
  1949.         v->expr = (struct enode *)0;
  1950.         v->flags &= ~is_strexpr;
  1951.     }
  1952.     return;
  1953.     }
  1954.     efree(v->expr);
  1955.     v->expr = se;
  1956.     v->flags |= (is_changed|is_strexpr);
  1957.     if (flushdir<0) v->flags |= is_leftflush;
  1958.  
  1959.     if (flushdir==0)
  1960.     v->flags |= is_label;
  1961.     else v->flags &= ~is_label;
  1962.  
  1963.     FullUpdate++;
  1964.     changed++;
  1965.     modflg++;
  1966. }
  1967.  
  1968. void
  1969. format_cell(v1, v2, s)
  1970. struct ent *v1, *v2;
  1971. char *s;
  1972. {
  1973.     register r,c;
  1974.     register struct ent *n;
  1975.     int maxr, maxc;
  1976.     int minr, minc;
  1977.  
  1978.     maxr = v2->row;
  1979.     maxc = v2->col;
  1980.     minr = v1->row;
  1981.     minc = v1->col;
  1982.     if (minr>maxr) r = maxr, maxr = minr, minr = r;
  1983.     if (minc>maxc) c = maxc, maxc = minc, minc = c;
  1984.     checkbounds(&maxr, &maxc);
  1985.     if (minr < 0) minr = 0;
  1986.     if (minc < 0) minc = 0;
  1987.  
  1988.     FullUpdate++;
  1989.     modflg++;
  1990.     for (r = minr; r <= maxr; r++)
  1991.     for (c = minc; c <= maxc; c++) {
  1992.         n = lookat (r, c);
  1993.         if (n->flags&is_locked) {
  1994.         error("Cell %s%d is locked", coltoa(n->col), n->row);
  1995.         continue;
  1996.         }
  1997.         if (n->format)
  1998.         scxfree(n->format);
  1999.         n->format = 0;
  2000.         if (s && *s != '\0')
  2001.         n->format = strcpy(scxmalloc((unsigned)(strlen(s)+1)), s);
  2002.         n->flags |= is_changed;
  2003.        }
  2004. }
  2005.  
  2006. void
  2007. hide_row(arg)
  2008. int arg;
  2009. {
  2010.     if (arg < 0) {
  2011.     error("Invalid Range");
  2012.     return;
  2013.     }
  2014.     if (arg >= maxrows-1)
  2015.     {
  2016.     if (!growtbl(GROWROW, arg+1, 0))
  2017.     {    error("You can't hide the last row");
  2018.         return;
  2019.     }
  2020.     }
  2021.     FullUpdate++;
  2022.     row_hidden[arg] = 1;
  2023. }
  2024.  
  2025. void
  2026. hide_col(arg)
  2027. int arg;
  2028. {
  2029.     if (arg < 0) {
  2030.     error("Invalid Range");
  2031.     return;
  2032.     }
  2033.     if (arg >= maxcols-1)
  2034.     {    if ((arg >= ABSMAXCOLS-1) || !growtbl(GROWCOL, 0, arg+1))
  2035.     {    error("You can't hide the last col");
  2036.         return;
  2037.     }
  2038.     }
  2039.     FullUpdate++;
  2040.     col_hidden[arg] = TRUE;
  2041. }
  2042.  
  2043. void
  2044. clearent (v)
  2045. struct ent *v;
  2046. {
  2047.     if (!v)
  2048.     return;
  2049.     label(v,"",-1);
  2050.     v->v = (double)0;
  2051.     if (v->expr)
  2052.     efree(v->expr);
  2053.     v->expr = (struct enode *)0;
  2054.     if (v->format)
  2055.     scxfree(v->format);
  2056.     v->format = (char *)0;
  2057.     v->flags |= (is_changed);
  2058.     v->flags &= ~(is_valid);
  2059.     changed++;
  2060.     modflg++;
  2061. }
  2062.  
  2063. /*
  2064.  * Say if an expression is a constant (return 1) or not.
  2065.  */
  2066. int
  2067. constant (e)
  2068.     register struct enode *e;
  2069. {
  2070.     return (
  2071.      e == (struct enode *)0
  2072.      || e -> op == O_CONST
  2073.      || e -> op == O_SCONST
  2074.      || (
  2075.          e -> op != O_VAR
  2076.          && (e -> op & REDUCE) != REDUCE
  2077.          && constant (e -> e.o.left)
  2078.          && constant (e -> e.o.right)
  2079.          && e -> op != EXT     /* functions look like constants but aren't */
  2080.          && e -> op != NVAL
  2081.          && e -> op != SVAL
  2082.          && e -> op != NOW
  2083.          && e -> op != MYROW
  2084.          && e -> op != MYCOL
  2085.          && e -> op != NUMITER
  2086.     )
  2087.     );
  2088. }
  2089.  
  2090. void
  2091. efree (e)
  2092. struct enode *e;
  2093. {
  2094.     if (e) {
  2095.     if (e->op != O_VAR && e->op !=O_CONST && e->op != O_SCONST
  2096.         && (e->op & REDUCE) != REDUCE) {
  2097.         efree(e->e.o.left);
  2098.         efree(e->e.o.right);
  2099.     }
  2100.     if (e->op == O_SCONST && e->e.s)
  2101.         scxfree(e->e.s);
  2102.     e->e.o.left = freeenodes;
  2103.     freeenodes = e;
  2104.     }
  2105. }
  2106.  
  2107. void
  2108. label (v, s, flushdir)
  2109. register struct ent *v;
  2110. register char *s;
  2111. int    flushdir;
  2112. {
  2113.     if (v) {
  2114.     if (flushdir==0 && v->flags&is_valid) {
  2115.         register struct ent *tv;
  2116.         if (v->col>0 && ((tv=lookat(v->row,v->col-1))->flags&is_valid)==0)
  2117.         v = tv, flushdir = 1;
  2118.         else if (((tv=lookat (v->row,v->col+1))->flags&is_valid)==0)
  2119.         v = tv, flushdir = -1;
  2120.         else flushdir = -1;
  2121.     }
  2122.     if (v->label) scxfree((char *)(v->label));
  2123.     if (s && s[0]) {
  2124.         v->label = scxmalloc ((unsigned)(strlen(s)+1));
  2125.         (void) strcpy (v->label, s);
  2126.     } else
  2127.         v->label = (char *)0;
  2128.     if (flushdir<0) v->flags |= is_leftflush;
  2129.     else v->flags &= ~is_leftflush;
  2130.     if (flushdir==0) v->flags |= is_label;
  2131.     else v->flags &= ~is_label;
  2132.     FullUpdate++;
  2133.     modflg++;
  2134.     }
  2135. }
  2136.  
  2137. void
  2138. decodev (v)
  2139. struct ent_ptr v; 
  2140. {
  2141.     register struct range *r;
  2142.  
  2143.     if (!v.vp) (void) sprintf (line+linelim,"VAR?");
  2144.     else if ((r = find_range((char *)0, 0, v.vp, v.vp)) && !r->r_is_range)
  2145.         (void) sprintf(line+linelim, "%s", r->r_name);
  2146.     else
  2147.         (void) sprintf (line+linelim, "%s%s%s%d",
  2148.             v.vf & FIX_COL ? "$" : "",
  2149.             coltoa(v.vp->col),
  2150.             v.vf & FIX_ROW ? "$" : "",
  2151.             v.vp->row);
  2152.     linelim += strlen (line+linelim);
  2153. }
  2154.  
  2155. char *
  2156. coltoa(col)
  2157. int col;
  2158. {
  2159.     static char rname[3];
  2160.     register char *p = rname;
  2161.  
  2162.     if (col > 25) {
  2163.     *p++ = col/26 + 'A' - 1;
  2164.     col %= 26;
  2165.     }
  2166.     *p++ = col+'A';
  2167.     *p = '\0';
  2168.     return(rname);
  2169. }
  2170.  
  2171. /*
  2172.  *    To make list elements come out in the same order
  2173.  *    they were entered, we must do a depth-first eval
  2174.  *    of the ELIST tree
  2175.  */
  2176. static void
  2177. decompile_list(p)
  2178. struct enode *p;
  2179. {
  2180.     if (!p) return;
  2181.     decompile_list(p->e.o.left);    /* depth first */
  2182.         decompile(p->e.o.right, 0);
  2183.     line[linelim++] = ',';
  2184. }
  2185.  
  2186. void
  2187. decompile(e, priority)
  2188. register struct enode *e;
  2189. int    priority;
  2190. {
  2191.     register char *s;
  2192.     if (e) {
  2193.     int mypriority;
  2194.     switch (e->op) {
  2195.     default: mypriority = 99; break;
  2196.     case '?': mypriority = 1; break;
  2197.     case ':': mypriority = 2; break;
  2198.     case '|': mypriority = 3; break;
  2199.     case '&': mypriority = 4; break;
  2200.     case '<': case '=': case '>': mypriority = 6; break;
  2201.     case '+': case '-': case '#': mypriority = 8; break;
  2202.     case '*': case '/': case '%': mypriority = 10; break;
  2203.     case '^': mypriority = 12; break;
  2204.     }
  2205.     if (mypriority<priority) line[linelim++] = '(';
  2206.     switch (e->op) {
  2207.     case 'f':    for (s="fixed "; line[linelim++] = *s++;);
  2208.             linelim--;
  2209.             decompile (e->e.o.right, 30);
  2210.             break;
  2211.     case 'm':    line[linelim++] = '-';
  2212.             decompile (e->e.o.right, 30);
  2213.             break;
  2214.     case '~':    line[linelim++] = '~';
  2215.             decompile (e->e.o.right, 30);
  2216.             break;
  2217.     case O_VAR:    decodev (e->e.v);
  2218.             break;
  2219.     case O_CONST:    (void) sprintf (line+linelim,"%.15g",e->e.k);
  2220.             linelim += strlen (line+linelim);
  2221.             break;
  2222.     case O_SCONST:    (void) sprintf (line+linelim, "\"%s\"", e->e.s);
  2223.             linelim += strlen(line+linelim);
  2224.             break;
  2225.  
  2226.     case REDUCE | '+': range_arg( "@sum(", e); break;
  2227.     case REDUCE | '*': range_arg( "@prod(", e); break;
  2228.     case REDUCE | 'a': range_arg( "@avg(", e); break;
  2229.     case REDUCE | 'c': range_arg( "@count(", e); break;
  2230.     case REDUCE | 's': range_arg( "@stddev(", e); break;
  2231.     case REDUCE | MAX: range_arg( "@max(", e); break;
  2232.     case REDUCE | MIN: range_arg( "@min(", e); break;
  2233.  
  2234.     case ABS:        one_arg( "@abs(", e); break;
  2235.     case ACOS:    one_arg( "@acos(", e); break;
  2236.     case ASIN:    one_arg( "@asin(", e); break;
  2237.     case ATAN:    one_arg( "@atan(", e); break;
  2238.     case ATAN2:    two_arg( "@atan2(", e); break;
  2239.     case CEIL:    one_arg( "@ceil(", e); break;
  2240.     case COS:    one_arg( "@cos(", e); break;
  2241.     case EXP:    one_arg( "@exp(", e); break;
  2242.     case FABS:    one_arg( "@fabs(", e); break;
  2243.     case FLOOR:    one_arg( "@floor(", e); break;
  2244.     case HYPOT:    two_arg( "@hypot(", e); break;
  2245.     case LOG:    one_arg( "@ln(", e); break;
  2246.     case LOG10:    one_arg( "@log(", e); break;
  2247.     case POW:    two_arg( "@pow(", e); break;
  2248.     case SIN:    one_arg( "@sin(", e); break;
  2249.     case SQRT:    one_arg( "@sqrt(", e); break;
  2250.     case TAN:    one_arg( "@tan(", e); break;
  2251.     case DTR:    one_arg( "@dtr(", e); break;
  2252.     case RTD:    one_arg( "@rtd(", e); break;
  2253.     case RND:    one_arg( "@rnd(", e); break;
  2254.     case ROUND:    two_arg( "@round(", e); break;
  2255.     case HOUR:    one_arg( "@hour(", e); break;
  2256.     case MINUTE:    one_arg( "@minute(", e); break;
  2257.     case SECOND:    one_arg( "@second(", e); break;
  2258.     case MONTH:    one_arg( "@month(", e); break;
  2259.     case DAY:    one_arg( "@day(", e); break;
  2260.     case YEAR:    one_arg( "@year(", e); break;
  2261.     case DATE:    one_arg( "@date(", e); break;
  2262.     case UPPER:    one_arg( "@upper(", e); break;
  2263.     case LOWER:    one_arg( "@lower(", e); break;
  2264.     case CAPITAL:    one_arg( "@capital(", e); break;
  2265.     case DTS:    three_arg( "@dts(", e); break;
  2266.     case TTS:    three_arg( "@tts(", e); break;
  2267.     case STON:    one_arg( "@ston(", e); break;
  2268.     case FMT:    two_arg( "@fmt(", e); break;
  2269.     case EQS:    two_arg( "@eqs(", e); break;
  2270.     case NOW:    for ( s = "@now"; line[linelim++] = *s++;);
  2271.             linelim--;
  2272.             break;
  2273.     case LMAX:    list_arg("@max(", e); break;
  2274.     case LMIN:     list_arg("@min(", e); break;
  2275.     case FV:    three_arg("@fv(", e); break;
  2276.     case PV:    three_arg("@pv(", e); break;
  2277.     case PMT:    three_arg("@pmt(", e); break;
  2278.     case NVAL:    two_arg("@nval(", e); break;
  2279.     case SVAL:    two_arg("@sval(", e); break;
  2280.     case EXT:    two_arg("@ext(", e); break;
  2281.     case SUBSTR:    three_arg("@substr(", e); break;
  2282.     case STINDEX:    index_arg("@stindex(", e); break;
  2283.     case INDEX:    index_arg("@index(", e); break;
  2284.     case LOOKUP:    index_arg("@lookup(", e); break;
  2285.     case HLOOKUP:    two_arg_index("@hlookup(", e); break;
  2286.     case VLOOKUP:    two_arg_index("@vlookup(", e); break;
  2287.     case IF:    three_arg("@if(", e); break;
  2288.     case MYROW:    for ( s = "@myrow"; line[linelim++] = *s++;);
  2289.             linelim--;
  2290.             break;
  2291.     case MYCOL:    for ( s = "@mycol"; line[linelim++] = *s++;);
  2292.             linelim--;
  2293.             break;
  2294.     case COLTOA:    one_arg( "@coltoa(", e); break;
  2295.     case NUMITER:    for ( s = "@numiter"; line[linelim++] = *s++;);
  2296.                         linelim--;
  2297.                         break;
  2298.     default:    decompile (e->e.o.left, mypriority);
  2299.             line[linelim++] = e->op;
  2300.             decompile (e->e.o.right, mypriority+1);
  2301.             break;
  2302.     }
  2303.     if (mypriority<priority) line[linelim++] = ')';
  2304.     } else line[linelim++] = '?';
  2305. }
  2306.  
  2307. void
  2308. index_arg(s, e)
  2309. char *s;
  2310. struct enode *e;
  2311. {
  2312.     for (; line[linelim++] = *s++;);
  2313.     linelim--;
  2314.     decompile( e-> e.o.left, 0 );
  2315.     range_arg(", ", e->e.o.right);
  2316. }
  2317.  
  2318. void
  2319. two_arg_index(s, e)
  2320. char *s;
  2321. struct enode *e;
  2322. {
  2323.     for (; line[linelim++] = *s++;);
  2324.     linelim--;
  2325.     decompile( e->e.o.left->e.o.left, 0 );
  2326.     range_arg(",", e->e.o.right);
  2327.     linelim--;
  2328.     line[linelim++] = ',';
  2329.     decompile( e->e.o.left->e.o.right, 0 );
  2330.     line[linelim++] = ')';
  2331. }
  2332.  
  2333. void
  2334. list_arg(s, e)
  2335. char *s;
  2336. struct enode *e;
  2337. {
  2338.     for (; line[linelim++] = *s++;);
  2339.     linelim--;
  2340.  
  2341.     decompile (e->e.o.right, 0);
  2342.     line[linelim++] = ',';
  2343.     decompile_list(e->e.o.left);
  2344.     line[linelim - 1] = ')';
  2345. }
  2346.  
  2347. void
  2348. one_arg(s, e)
  2349. char *s;
  2350. struct enode *e;
  2351. {
  2352.     for (; line[linelim++] = *s++;);
  2353.     linelim--;
  2354.     decompile (e->e.o.right, 0);
  2355.     line[linelim++] = ')';
  2356. }
  2357.  
  2358. void
  2359. two_arg(s,e)
  2360. char *s;
  2361. struct enode *e;
  2362. {
  2363.     for (; line[linelim++] = *s++;);
  2364.     linelim--;
  2365.     decompile (e->e.o.left, 0);
  2366.     line[linelim++] = ',';
  2367.     decompile (e->e.o.right, 0);
  2368.     line[linelim++] = ')';
  2369. }
  2370.  
  2371. void
  2372. three_arg(s,e)
  2373. char *s;
  2374. struct enode *e;
  2375. {
  2376.     for (; line[linelim++] = *s++;);
  2377.     linelim--;
  2378.     decompile (e->e.o.left, 0);
  2379.     line[linelim++] = ',';
  2380.     decompile (e->e.o.right->e.o.left, 0);
  2381.     line[linelim++] = ',';
  2382.     decompile (e->e.o.right->e.o.right, 0);
  2383.     line[linelim++] = ')';
  2384. }
  2385.  
  2386. void
  2387. range_arg(s,e)
  2388. char *s;
  2389. struct enode *e;
  2390. {
  2391.     struct range *r;
  2392.  
  2393.     for (; line[linelim++] = *s++;);
  2394.     linelim--;
  2395.     if ((r = find_range((char *)0, 0, e->e.r.left.vp,
  2396.                  e->e.r.right.vp)) && r->r_is_range) {
  2397.     (void) sprintf(line+linelim, "%s", r->r_name);
  2398.     linelim += strlen(line+linelim);
  2399.     } else {
  2400.     decodev (e->e.r.left);
  2401.     line[linelim++] = ':';
  2402.     decodev (e->e.r.right);
  2403.     }
  2404.     line[linelim++] = ')';
  2405. }
  2406.  
  2407. void
  2408. editfmt (row, col)
  2409. int row, col;
  2410. {
  2411.     register struct ent *p;
  2412.  
  2413.     p = lookat (row, col);
  2414.     if (p->format) {
  2415.         (void) sprintf (line, "fmt %s \"%s\"", v_name(row, col), p->format);
  2416.     linelim = strlen(line);
  2417.     }
  2418. }
  2419.  
  2420. void
  2421. editv (row, col)
  2422. int row, col;
  2423. {
  2424.     register struct ent *p;
  2425.  
  2426.     p = lookat (row, col);
  2427.     (void) sprintf (line, "let %s = ", v_name(row, col));
  2428.     linelim = strlen(line);
  2429.     if (p->flags & is_strexpr || p->expr == 0) {
  2430.     (void) sprintf (line+linelim, "%.15g", p->v);
  2431.     linelim += strlen (line+linelim);
  2432.     } else {
  2433.         editexp(row,col);
  2434.     }
  2435. }
  2436.  
  2437. void
  2438. editexp(row,col)
  2439. int row, col;
  2440. {
  2441.     register struct ent *p;
  2442.  
  2443.     p = lookat (row, col);
  2444.     decompile (p->expr, 0);
  2445.     line[linelim] = '\0';
  2446. }
  2447.  
  2448. void
  2449. edits (row, col)
  2450. int row, col;
  2451. {
  2452.     register struct ent *p;
  2453.  
  2454.     p = lookat (row, col);
  2455.     if( p->flags&is_label )
  2456.     (void) sprintf( line, "label %s = ", v_name(row, col));
  2457.     else
  2458.     (void) sprintf (line, "%sstring %s = ",
  2459.             ((p->flags&is_leftflush) ? "left" : "right"),
  2460.             v_name(row, col));
  2461.     linelim = strlen(line);
  2462.     if (p->flags & is_strexpr && p->expr) {
  2463.     editexp(row, col);
  2464.     } else if (p->label) {
  2465.         (void) sprintf (line+linelim, "\"%s\"", p->label);
  2466.         linelim += strlen (line+linelim);
  2467.     } else {
  2468.         (void) sprintf (line+linelim, "\"");
  2469.         linelim += 1;
  2470.     }
  2471. }
  2472.  
  2473. #ifdef RINT
  2474. /*    round-to-even, also known as ``banker's rounding''.
  2475.     With round-to-even, a number exactly halfway between two values is
  2476.     rounded to whichever is even; e.g. rnd(0.5)=0, rnd(1.5)=2,
  2477.     rnd(2.5)=2, rnd(3.5)=4.  This is the default rounding mode for
  2478.     IEEE floating point, for good reason: it has better numeric
  2479.     properties.  For example, if X+Y is an integer,
  2480.     then X+Y = rnd(X)+rnd(Y) with round-to-even,
  2481.     but not always with sc's rounding (which is
  2482.     round-to-positive-infinity).  I ran into this problem when trying to
  2483.     split interest in an account to two people fairly.
  2484. */
  2485. double rint(d) double d;
  2486. {
  2487.     /* as sent */
  2488.     double fl = floor(d),  fr = d-fl;
  2489.     return
  2490.         fr<0.5  ||  fr==0.5 && fl==floor(fl/2)*2   ?   fl   :   ceil(d);
  2491. }
  2492. #endif
  2493.