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