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