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