home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume13 / sc5.1 / part03 < prev    next >
Encoding:
Internet Message Format  |  1988-01-30  |  62.7 KB

  1. Subject:  v13i018:  SC spreadsheet program, version 5.1, Part03/03
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: nscpdc.nsc.com!rgb
  7. Posting-number: Volume 13, Issue 18
  8. Archive-name: sc5.1/part03
  9.  
  10. # This is a shell archive.  Remove anything before this line
  11. # then unpack it by saving it in a file and typing "sh file"
  12. # (Files unpacked will be owned by you and have default permissions).
  13. # This archive contains the following files:
  14. #    ./interp.c
  15. #    ./cmds.c
  16. #    ./crypt.c
  17. #    ./xmalloc.c
  18. #    ./range.c
  19. #    ./eres.sed
  20. #    ./sres.sed
  21. #    ./Makefile
  22. #    ./cvt.sed
  23. #    ./psc.c
  24. #
  25. if `test ! -s ./interp.c`
  26. then
  27. echo "Extracting ./interp.c"
  28. cat > ./interp.c << '\SHAR\EOF\'
  29. /*    SC    A Spreadsheet Calculator
  30.  *        Expression interpreter and assorted support routines.
  31.  *
  32.  *        original by James Gosling, September 1982
  33.  *        modified by Mark Weiser and Bruce Israel, 
  34.  *            University of Maryland
  35.  *
  36.  *              More mods Robert Bond, 12/86
  37.  */
  38.  
  39. #include <math.h>
  40. #include <signal.h>
  41. #include <setjmp.h>
  42. #include <stdio.h>
  43.  
  44. #ifdef BSD42
  45. #include <strings.h>
  46. #include <sys/time.h>
  47. #else
  48. #include <time.h>
  49. #ifndef SYSIII
  50. #include <string.h>
  51. #endif
  52. #endif
  53.  
  54. #include <curses.h>
  55. #include "sc.h"
  56. #define DEFCOLDELIM ':'
  57.  
  58. extern char curfile[];
  59.  
  60. jmp_buf fpe_save;
  61. int    exprerr;    /* Set by eval() and seval() if expression errors */
  62.  
  63. #ifdef SYSV3
  64. void exit();
  65. #endif
  66. #define PI (double)3.14159265358979323846
  67. #define dtr(x) ((x)*(PI/(double)180.0))
  68. #define rtd(x) ((x)*(180.0/(double)PI))
  69.  
  70. double
  71. dosum(minr, minc, maxr, maxc)
  72. int minr, minc, maxr, maxc;
  73. {
  74.     double v;
  75.     register r,c;
  76.     register struct ent *p;
  77.  
  78.     v = 0;
  79.     for (r = minr; r<=maxr; r++)
  80.     for (c = minc; c<=maxc; c++)
  81.         if ((p = tbl[r][c]) && p->flags&is_valid)
  82.         v += p->v;
  83.     return v;
  84. }
  85.  
  86. double
  87. doprod(minr, minc, maxr, maxc)
  88. int minr, minc, maxr, maxc;
  89. {
  90.     double v;
  91.     register r,c;
  92.     register struct ent *p;
  93.  
  94.     v = 1;
  95.     for (r = minr; r<=maxr; r++)
  96.     for (c = minc; c<=maxc; c++)
  97.         if ((p = tbl[r][c]) && p->flags&is_valid)
  98.         v *= p->v;
  99.     return v;
  100. }
  101.  
  102. double
  103. doavg(minr, minc, maxr, maxc)
  104. int minr, minc, maxr, maxc;
  105. {
  106.     double v;
  107.     register r,c,count;
  108.     register struct ent *p;
  109.  
  110.     v = 0;
  111.     count = 0;
  112.     for (r = minr; r<=maxr; r++)
  113.     for (c = minc; c<=maxc; c++)
  114.         if ((p = tbl[r][c]) && p->flags&is_valid) {
  115.         v += p->v;
  116.         count++;
  117.         }
  118.  
  119.     if (count == 0) 
  120.     return ((double) 0);
  121.  
  122.     return (v / (double)count);
  123. }
  124.  
  125. double
  126. dostddev(minr, minc, maxr, maxc)
  127. int minr, minc, maxr, maxc;
  128. {
  129.     double lp, rp, v, nd;
  130.     register r,c,n;
  131.     register struct ent *p;
  132.  
  133.     n = 0;
  134.     lp = 0;
  135.     rp = 0;
  136.     for (r = minr; r<=maxr; r++)
  137.     for (c = minc; c<=maxc; c++)
  138.         if ((p = tbl[r][c]) && p->flags&is_valid) {
  139.         v = p->v;
  140.         lp += v*v;
  141.         rp += v;
  142.         n++;
  143.         }
  144.  
  145.     if ((n == 0) || (n == 1)) 
  146.     return ((double) 0);
  147.     nd = (double)n;
  148.     return (sqrt((nd*lp-rp*rp)/(nd*(nd-1))));
  149. }
  150.  
  151. double
  152. domax(minr, minc, maxr, maxc)
  153. int minr, minc, maxr, maxc;
  154. {
  155.     double v;
  156.     register r,c,count;
  157.     register struct ent *p;
  158.  
  159.     count = 0;
  160.     for (r = minr; r<=maxr; r++)
  161.     for (c = minc; c<=maxc; c++)
  162.         if ((p = tbl[r][c]) && p->flags&is_valid) {
  163.         if (!count) {
  164.             v = p->v;
  165.             count++;
  166.         } else if (p->v > v)
  167.             v = p->v;
  168.         }
  169.  
  170.     if (count == 0) 
  171.     return ((double) 0);
  172.  
  173.     return (v);
  174. }
  175.  
  176. double
  177. domin(minr, minc, maxr, maxc)
  178. int minr, minc, maxr, maxc;
  179. {
  180.     double v;
  181.     register r,c,count;
  182.     register struct ent *p;
  183.  
  184.     count = 0;
  185.     for (r = minr; r<=maxr; r++)
  186.     for (c = minc; c<=maxc; c++)
  187.         if ((p = tbl[r][c]) && p->flags&is_valid) {
  188.         if (!count) {
  189.             v = p->v;
  190.             count++;
  191.         } else if (p->v < v)
  192.             v = p->v;
  193.         }
  194.  
  195.     if (count == 0) 
  196.     return ((double) 0);
  197.  
  198.     return (v);
  199. }
  200.  
  201. double
  202. dotime(which, when)
  203. int which;
  204. double when;
  205. {
  206.     long time();
  207.  
  208.     static long t_cache;
  209.     static struct tm *tp;
  210.     long tloc;
  211.  
  212.     if (which == NOW) 
  213.         return (double)time((long *)0);
  214.  
  215.     tloc = (long)when;
  216.  
  217.     if (tloc != t_cache) {
  218.         tp = localtime(&tloc);
  219.         tp->tm_mon += 1;
  220.         tp->tm_year += 1900;
  221.         t_cache = tloc;
  222.     }
  223.  
  224.     switch (which) {
  225.         case HOUR: return((double)(tp->tm_hour));
  226.         case MINUTE: return((double)(tp->tm_min));
  227.         case SECOND: return((double)(tp->tm_sec));
  228.         case MONTH: return((double)(tp->tm_mon));
  229.         case DAY: return((double)(tp->tm_mday));
  230.         case YEAR: return((double)(tp->tm_year));
  231.     }
  232.     /* Safety net */
  233.     return (0.0);
  234. }
  235.  
  236. double
  237. doston(s)
  238. char *s;
  239. {
  240.     char *strtof();
  241.     double v;
  242.  
  243.     if (!s)
  244.     return((double)0.0);
  245.  
  246.     (void)strtof(s, &v);
  247.     xfree(s);
  248.     return(v);
  249. }
  250.  
  251. double
  252. doeqs(s1, s2)
  253. char *s1, *s2;
  254. {
  255.     double v;
  256.  
  257.     if (strcmp(s1, s2) == 0)
  258.     v = 1.0;
  259.     else
  260.     v = 0.0;
  261.  
  262.     if (s1)
  263.         xfree(s1);
  264.  
  265.     if (s2)
  266.         xfree(s2);
  267.  
  268.     return(v);
  269. }
  270.  
  271. double 
  272. eval(e)
  273. register struct enode *e;
  274. {
  275.     if (e==0) return 0;
  276.     switch (e->op) {
  277.     case '+':    return (eval(e->e.o.left) + eval(e->e.o.right));
  278.     case '-':    return (eval(e->e.o.left) - eval(e->e.o.right));
  279.     case '*':    return (eval(e->e.o.left) * eval(e->e.o.right));
  280.     case '/':     {    double denom = eval (e->e.o.right);
  281.             return denom ? eval(e->e.o.left) / denom : 0; }
  282.     case '^':    return (pow(eval(e->e.o.left), eval(e->e.o.right)));
  283.     case '<':    return (eval(e->e.o.left) < eval(e->e.o.right));
  284.     case '=':    return (eval(e->e.o.left) == eval(e->e.o.right));
  285.     case '>':    return (eval(e->e.o.left) > eval(e->e.o.right));
  286.     case '&':    return (eval(e->e.o.left) && eval(e->e.o.right));
  287.     case '|':    return (eval(e->e.o.left) || eval(e->e.o.right));
  288.     case '?':    return eval(e->e.o.left) ? eval(e->e.o.right->e.o.left)
  289.                         : eval(e->e.o.right->e.o.right);
  290.     case 'm':    return (-eval(e->e.o.right));
  291.     case 'f':    return (eval(e->e.o.right));
  292.     case '~':    return (eval(e->e.o.right) == 0.0);
  293.     case 'k':    return (e->e.k);
  294.     case 'v':    return (e->e.v.vp->v);
  295.     case O_REDUCE('+'):
  296.      case O_REDUCE('*'):
  297.      case O_REDUCE('a'):
  298.      case O_REDUCE('s'):
  299.     case O_REDUCE(MAX):
  300.     case O_REDUCE(MIN):
  301.         {    register r,c;
  302.         register maxr, maxc;
  303.         register minr, minc;
  304.         maxr = e->e.r.right.vp -> row;
  305.         maxc = e->e.r.right.vp -> col;
  306.         minr = e->e.r.left.vp -> row;
  307.         minc = e->e.r.left.vp -> col;
  308.         if (minr>maxr) r = maxr, maxr = minr, minr = r;
  309.         if (minc>maxc) c = maxc, maxc = minc, minc = c;
  310.             switch (e->op) {
  311.                 case O_REDUCE('+'): return dosum(minr, minc, maxr, maxc);
  312.                  case O_REDUCE('*'): return doprod(minr, minc, maxr, maxc);
  313.                  case O_REDUCE('a'): return doavg(minr, minc, maxr, maxc);
  314.                  case O_REDUCE('s'): return dostddev(minr, minc, maxr, maxc);
  315.                  case O_REDUCE(MAX): return domax(minr, minc, maxr, maxc);
  316.                  case O_REDUCE(MIN): return domin(minr, minc, maxr, maxc);
  317.         }
  318.         }
  319.     case ACOS:     return (acos(eval(e->e.o.right)));
  320.     case ASIN:     return (asin(eval(e->e.o.right)));
  321.     case ATAN:     return (atan(eval(e->e.o.right)));
  322.     case CEIL:     return (ceil(eval(e->e.o.right)));
  323.     case COS:     return (cos(eval(e->e.o.right)));
  324.     case EXP:     return (exp(eval(e->e.o.right)));
  325.     case FABS:     return (fabs(eval(e->e.o.right)));
  326.     case FLOOR:     return (floor(eval(e->e.o.right)));
  327.     case HYPOT:     return (hypot(eval(e->e.o.left), eval(e->e.o.right)));
  328.     case LOG:     { double arg = eval(e->e.o.right);
  329.                return arg ? log(arg) : 0; }
  330.     case LOG10:     { double arg = eval(e->e.o.right);
  331.                return arg ? log10(arg) : 0; }
  332.     case POW:     return (pow(eval(e->e.o.left), eval(e->e.o.right)));
  333.     case SIN:     return (sin(eval(e->e.o.right)));
  334.     case SQRT:     return (sqrt(eval(e->e.o.right)));
  335.     case TAN:     return (tan(eval(e->e.o.right)));
  336.     case DTR:     return (dtr(eval(e->e.o.right)));
  337.     case RTD:     return (rtd(eval(e->e.o.right)));
  338.     case RND:     {
  339.                 double temp;
  340.                 temp = eval(e->e.o.right);
  341.                 return(temp-floor(temp) < 0.5 ?
  342.                          floor(temp) : ceil(temp));
  343.              }
  344.     case HOUR:     return (dotime(HOUR, eval(e->e.o.right)));
  345.     case MINUTE:     return (dotime(MINUTE, eval(e->e.o.right)));
  346.     case SECOND:     return (dotime(SECOND, eval(e->e.o.right)));
  347.     case MONTH:     return (dotime(MONTH, eval(e->e.o.right)));
  348.     case DAY:     return (dotime(DAY, eval(e->e.o.right)));
  349.     case YEAR:     return (dotime(YEAR, eval(e->e.o.right)));
  350.     case NOW:     return (dotime(NOW, (double)0.0));
  351.     case STON:     return (doston(seval(e->e.o.right)));
  352.     case EQS:        return (doeqs(seval(e->e.o.right),seval(e->e.o.left)));
  353.     default:     error("Illegal Numeric Expression");
  354.              exprerr = 1;
  355.              return((double)0.0);
  356.     }
  357. }
  358.  
  359. /* 
  360.  * Rules for string functions:
  361.  * Take string arguments which they xfree.
  362.  * All returned strings are assumed to be xalloced.
  363.  */
  364.  
  365. char *
  366. docat(s1, s2)
  367. register char *s1, *s2;
  368. {
  369.     register char *p;
  370.  
  371.     p = xmalloc((unsigned)(strlen(s1)+strlen(s2)+1));
  372.     (void) strcpy(p, s1);
  373.     (void) strcat(p, s2);
  374.     if (s1)
  375.         xfree(s1);
  376.     if (s2)
  377.         xfree(s2);
  378.     return(p);
  379. }
  380.  
  381. char *
  382. dodate(tloc)
  383. long tloc;
  384. {
  385.     char *tp;
  386.     char *p;
  387.  
  388.     tp = ctime(&tloc);
  389.     tp[24] = 0;
  390.     p = xmalloc((unsigned)25);
  391.     (void) strcpy(p, tp);
  392.     return(p);
  393. }
  394.  
  395. char *
  396. dofmt(fmtstr, v)
  397. char *fmtstr;
  398. double v;
  399. {
  400.     char buff[1024];
  401.     char *p;
  402.  
  403.     if (!fmtstr)
  404.     return(0);
  405.     (void)sprintf(buff, fmtstr, v);
  406.     p = xmalloc((unsigned)(strlen(buff)+1));
  407.     (void) strcpy(p, buff);
  408.     xfree(fmtstr);
  409.     return(p);
  410. }
  411.  
  412. char *
  413. dosubstr(s, v1, v2)
  414. char *s;
  415. register int v1,v2;
  416. {
  417.     register char *s1, *s2;
  418.     char *p;
  419.  
  420.     if (!s)
  421.     return(0);
  422.  
  423.     if (v1 < 0 || v2 < v1 || strlen(s) <= v2 ) {
  424.     xfree(s);
  425.     p = xmalloc((unsigned)1);
  426.     p[0] = 0;
  427.     return(p);
  428.     }
  429.     s2 = p = xmalloc((unsigned)(v2-v1+2));
  430.     s1 = &s[v1];
  431.     for(; v1 <= v2; s1++, s2++, v1++)
  432.     *s2 = *s1;
  433.     *s2 = 0;
  434.     xfree(s);
  435.     return(p);
  436. }
  437.  
  438. char *
  439. seval(se)
  440. register struct enode *se;
  441. {
  442.     register char *p;
  443.  
  444.     if (se==0) return 0;
  445.     switch (se->op) {
  446.     case O_SCONST: p = xmalloc((unsigned)(strlen(se->e.s)+1));
  447.              (void) strcpy(p, se->e.s);
  448.              return(p);
  449.     case O_VAR:    {
  450.             struct ent *ep;
  451.  
  452.             ep = se->e.v.vp;
  453.             p = xmalloc((unsigned)(strlen(ep->label)+1));
  454.             (void) strcpy(p, ep->label);
  455.             return(p);
  456.              }
  457.     case '#':    return(docat(seval(se->e.o.left), seval(se->e.o.right)));
  458.     case 'f':    return(seval(se->e.o.right));
  459.     case '?':    return(eval(se->e.o.left) ? seval(se->e.o.right->e.o.left)
  460.                          : seval(se->e.o.right->e.o.right));
  461.     case DATE:   return(dodate((long)(eval(se->e.o.right))));
  462.     case FMT:    return(dofmt(seval(se->e.o.left), eval(se->e.o.right)));
  463.     case SUBSTR: return(dosubstr(seval(se->e.o.left),
  464.                 (int)eval(se->e.o.right->e.o.left) - 1,
  465.                 (int)eval(se->e.o.right->e.o.right) - 1));
  466.     default:
  467.              error("Illegal String Expression");
  468.              exprerr = 1;
  469.              return(0);
  470.     }
  471. }
  472.  
  473. #define MAXPROP 7
  474.  
  475. EvalAll () {
  476.     int repct = 0;
  477.  
  478.     while (RealEvalAll() && (repct++ <= MAXPROP));
  479. }
  480.  
  481.  
  482. #ifdef SYSV3
  483. void
  484. #endif
  485. eval_fpe() /* Trap for FPE errors in eval */
  486. {
  487.     longjmp(fpe_save, 1);
  488. }
  489.  
  490. int 
  491. RealEvalAll () {
  492.     register i,j;
  493.     int chgct = 0;
  494.     register struct ent *p;
  495. #ifdef SYSV3
  496.     void quit();
  497. #else
  498.     int quit();
  499. #endif
  500.  
  501.     (void) signal(SIGFPE, eval_fpe);
  502.     for (i=0; i<=maxrow; i++)
  503.     for (j=0; j<=maxcol; j++)
  504.         if ((p=tbl[i][j]) && p->expr) {
  505.         if (p->flags & is_strexpr) {
  506.             char *v;
  507.             if (setjmp(fpe_save)) {
  508.             error("Floating point exception %s", v_name(i,j));
  509.             v = "";
  510.             } else {
  511.                 v = seval(p->expr);
  512.             }
  513.             if (strcmp(v, p->label) != 0) {
  514.             chgct++;
  515.                 p->flags |= is_changed;
  516.             }
  517.             if(p->label)
  518.             xfree(p->label);
  519.             p->label = v;
  520.         } else {
  521.             double v;
  522.             if (setjmp(fpe_save)) {
  523.             error("Floating point exception %s", v_name(i,j));
  524.             v = 0.0;
  525.             } else {
  526.                 v = eval (p->expr);
  527.             }
  528.             if (v != p->v) {
  529.             p->v = v; chgct++;
  530.             p->flags |= (is_changed|is_valid);
  531.             }
  532.         }
  533.         }
  534.     (void) signal(SIGFPE, quit);
  535.     return(chgct);
  536. }
  537.  
  538. struct enode *
  539. new(op, a1, a2)
  540. struct enode *a1, *a2;
  541. {
  542.     register struct enode *p;
  543.     p = (struct enode *) xmalloc ((unsigned)sizeof (struct enode));
  544.     p->op = op;
  545.     p->e.o.left = a1;
  546.     p->e.o.right = a2;
  547.     return p;
  548. }
  549.  
  550. struct enode *
  551. new_var(op, a1)
  552. struct ent_ptr a1;
  553. {
  554.     register struct enode *p;
  555.     p = (struct enode *) xmalloc ((unsigned)sizeof (struct enode));
  556.     p->op = op;
  557.     p->e.v = a1;
  558.     return p;
  559. }
  560.  
  561. struct enode *
  562. new_range(op, a1)
  563. struct range_s a1;
  564. {
  565.     register struct enode *p;
  566.     p = (struct enode *) xmalloc ((unsigned)sizeof (struct enode));
  567.     p->op = op;
  568.     p->e.r = a1;
  569.     return p;
  570. }
  571.  
  572. struct enode *
  573. new_const(op, a1)
  574. double a1;
  575. {
  576.     register struct enode *p;
  577.     p = (struct enode *) xmalloc ((unsigned)sizeof (struct enode));
  578.     p->op = op;
  579.     p->e.k = a1;
  580.     return p;
  581. }
  582.  
  583. struct enode *
  584. new_str(s)
  585. char *s;
  586. {
  587.     register struct enode *p;
  588.  
  589.     p = (struct enode *) xmalloc ((unsigned)sizeof(struct enode));
  590.     p->op = O_SCONST;
  591.     p->e.s = s;
  592.     return(p);
  593. }
  594.  
  595. copy(dv1, dv2, v1, v2)
  596. struct ent *dv1, *dv2, *v1, *v2;
  597. {
  598.     int minsr, minsc;
  599.     int maxsr, maxsc;
  600.     int mindr, mindc;
  601.     int maxdr, maxdc;
  602.     int vr, vc;
  603.     int r, c;
  604.  
  605.     mindr = dv1->row;
  606.     mindc = dv1->col;
  607.     maxdr = dv2->row;
  608.     maxdc = dv2->col;
  609.     if (mindr>maxdr) r = maxdr, maxdr = mindr, mindr = r;
  610.     if (mindc>maxdc) c = maxdc, maxdc = mindc, mindc = c;
  611.     maxsr = v2->row;
  612.     maxsc = v2->col;
  613.     minsr = v1->row;
  614.     minsc = v1->col;
  615.     if (minsr>maxsr) r = maxsr, maxsr = minsr, minsr = r;
  616.     if (minsc>maxsc) c = maxsc, maxsc = minsc, minsc = c;
  617.     if (maxdr >= MAXROWS  || 
  618.            maxdc >= MAXCOLS) {
  619.     error ("The table can't be any bigger");
  620.     return;
  621.     }
  622.     erase_area(mindr, mindc, maxdr, maxdc);
  623.     if (minsr == maxsr && minsc == maxsc) {
  624.     /* Source is a single cell */
  625.     for(vr = mindr; vr <= maxdr; vr++)
  626.         for (vc = mindc; vc <= maxdc; vc++)
  627.         copyrtv(vr, vc, minsr, minsc, maxsr, maxsc);
  628.     } else if (minsr == maxsr) {
  629.     /* Source is a single row */
  630.     for (vr = mindr; vr <= maxdr; vr++)
  631.         copyrtv(vr, mindc, minsr, minsc, maxsr, maxsc);
  632.     } else if (minsc == maxsc) {
  633.     /* Source is a single column */
  634.     for (vc = mindc; vc <= maxdc; vc++)
  635.         copyrtv(mindr, vc, minsr, minsc, maxsr, maxsc);
  636.     } else {
  637.     /* Everything else */
  638.     copyrtv(mindr, mindc, minsr, minsc, maxsr, maxsc);
  639.     }
  640.     sync_refs();
  641. }
  642.  
  643. copyrtv(vr, vc, minsr, minsc, maxsr, maxsc)
  644. int vr, vc, minsr, minsc, maxsr, maxsc;
  645. {
  646.     register struct ent *p;
  647.     register struct ent *n;
  648.     register int sr, sc;
  649.     register int dr, dc;
  650.  
  651.     for (dr=vr, sr=minsr; sr<=maxsr; sr++, dr++)
  652.     for (dc=vc, sc=minsc; sc<=maxsc; sc++, dc++) {
  653.         n = lookat (dr, dc);
  654.         (void) clearent(n);
  655.         if (p = tbl[sr][sc]) {
  656.         n -> v = p -> v;
  657.         n -> flags = p -> flags;
  658.         n -> expr = copye(p->expr, dr - sr, dc - sc);
  659.         n -> label = 0;
  660.         if (p -> label) {
  661.             n -> label = xmalloc ((unsigned)(strlen (p -> label) + 1));
  662.             (void) strcpy (n -> label, p -> label);
  663.         }
  664.         }
  665.     }
  666. }
  667.  
  668. eraser(v1, v2)
  669. struct ent *v1, *v2;
  670. {
  671.     FullUpdate++;
  672.     flush_saved();
  673.     erase_area(v1->row, v1->col, v2->row, v2->col);
  674.     sync_refs();
  675. }
  676.  
  677. moveto(v)
  678. struct ent *v;
  679. {
  680.     currow = v->row;
  681.     curcol = v->col;
  682. }
  683.  
  684. fill (v1, v2, start, inc)
  685. struct ent *v1, *v2;
  686. double start, inc;
  687. {
  688.     register r,c;
  689.     register struct ent *n;
  690.     int maxr, maxc;
  691.     int minr, minc;
  692.  
  693.     maxr = v2->row;
  694.     maxc = v2->col;
  695.     minr = v1->row;
  696.     minc = v1->col;
  697.     if (minr>maxr) r = maxr, maxr = minr, minr = r;
  698.     if (minc>maxc) c = maxc, maxc = minc, minc = c;
  699.     if (maxr >= MAXROWS) maxr = MAXROWS-1;
  700.     if (maxc >= MAXCOLS) maxc = MAXCOLS-1;
  701.     if (minr < 0) minr = 0;
  702.     if (minr < 0) minr = 0;
  703.  
  704.     FullUpdate++;
  705.     for (r = minr; r<=maxr; r++)
  706.     for (c = minc; c<=maxc; c++) {
  707.         n = lookat (r, c);
  708.         (void) clearent(n);
  709.         n->v = start;
  710.         start += inc;
  711.         n->flags |= (is_changed|is_valid);
  712.     }
  713. }
  714.  
  715. let (v, e)
  716. struct ent *v;
  717. struct enode *e;
  718. {
  719.     double val;
  720.  
  721.     exprerr = 0;
  722.     (void) signal(SIGFPE, eval_fpe);
  723.     if (setjmp(fpe_save)) {
  724.     error("Floating point exception %s", v_name(v->row, v->col));
  725.     val = 0.0;
  726.     } else {
  727.     val = eval(e);
  728.     }
  729.     (void) signal(SIGFPE, quit);
  730.     if (exprerr) {
  731.     efree(e);
  732.     return;
  733.     }
  734.     if (constant(e)) {
  735.     v->v = val;
  736.     if (!(v->flags & is_strexpr)) {
  737.             efree (v->expr);
  738.         v->expr = 0;
  739.     }
  740.     efree(e);
  741.         v->flags |= (is_changed|is_valid);
  742.         changed++;
  743.         modflg++;
  744.     return;
  745.     }
  746.     efree (v->expr);
  747.     v->expr = e;
  748.     v->flags |= (is_changed|is_valid);
  749.     v->flags &= ~is_strexpr;
  750.     changed++;
  751.     modflg++;
  752. }
  753.  
  754. slet (v, se, flushdir)
  755. struct ent *v;
  756. struct enode *se;
  757. int flushdir;
  758. {
  759.     char *p;
  760.  
  761.     exprerr = 0;
  762.     (void) signal(SIGFPE, eval_fpe);
  763.     if (setjmp(fpe_save)) {
  764.     error("Floating point exception %s", v_name(v->row, v->col));
  765.     p = "";
  766.     } else {
  767.     p = seval(se);
  768.     }
  769.     (void) signal(SIGFPE, quit);
  770.     if (exprerr) {
  771.     efree(se);
  772.     return;
  773.     }
  774.     if (constant(se)) {
  775.     label(v, p, flushdir);
  776.     if (p)
  777.         xfree(p);
  778.     efree(se);
  779.     if (v->flags & is_strexpr) {
  780.             efree (v->expr);
  781.         v->expr = 0;
  782.         v->flags &= ~is_strexpr;
  783.     }
  784.     return;
  785.     }
  786.     efree (v->expr);
  787.     v->expr = se;
  788.     v->flags |= (is_changed|is_strexpr);
  789.     if (flushdir<0) v->flags |= is_leftflush;
  790.     else v->flags &= ~is_leftflush;
  791.     FullUpdate++;
  792.     changed++;
  793.     modflg++;
  794. }
  795.  
  796. clearent (v)
  797. struct ent *v; {
  798.     if (!v)
  799.     return;
  800.     label(v,"",-1);
  801.     v->v = 0;
  802.     if (v->expr)
  803.     efree(v->expr);
  804.     v->expr = 0;
  805.     v->flags |= (is_changed);
  806.     v->flags &= ~(is_valid);
  807.     changed++;
  808.     modflg++;
  809. }
  810.  
  811. constant(e)
  812. register struct enode *e; {
  813.     return e==0 || e->op == O_CONST || e->op == O_SCONST
  814.     || (e->op != O_VAR
  815.      && (e->op&~0177) != O_REDUCE(0)
  816.      && constant (e->e.o.left)
  817.      && constant(e->e.o.right)
  818.      && e->op != NOW);
  819. }
  820.  
  821. efree (e)
  822. register struct enode *e; {
  823.     if (e) {
  824.     if (e->op != O_VAR && e->op !=O_CONST && e->op != O_SCONST
  825.         && (e->op&~0177) != O_REDUCE(0)) {
  826.         efree(e->e.o.left);
  827.         efree(e->e.o.right);
  828.     }
  829.     if (e->op == O_SCONST && e->e.s)
  830.         xfree(e->e.s);
  831.     xfree ((char *)e);
  832.     }
  833. }
  834.  
  835. label (v, s, flushdir)
  836. register struct ent *v;
  837. register char *s; {
  838.     if (v) {
  839.     if (flushdir==0 && v->flags&is_valid) {
  840.         register struct ent *tv;
  841.         if (v->col>0 && ((tv=lookat(v->row,v->col-1))->flags&is_valid)==0)
  842.         v = tv, flushdir = 1;
  843.         else if (((tv=lookat (v->row,v->col+1))->flags&is_valid)==0)
  844.         v = tv, flushdir = -1;
  845.         else flushdir = -1;
  846.     }
  847.     if (v->label) xfree((char *)(v->label));
  848.     if (s && s[0]) {
  849.         v->label = xmalloc ((unsigned)(strlen(s)+1));
  850.         (void) strcpy (v->label, s);
  851.     } else
  852.         v->label = 0;
  853.     if (flushdir<0) v->flags |= is_leftflush;
  854.     else v->flags &= ~is_leftflush;
  855.     FullUpdate++;
  856.     modflg++;
  857.     }
  858. }
  859.  
  860. decodev (v)
  861. struct ent_ptr v; 
  862. {
  863.     register struct range *r;
  864.  
  865.     if (!v.vp) (void)sprintf (line+linelim,"VAR?");
  866.     else if (r = find_range((char *)0, 0, v.vp, v.vp))
  867.         (void)sprintf(line+linelim, "%s", r->r_name);
  868.     else
  869.         (void)sprintf (line+linelim, "%s%s%s%d",
  870.             v.vf & FIX_COL ? "$" : "",
  871.             coltoa(v.vp->col),
  872.             v.vf & FIX_ROW ? "$" : "",
  873.             v.vp->row);
  874.     linelim += strlen (line+linelim);
  875. }
  876.  
  877. char *
  878. coltoa(col)
  879. int col;
  880. {
  881.     static char rname[3];
  882.     register char *p = rname;
  883.  
  884.     if (col > 25) {
  885.     *p++ = col/26 + 'A' - 1;
  886.     col %= 26;
  887.     }
  888.     *p++ = col+'A';
  889.     *p = 0;
  890.     return(rname);
  891. }
  892.  
  893. decompile(e, priority)
  894. register struct enode *e; {
  895.     register char *s;
  896.     if (e) {
  897.     int mypriority;
  898.     switch (e->op) {
  899.     default: mypriority = 99; break;
  900.     case '?': mypriority = 1; break;
  901.     case ':': mypriority = 2; break;
  902.     case '|': mypriority = 3; break;
  903.     case '&': mypriority = 4; break;
  904.     case '<': case '=': case '>': mypriority = 6; break;
  905.     case '+': case '-': case '#': mypriority = 8; break;
  906.     case '*': case '/': mypriority = 10; break;
  907.     case '^': mypriority = 12; break;
  908.     }
  909.     if (mypriority<priority) line[linelim++] = '(';
  910.     switch (e->op) {
  911.     case 'f':    { 
  912.                 for (s="fixed "; line[linelim++] = *s++;);
  913.                 linelim--;
  914.                 decompile (e->e.o.right, 30);
  915.                 break;
  916.             }
  917.     case 'm':    line[linelim++] = '-';
  918.             decompile (e->e.o.right, 30);
  919.             break;
  920.     case '~':    line[linelim++] = '~';
  921.             decompile (e->e.o.right, 30);
  922.             break;
  923.     case 'v':    decodev (e->e.v);
  924.             break;
  925.     case 'k':    (void)sprintf (line+linelim,"%.15g",e->e.k);
  926.             linelim += strlen (line+linelim);
  927.             break;
  928.     case '$':    (void)sprintf (line+linelim, "\"%s\"", e->e.s);
  929.             linelim += strlen(line+linelim);
  930.             break;
  931.     case O_REDUCE('+'):
  932.             s = "@sum("; goto more;
  933.     case O_REDUCE('*'):
  934.             s = "@prod("; goto more;
  935.     case O_REDUCE('s'):
  936.             s = "@stddev("; goto more;
  937.     case O_REDUCE(MAX):
  938.             s = "@max("; goto more;
  939.     case O_REDUCE(MIN):
  940.             s = "@min("; goto more;
  941.     case O_REDUCE('a'):
  942.             s = "@avg("; /* fall though to more; */
  943.     more:        {
  944.             struct range *r;
  945.  
  946.             for (; line[linelim++] = *s++;);
  947.             linelim--;
  948.             if (r = find_range((char *)0, 0, e->e.r.left.vp,
  949.                          e->e.r.right.vp)) {
  950.                 (void)sprintf(line+linelim, "%s", r->r_name);
  951.                 linelim += strlen(line+linelim);
  952.             } else {
  953.                 decodev (e->e.r.left);
  954.                 line[linelim++] = ':';
  955.                 decodev (e->e.r.right);
  956.             }
  957.             line[linelim++] = ')';
  958.             break;
  959.             }
  960.     case ACOS:    s = "@acos("; goto more1;
  961.     case ASIN:    s = "@asin("; goto more1;
  962.     case ATAN:    s = "@atan("; goto more1;
  963.     case CEIL:    s = "@ceil("; goto more1;
  964.     case COS:    s = "@cos("; goto more1;
  965.     case EXP:    s = "@exp("; goto more1;
  966.     case FABS:    s = "@fabs("; goto more1;
  967.     case FLOOR:    s = "@floor("; goto more1;
  968.     case HYPOT:    s = "@hypot("; goto more2;
  969.     case LOG:    s = "@ln("; goto more1;
  970.     case LOG10:    s = "@log("; goto more1;
  971.     case POW:    s = "@pow("; goto more2;
  972.     case SIN:    s = "@sin("; goto more1;
  973.     case SQRT:    s = "@sqrt("; goto more1;
  974.     case TAN:    s = "@tan("; goto more1;
  975.     case DTR:    s = "@dtr("; goto more1;
  976.     case RTD:    s = "@rtd("; goto more1;
  977.     case RND:    s = "@rnd("; goto more1;
  978.     case HOUR:    s = "@hour("; goto more1;
  979.     case MINUTE:    s = "@minute("; goto more1;
  980.     case SECOND:    s = "@second("; goto more1;
  981.     case MONTH:    s = "@month("; goto more1;
  982.     case DAY:    s = "@day("; goto more1;
  983.     case YEAR:    s = "@year("; goto more1;
  984.     case DATE:    s = "@date("; goto more1;
  985.     case STON:    s = "@ston("; goto more1;
  986.     case FMT:    s = "@fmt("; goto more2;
  987.     case EQS:    s = "@eqs("; goto more2;
  988.     more1:        for (; line[linelim++] = *s++;);
  989.             linelim--;
  990.             decompile (e->e.o.right, 0);
  991.             line[linelim++] = ')';
  992.             break;
  993.     more2:        for (; line[linelim++] = *s++;);
  994.             linelim--;
  995.             decompile (e->e.o.left, 0);
  996.             line[linelim++] = ',';
  997.             decompile (e->e.o.right, 0);
  998.             line[linelim++] = ')';
  999.             break;
  1000.     case NOW:    s = "@now"; goto more0;
  1001.     more0:        for (; line[linelim++] = *s++;);
  1002.             linelim--;
  1003.             break;
  1004.     case SUBSTR:    s = "@substr(";
  1005.             for (; line[linelim++] = *s++;);
  1006.             linelim--;
  1007.             decompile (e->e.o.left, 0);
  1008.             line[linelim++] = ',';
  1009.             decompile (e->e.o.right->e.o.left, 0);
  1010.             line[linelim++] = ',';
  1011.             decompile (e->e.o.right->e.o.right, 0);
  1012.             line[linelim++] = ')';
  1013.             break;
  1014.  
  1015.     default:    decompile (e->e.o.left, mypriority);
  1016.             line[linelim++] = e->op;
  1017.             decompile (e->e.o.right, mypriority+1);
  1018.             break;
  1019.     }
  1020.     if (mypriority<priority) line[linelim++] = ')';
  1021.     } else line[linelim++] = '?';
  1022. }
  1023.  
  1024. editv (row, col) {
  1025.     register struct ent *p;
  1026.  
  1027.     p = lookat (row, col);
  1028.     (void)sprintf (line, "let %s = ", v_name(row, col));
  1029.     linelim = strlen(line);
  1030.     if (p->flags & is_strexpr || p->expr == 0) {
  1031.     (void)sprintf (line+linelim, "%.15g", p->v);
  1032.     linelim += strlen (line+linelim);
  1033.     } else {
  1034.         editexp(row,col);
  1035.     }
  1036. }
  1037.  
  1038. editexp(row,col) {
  1039.     register struct ent *p;
  1040.  
  1041.     p = lookat (row, col);
  1042.     decompile (p->expr, 0);
  1043.     line[linelim] = 0;
  1044. }
  1045.  
  1046. edits (row, col) {
  1047.     register struct ent *p;
  1048.  
  1049.     p = lookat (row, col);
  1050.     (void)sprintf (line, "%sstring %s = ",
  1051.             ((p->flags&is_leftflush) ? "left" : "right"),
  1052.             v_name(row, col));
  1053.     linelim = strlen(line);
  1054.     if (p->flags & is_strexpr && p->expr) {
  1055.     editexp(row, col);
  1056.     } else {
  1057.         (void)sprintf (line+linelim, "\"%s\"", p->label);
  1058.         linelim += strlen (line+linelim);
  1059.     }
  1060. }
  1061.  
  1062. printfile (fname, r0, c0, rn, cn)
  1063. char *fname;
  1064. {
  1065.     FILE *f;
  1066.     char pline[1000];
  1067.     int plinelim;
  1068.     int pid;
  1069.     int fieldlen, nextcol;
  1070.     register row, col;
  1071.     register struct ent **p;
  1072.     char ch, lin[100];
  1073.  
  1074.     if (strcmp(fname, curfile) == 0) {
  1075.     (void) move (0, 0);
  1076.     (void) clrtoeol ();
  1077.     (void) sprintf (lin,
  1078.         "Confirm that you want to destroy the data base: (y,n)");
  1079.     (void) addstr (lin);
  1080.     (void) refresh();
  1081.     ch = nmgetch();
  1082.     if (ch != 'y' && ch != 'Y') 
  1083.         return;
  1084.     }
  1085.  
  1086.     f = openout(fname, &pid);
  1087.  
  1088.     if (f==0) {
  1089.     error ("Can't create %s", fname);
  1090.     return;
  1091.     }
  1092.     for (row=r0;row<=rn; row++) {
  1093.     register c = 0;
  1094.     pline[plinelim=0] = '\0';
  1095.     for (p = &tbl[row][col=c0]; col<=cn;
  1096.             p += nextcol-col, col = nextcol, c += fieldlen) {
  1097.  
  1098.         fieldlen = fwidth[col];
  1099.         nextcol = col+1;
  1100.         if (*p) {
  1101.         char *s;
  1102.  
  1103.         while (plinelim<c) pline[plinelim++] = ' ';
  1104.         plinelim = c;
  1105.         if ((*p)->flags&is_valid) {
  1106.             (void)sprintf (pline+plinelim,"%*.*f",fwidth[col],
  1107.                                         precision[col], (*p)->v);
  1108.             plinelim += strlen (pline+plinelim);
  1109.         }
  1110.         if (s = (*p)->label) {
  1111.             int slen;
  1112.             char *start, *last;
  1113.             register char *fp;
  1114.             struct ent *nc;
  1115.  
  1116.             /* Figure out if the label slops over to a blank field */
  1117.             slen = strlen(s);
  1118.             while (slen > fieldlen && nextcol <= cn &&
  1119.                 !((nc = lookat(row,nextcol))->flags & is_valid) &&
  1120.                 !(nc->label)) {
  1121.             
  1122.             fieldlen += fwidth[nextcol];
  1123.             nextcol++;
  1124.             }
  1125.             if (slen > fieldlen)
  1126.             slen = fieldlen;
  1127.             
  1128.             /* Now justify and print */
  1129.             start = (*p)->flags & is_leftflush ? pline + c
  1130.                     : pline + c + fieldlen - slen;
  1131.             last = pline + c + fieldlen;
  1132.             fp = plinelim < c ? pline + plinelim : pline + c;
  1133.             while (fp < start)
  1134.             *fp++ = ' ';
  1135.             while (slen--)
  1136.             *fp++ = *s++;
  1137.             if (!((*p)->flags & is_valid) || fieldlen != fwidth[col])
  1138.             while(fp < last)
  1139.                 *fp++ = ' ';
  1140.             if (plinelim < fp - pline)
  1141.             plinelim = fp - pline;
  1142.         }
  1143.         }
  1144.     }
  1145.     (void) fprintf (f,"%.*s\n",plinelim,pline);
  1146.     }
  1147.  
  1148.     closeout(f, pid);
  1149. }
  1150.  
  1151. tblprintfile (fname, r0, c0, rn, cn)
  1152. char *fname;
  1153. {
  1154.     FILE *f;
  1155.     char pline[1000];
  1156.     int pid;
  1157.     register row, col;
  1158.     register struct ent **p;
  1159.     char coldelim = DEFCOLDELIM;
  1160.     char ch, lin[100];
  1161.  
  1162.     if (strcmp(fname, curfile) == 0) {
  1163.     (void) move (0, 0);
  1164.     (void) clrtoeol ();
  1165.     (void) sprintf (lin,
  1166.         "Confirm that you want to destroy the data base: (y,n)");
  1167.     (void) addstr (lin);
  1168.     (void) refresh();
  1169.     ch = nmgetch();
  1170.     if (ch != 'y' && ch != 'Y') 
  1171.         return;
  1172.     }
  1173.  
  1174.     f = openout(fname, &pid);
  1175.  
  1176.     if (f==0) {
  1177.     error ("Can't create %s", fname);
  1178.     return;
  1179.     }
  1180.     for (row=r0; row<=rn; row++) {
  1181.     for (p = &tbl[row][col=c0]; col<=cn; col++, p++) {
  1182.         if (*p) {
  1183.         char *s;
  1184.         if ((*p)->flags&is_valid) {
  1185.             (void) fprintf (f,"%.*f",precision[col],
  1186.                 (*p)->v);
  1187.         }
  1188.         if (s = (*p)->label) {
  1189.                 (void) fprintf (f,"%s",s);
  1190.         }
  1191.         }
  1192.         (void) fprintf(f,"%c",coldelim);
  1193.     }
  1194.     (void) fprintf (f,"\n",pline);
  1195.     }
  1196.  
  1197.     closeout(f, pid);
  1198. }
  1199.  
  1200. struct enode *
  1201. copye (e, Rdelta, Cdelta)
  1202. register struct enode *e; {
  1203.     register struct enode *ret;
  1204.     if (e==0) ret = 0;
  1205.     else {
  1206.     ret = (struct enode *) xmalloc ((unsigned) sizeof (struct enode));
  1207.     ret->op = e->op;
  1208.     switch (ret->op) {
  1209.     case 'v':
  1210.         {
  1211.             int newrow, newcol;
  1212.             newrow=e->e.v.vf & FIX_ROW ? e->e.v.vp->row :
  1213.                          e->e.v.vp->row+Rdelta;
  1214.             newcol=e->e.v.vf & FIX_COL ? e->e.v.vp->col :
  1215.                          e->e.v.vp->col+Cdelta;
  1216.             ret->e.v.vp = lookat (newrow, newcol);
  1217.             ret->e.v.vf = e->e.v.vf;
  1218.             break;
  1219.         }
  1220.     case 'k':
  1221.         ret->e.k = e->e.k;
  1222.         break;
  1223.     case 'f':
  1224.         ret->e.o.right = copye (e->e.o.right,0,0);
  1225.         ret->e.o.left = 0;
  1226.          break;
  1227.     case '$':
  1228.         ret->e.s = xmalloc((unsigned) strlen(e->e.s)+1);
  1229.         (void) strcpy(ret->e.s, e->e.s);
  1230.         break;
  1231.      case O_REDUCE('+'):
  1232.      case O_REDUCE('*'):
  1233.      case O_REDUCE('a'):
  1234.      case O_REDUCE('s'):
  1235.      case O_REDUCE(MAX):
  1236.      case O_REDUCE(MIN):
  1237.         {
  1238.             int newrow, newcol;
  1239.             newrow=e->e.r.left.vf & FIX_ROW ?e->e.r.left.vp->row :
  1240.                              e->e.r.left.vp->row+Rdelta;
  1241.             newcol=e->e.r.left.vf & FIX_COL ?e->e.r.left.vp->col :
  1242.                              e->e.r.left.vp->col+Cdelta;
  1243.             ret->e.r.left.vp = lookat (newrow, newcol);
  1244.             ret->e.r.left.vf = e->e.r.left.vf;
  1245.             newrow=e->e.r.right.vf & FIX_ROW ?e->e.r.right.vp->row :
  1246.                             e->e.r.right.vp->row+Rdelta;
  1247.             newcol=e->e.r.right.vf & FIX_COL ?e->e.r.right.vp->col :
  1248.                             e->e.r.right.vp->col+Cdelta;
  1249.             ret->e.r.right.vp = lookat (newrow, newcol);
  1250.             ret->e.r.right.vf = e->e.r.right.vf;
  1251.             break;
  1252.         }
  1253.     default:
  1254.         ret->e.o.right = copye (e->e.o.right,Rdelta,Cdelta);
  1255.         ret->e.o.left = copye (e->e.o.left,Rdelta,Cdelta);
  1256.         break;
  1257.     }
  1258.     }
  1259.     return ret;
  1260. }
  1261.  
  1262. /*
  1263.  * sync_refs and syncref are used to remove references to
  1264.  * deleted struct ents.  Note that the deleted structure must still
  1265.  * be hanging around before the call, but not referenced by an entry
  1266.  * in tbl.  Thus the free_ent, fix_ent calls in sc.c
  1267.  */
  1268.  
  1269. sync_refs () {
  1270.     register i,j;
  1271.     register struct ent *p;
  1272.     sync_ranges();
  1273.     for (i=0; i<=maxrow; i++)
  1274.     for (j=0; j<=maxcol; j++)
  1275.         if ((p=tbl[i][j]) && p->expr)
  1276.         syncref(p->expr);
  1277. }
  1278.  
  1279.  
  1280. syncref(e)
  1281. register struct enode *e;
  1282. {
  1283.     if (e==0)
  1284.     return;
  1285.     else {
  1286.     switch (e->op) {
  1287.     case 'v':
  1288.         e->e.v.vp = lookat(e->e.v.vp->row, e->e.v.vp->col);
  1289.         break;
  1290.     case 'k':
  1291.         break;
  1292.     case '$':
  1293.         break;
  1294.      case O_REDUCE('+'):
  1295.      case O_REDUCE('*'):
  1296.      case O_REDUCE('a'):
  1297.      case O_REDUCE('s'):
  1298.      case O_REDUCE(MAX):
  1299.      case O_REDUCE(MIN):
  1300.          e->e.r.right.vp = lookat ( e->e.r.right.vp->row,
  1301.                                            e->e.r.right.vp->col);
  1302.          e->e.r.left.vp = lookat ( e->e.r.left.vp->row,
  1303.                                           e->e.r.left.vp->col);
  1304.         break;
  1305.     default:
  1306.         syncref(e->e.o.right);
  1307.         syncref(e->e.o.left);
  1308.         break;
  1309.     }
  1310.     }
  1311. }
  1312.  
  1313. hiderow(arg)
  1314. {
  1315.     register int r1;
  1316.     register int r2;
  1317.  
  1318.     r1 = currow;
  1319.     r2 = r1 + arg - 1;
  1320.     if (r1 < 0 || r1 > r2) {
  1321.     error("Invalid Range");
  1322.     return;
  1323.     }
  1324.     if (r2 > MAXROWS-2) {
  1325.     error("You can't hide the last row");
  1326.     return;
  1327.     }
  1328.     FullUpdate++;
  1329.     while (r1 <= r2)
  1330.     row_hidden[r1++] = 1;
  1331. }
  1332.  
  1333. hidecol(arg)
  1334. {
  1335.     register int c1;
  1336.     register int c2;
  1337.  
  1338.     c1 = curcol;
  1339.     c2 = c1 + arg - 1;
  1340.     if (c1 < 0 || c1 > c2) {
  1341.     error("Invalid Range");
  1342.     return;
  1343.     }
  1344.     if (c2 > MAXCOLS-2) {
  1345.     error("You can't hide the last col");
  1346.     return;
  1347.     }
  1348.     FullUpdate++;
  1349.     while (c1 <= c2)
  1350.     col_hidden[c1++] = 1;
  1351. }
  1352.  
  1353. showrow(r1, r2)
  1354. {
  1355.     if (r1 < 0 || r1 > r2) {
  1356.     error("Invalid Range");
  1357.     return;
  1358.     }
  1359.     if (r2 > MAXROWS-1) {
  1360.     r2 = MAXROWS-1;
  1361.     }
  1362.     FullUpdate++;
  1363.     while (r1 <= r2)
  1364.     row_hidden[r1++] = 0;
  1365. }
  1366.  
  1367. showcol(c1, c2)
  1368. {
  1369.     if (c1 < 0 || c1 > c2) {
  1370.     error("Invalid Range");
  1371.     return;
  1372.     }
  1373.     if (c2 > MAXCOLS-1) {
  1374.     c2 = MAXCOLS-1;
  1375.     }
  1376.     FullUpdate++;
  1377.     while (c1 <= c2)
  1378.     col_hidden[c1++] = 0;
  1379. }
  1380.  
  1381. /* Open the output file, setting up a pipe if needed */
  1382.  
  1383. FILE *
  1384. openout(fname, rpid)
  1385. char *fname;
  1386. int *rpid;
  1387. {
  1388.     int pipefd[2];
  1389.     int pid;
  1390.     FILE *f;
  1391.  
  1392.     while (*fname && (*fname == ' '))  /* Skip leading blanks */
  1393.     fname++;
  1394.  
  1395.     if (*fname != '|') {        /* Open file if not pipe */
  1396.     *rpid = 0;
  1397.     return(fopen(fname, "w"));
  1398.     }
  1399.  
  1400.     fname++;                /* Skip | */
  1401.     if ( pipe (pipefd) < 0) {
  1402.     error("Can't make pipe to child");
  1403.     *rpid = 0;
  1404.     return(0);
  1405.     }
  1406.  
  1407.     deraw();
  1408.     if ((pid=fork()) == 0)              /* if child  */
  1409.     {
  1410.     (void) close (0);              /* close stdin */
  1411.     (void) close (pipefd[1]);
  1412.     (void) dup (pipefd[0]);          /* connect to pipe input */
  1413.     (void) execl ("/bin/sh", "sh", "-c", fname, 0);
  1414.     exit (-127);
  1415.     }
  1416.     else                  /* else parent */
  1417.     {
  1418.     *rpid = pid;
  1419.     f = fdopen (pipefd[1], "w");
  1420.     if (f == 0)
  1421.     {
  1422.         (void) kill (pid, -9);
  1423.         error ("Can't fdopen output");
  1424.         (void) close (pipefd[1]);
  1425.         *rpid = 0;
  1426.         return(0);
  1427.     }
  1428.     }
  1429.     return(f);
  1430. }
  1431.  
  1432. closeout(f, pid)
  1433. FILE *f;
  1434. int pid;
  1435. {
  1436.     int temp;
  1437.  
  1438.     (void) fclose (f);
  1439.     if (pid) {
  1440.          while (pid != wait(&temp)) /**/;
  1441.      (void) printf("Press <return> to continue");
  1442.      (void) fflush(stdout);
  1443.      (void) nmgetch();
  1444.      goraw();
  1445.     }
  1446. }
  1447. \SHAR\EOF\
  1448. else
  1449.   echo "will not over write ./interp.c"
  1450. fi
  1451. if [ `wc -c ./interp.c | awk '{printf $1}'` -ne 31137 ]
  1452. then
  1453. echo `wc -c ./interp.c | awk '{print "Got " $1 ", Expected " 31137}'`
  1454. fi
  1455. if `test ! -s ./cmds.c`
  1456. then
  1457. echo "Extracting ./cmds.c"
  1458. cat > ./cmds.c << '\SHAR\EOF\'
  1459. /*    SC    A Spreadsheet Calculator
  1460.  *        Main driver
  1461.  *
  1462.  *        original by James Gosling, September 1982
  1463.  *        modifications by Mark Weiser and Bruce Israel,
  1464.  *            University of Maryland
  1465.  *
  1466.  *              More mods Robert Bond, 12/86
  1467.  *
  1468.  */
  1469.  
  1470. #include <curses.h>
  1471. #include "sc.h"
  1472.  
  1473. #ifdef BSD42
  1474. #include <strings.h>
  1475. #else
  1476. #ifndef SYSIII
  1477. #include <string.h>
  1478. #endif
  1479. #endif
  1480.  
  1481. duprow()
  1482. {
  1483.     if (currow >= MAXROWS - 1 || maxrow >= MAXROWS - 1) {
  1484.     error ("The table can't be any bigger");
  1485.     return;
  1486.     }
  1487.     modflg++;
  1488.     currow++;
  1489.     openrow (currow);
  1490.     for (curcol = 0; curcol <= maxcol; curcol++) {
  1491.     register struct ent *p = tbl[currow - 1][curcol];
  1492.     if (p) {
  1493.         register struct ent *n;
  1494.         n = lookat (currow, curcol);
  1495.         n -> v = p -> v;
  1496.         n -> flags = p -> flags;
  1497.         n -> expr = copye (p -> expr, 1, 0);
  1498.         n -> label = 0;
  1499.         if (p -> label) {
  1500.         n -> label = (char *)
  1501.                  xmalloc ((unsigned)(strlen (p -> label) + 1));
  1502.         (void) strcpy (n -> label, p -> label);
  1503.         }
  1504.     }
  1505.     }
  1506.     for (curcol = 0; curcol <= maxcol; curcol++) {
  1507.     register struct ent *p = tbl[currow][curcol];
  1508.     if (p && (p -> flags & is_valid) && !p -> expr)
  1509.         break;
  1510.     }
  1511.     if (curcol > maxcol)
  1512.     curcol = 0;
  1513. }
  1514.  
  1515. dupcol() 
  1516. {
  1517.     if (curcol >= MAXCOLS - 1 || maxcol >= MAXCOLS - 1) {
  1518.     error ("The table can't be any wider");
  1519.     return;
  1520.     }
  1521.     modflg++;
  1522.     curcol++;
  1523.     opencol (curcol);
  1524.     for (currow = 0; currow <= maxrow; currow++) {
  1525.     register struct ent *p = tbl[currow][curcol - 1];
  1526.     if (p) {
  1527.         register struct ent *n;
  1528.         n = lookat (currow, curcol);
  1529.         n -> v = p -> v;
  1530.         n -> flags = p -> flags;
  1531.         n -> expr = copye (p -> expr, 0, 1);
  1532.         n -> label = 0;
  1533.         if (p -> label) {
  1534.         n -> label = (char *)
  1535.                  xmalloc ((unsigned) (strlen (p -> label) + 1));
  1536.         (void) strcpy (n -> label, p -> label);
  1537.         }
  1538.     }
  1539.     }
  1540.     for (currow = 0; currow <= maxrow; currow++) {
  1541.     register struct ent *p = tbl[currow][curcol];
  1542.     if (p && (p -> flags & is_valid) && !p -> expr)
  1543.         break;
  1544.     }
  1545.     if (currow > maxrow)
  1546.     currow = 0;
  1547. }
  1548.  
  1549. insertrow(arg)
  1550. {
  1551.     while (--arg>=0) openrow (currow);
  1552. }
  1553.  
  1554. deleterow(arg)
  1555. {
  1556.     flush_saved();
  1557.     erase_area(currow, 0, currow + arg - 1, maxcol);
  1558.     currow += arg;
  1559.     while (--arg>=0) closerow (--currow);
  1560.     sync_refs();
  1561. }
  1562.  
  1563. insertcol(arg)
  1564. {
  1565.     while (--arg>=0) opencol(curcol);
  1566. }
  1567.  
  1568. deletecol(arg)
  1569. {
  1570.     flush_saved();
  1571.     erase_area(0, curcol, maxrow, curcol + arg - 1);
  1572.     curcol += arg;
  1573.     while (--arg>=0) closecol (--curcol);
  1574.     sync_refs();
  1575. }
  1576.  
  1577. rowvalueize(arg)
  1578. {
  1579.     valueize_area(currow, 0, currow + arg - 1, maxcol);
  1580. }
  1581.  
  1582. colvalueize(arg)
  1583. {
  1584.     valueize_area(0, curcol, maxrow, curcol + arg - 1);
  1585. }
  1586.  
  1587. erase_area(sr, sc, er, ec)
  1588. int sr, sc, er, ec;
  1589. {
  1590.     register int r, c;
  1591.     register struct ent **p;
  1592.  
  1593.     if (sr > er) {
  1594.     r = sr; sr = er; er= r;    
  1595.     }
  1596.  
  1597.     if (sc > ec) {
  1598.     c = sc; sc = ec; ec= c;    
  1599.     }
  1600.  
  1601.     if (sr < 0)
  1602.     sr = 0; 
  1603.     if (sc < 0)
  1604.     sc = 0;
  1605.     if (er >= MAXROWS)
  1606.     er = MAXROWS-1;
  1607.     if (ec >= MAXCOLS)
  1608.     ec = MAXCOLS-1;
  1609.  
  1610.     for (r = sr; r <= er; r++) {
  1611.     for (c = sc; c <= ec; c++) {
  1612.         p = &tbl[r][c];
  1613.         if (*p) {
  1614.         free_ent(*p);
  1615.         *p = 0;
  1616.         }
  1617.     }
  1618.     }
  1619.  
  1620. }
  1621.  
  1622. valueize_area(sr, sc, er, ec)
  1623. int sr, sc, er, ec;
  1624. {
  1625.     register int r, c;
  1626.     register struct ent *p;
  1627.  
  1628.     if (sr > er) {
  1629.     r = sr; sr = er; er= r;    
  1630.     }
  1631.  
  1632.     if (sc > ec) {
  1633.     c = sc; sc = ec; ec= c;    
  1634.     }
  1635.  
  1636.     if (sr < 0)
  1637.     sr = 0; 
  1638.     if (sc < 0)
  1639.     sc = 0;
  1640.     if (er >= MAXROWS)
  1641.     er = MAXROWS-1;
  1642.     if (ec >= MAXCOLS)
  1643.     ec = MAXCOLS-1;
  1644.  
  1645.     for (r = sr; r <= er; r++) {
  1646.     for (c = sc; c <= ec; c++) {
  1647.         p = tbl[r][c];
  1648.         if (p && p->expr) {
  1649.         efree(p->expr);
  1650.         p->expr = 0;
  1651.         p->flags &= ~is_strexpr;
  1652.         }
  1653.     }
  1654.     }
  1655.  
  1656. }
  1657.  
  1658. pullcells(to_insert)
  1659. {
  1660.     register struct ent *p, *n;
  1661.     register int deltar, deltac;
  1662.     int minrow, mincol;
  1663.     int mxrow, mxcol;
  1664.     int numrows, numcols;
  1665.  
  1666.     if (!to_fix)
  1667.     return;
  1668.  
  1669.     switch (to_insert) {
  1670.     case 'm':
  1671.     case 'r':
  1672.     case 'c':
  1673.     break;
  1674.     default:
  1675.     error("Invalid pull command");
  1676.     return;
  1677.     }
  1678.  
  1679.     minrow = MAXROWS; 
  1680.     mincol = MAXCOLS;
  1681.     mxrow = 0;
  1682.     mxcol = 0;
  1683.  
  1684.     for (p = to_fix; p; p = p->next) {
  1685.     if (p->row < minrow)
  1686.         minrow = p->row;
  1687.     if (p->row > mxrow)
  1688.         mxrow = p->row;
  1689.     if (p->col < mincol)
  1690.         mincol = p->col;
  1691.     if (p->col > mxcol)
  1692.         mxcol = p->col;
  1693.     }
  1694.  
  1695.     numrows = mxrow - minrow + 1;
  1696.     numcols = mxcol - mincol + 1;
  1697.     deltar = currow - minrow;
  1698.     deltac = curcol - mincol;
  1699.  
  1700.     if (to_insert == 'r') {
  1701.     insertrow(numrows);
  1702.     deltac = 0;
  1703.     } else if (to_insert == 'c') {
  1704.     insertcol(numcols);
  1705.     deltar = 0;
  1706.     }
  1707.  
  1708.     FullUpdate++;
  1709.     modflg++;
  1710.  
  1711.     for (p = to_fix; p; p = p->next) {
  1712.     n = lookat (p->row + deltar, p->col + deltac);
  1713.     (void) clearent(n);
  1714.     n -> flags = p -> flags & ~is_deleted;
  1715.     n -> v = p -> v;
  1716.     n -> expr = copye(p->expr, deltar, deltac);
  1717.     n -> label = 0;
  1718.     if (p -> label) {
  1719.         n -> label = (char *)
  1720.              xmalloc((unsigned)(strlen(p->label)+1));
  1721.         (void) strcpy (n -> label, p -> label);
  1722.     }
  1723.     }
  1724. }
  1725.  
  1726. colshow_op()
  1727. {
  1728.     register int i,j;
  1729.     for (i=0; i<MAXCOLS; i++)
  1730.     if (col_hidden[i]) 
  1731.         break;
  1732.     for(j=i; j<MAXCOLS; j++)
  1733.     if (!col_hidden[j])
  1734.         break;
  1735.     j--;
  1736.     if (i<MAXCOLS) {
  1737.     (void) sprintf(line,"show %s:", coltoa(i));
  1738.     (void) sprintf(line + strlen(line),"%s",coltoa(j));
  1739.     linelim = strlen (line);
  1740.     }
  1741. }
  1742.  
  1743. rowshow_op()
  1744. {
  1745.     register int i,j;
  1746.     for (i=0; i<MAXROWS; i++)
  1747.     if (row_hidden[i]) 
  1748.         break;
  1749.     for(j=i; j<MAXROWS; j++)
  1750.     if (!row_hidden[j]) {
  1751.         break;
  1752.     }
  1753.     j--;
  1754.     if (i<MAXROWS) {
  1755.     (void) sprintf(line,"show %d:%d", i, j);
  1756.         linelim = strlen (line);
  1757.     }
  1758. }
  1759.  
  1760. get_qual()
  1761. {
  1762.     register int c;
  1763.  
  1764.     c = nmgetch();
  1765.     switch (c) {
  1766.     case 'c':
  1767.     case 'j':
  1768.     case 'k':
  1769.     case ctl(p):
  1770.     case ctl(n):
  1771.     return('c');
  1772.     case 'r':
  1773.     case 'l':
  1774.     case 'h':
  1775.     case ctl(f):
  1776.     case ctl(b):
  1777.     return('r');
  1778.     default:
  1779.     return(c);
  1780.     }
  1781.     /*NOTREACHED*/
  1782. }
  1783.  
  1784. openrow (rs) {
  1785.     register    r;
  1786.     register struct ent **p;
  1787.     register    c;
  1788.     register    i;
  1789.  
  1790.     if (rs > maxrow) maxrow = rs;
  1791.     if (maxrow >= MAXROWS - 1 || rs > MAXROWS - 1) {
  1792.     error ("The table can't be any longer");
  1793.     return;
  1794.     }
  1795.     for (i = maxrow+1; i > rs; i--) {
  1796.     row_hidden[i] = row_hidden[i-1];
  1797.     }
  1798.     for (r = ++maxrow; r > rs; r--)
  1799.     for (c = maxcol + 1, p = &tbl[r][0]; --c >= 0; p++)
  1800.         if (p[0] = p[-MAXCOLS])
  1801.         p[0] -> row++;
  1802.     p = &tbl[rs][0];
  1803.     for (c = maxcol + 1; --c >= 0;)
  1804.     *p++ = 0;
  1805.     FullUpdate++;
  1806.     modflg++;
  1807. }
  1808.  
  1809. closerow (r)
  1810. register r; {
  1811.     register struct ent **p;
  1812.     register c;
  1813.     register int i;
  1814.  
  1815.     if (r > maxrow) return;
  1816.  
  1817.     p = &tbl[r][0];
  1818.     for (c=maxcol+1; --c>=0; ) {
  1819.     if (*p)
  1820.         free_ent(*p);
  1821.     *p++ = 0;
  1822.     }
  1823.  
  1824.     for (i = r; i < MAXROWS - 1; i++) {
  1825.     row_hidden[i] = row_hidden[i+1];
  1826.     }
  1827.  
  1828.     while (r<maxrow) {
  1829.     for (c = maxcol+1, p = &tbl[r][0]; --c>=0; p++)
  1830.         if (p[0] = p[MAXCOLS])
  1831.         p[0]->row--;
  1832.     r++;
  1833.     }
  1834.  
  1835.     p = &tbl[maxrow][0];
  1836.     for (c=maxcol+1; --c>=0; ) *p++ = 0;
  1837.     maxrow--;
  1838.     FullUpdate++;
  1839.     modflg++;
  1840. }
  1841.  
  1842. opencol (cs) {
  1843.     register r;
  1844.     register struct ent **p;
  1845.     register c;
  1846.     register lim = maxcol-cs+1;
  1847.     int i;
  1848.  
  1849.     if (cs > maxcol) maxcol = cs;
  1850.     if (maxcol >= MAXCOLS - 1 || cs > MAXCOLS - 1) {
  1851.     error ("The table can't be any wider");
  1852.     return;
  1853.     }
  1854.     for (i = maxcol+1; i > cs; i--) {
  1855.     fwidth[i] = fwidth[i-1];
  1856.     precision[i] = precision[i-1];
  1857.     col_hidden[i] = col_hidden[i-1];
  1858.     }
  1859.     /* fwidth[cs] = DEFWIDTH;
  1860.     precision[i] =  DEFPREC;  */
  1861.  
  1862.     for (r=0; r<=maxrow; r++) {
  1863.     p = &tbl[r][maxcol+1];
  1864.     for (c=lim; --c>=0; p--)
  1865.         if (p[0] = p[-1])
  1866.         p[0]->col++;
  1867.     p[0] = 0;
  1868.     }
  1869.     maxcol++;
  1870.     FullUpdate++;
  1871.     modflg++;
  1872. }
  1873.  
  1874. closecol (cs) {
  1875.     register r;
  1876.     register struct ent **p;
  1877.     register struct ent *q;
  1878.     register c;
  1879.     register lim = maxcol-cs;
  1880.     int i;
  1881.  
  1882.     if (lim < 0) return;
  1883.  
  1884.     for (r=0; r<=maxrow; r++)
  1885.     if (q = tbl[r][cs]) {
  1886.         free_ent(q);
  1887.     }
  1888.  
  1889.     for (r=0; r<=maxrow; r++) {
  1890.     p = &tbl[r][cs];
  1891.     for (c=lim; --c>=0; p++)
  1892.         if (p[0] = p[1])
  1893.         p[0]->col--;
  1894.     p[0] = 0;
  1895.     }
  1896.  
  1897.     for (i = cs; i < MAXCOLS - 1; i++) {
  1898.     fwidth[i] = fwidth[i+1];
  1899.     precision[i] = precision[i+1];
  1900.     col_hidden[i] = col_hidden[i+1];
  1901.     }
  1902.  
  1903.     maxcol--;
  1904.     FullUpdate++;
  1905.     modflg++;
  1906. }
  1907.  
  1908. doend(rowinc, colinc)
  1909. {
  1910.     register struct ent *p;
  1911.     int r, c;
  1912.  
  1913.     if (VALID_CELL(p, currow, curcol)) {
  1914.     r = currow + rowinc;
  1915.     c = curcol + colinc;
  1916.     if (r >= 0 && r < MAXROWS && 
  1917.         c >= 0 && c < MAXCOLS &&
  1918.         !VALID_CELL(p, r, c)) {
  1919.         currow = r;
  1920.         curcol = c;
  1921.     }
  1922.     }
  1923.  
  1924.     if (!VALID_CELL(p, currow, curcol)) {
  1925.         switch (rowinc) {
  1926.         case -1:
  1927.         while (!VALID_CELL(p, currow, curcol) && currow > 0)
  1928.         currow--;
  1929.         break;
  1930.         case  1:
  1931.         while (!VALID_CELL(p, currow, curcol) && currow < MAXROWS-1)
  1932.         currow++;
  1933.         break;
  1934.         case  0:
  1935.             switch (colinc) {
  1936.          case -1:
  1937.             while (!VALID_CELL(p, currow, curcol) && curcol > 0)
  1938.             curcol--;
  1939.             break;
  1940.          case  1:
  1941.             while (!VALID_CELL(p, currow, curcol) && curcol < MAXCOLS-1)
  1942.             curcol++;
  1943.             break;
  1944.         }
  1945.             break;
  1946.         }
  1947.     return;
  1948.     }
  1949.  
  1950.     switch (rowinc) {
  1951.     case -1:
  1952.     while (VALID_CELL(p, currow, curcol) && currow > 0)
  1953.         currow--;
  1954.     break;
  1955.     case  1:
  1956.     while (VALID_CELL(p, currow, curcol) && currow < MAXROWS-1)
  1957.         currow++;
  1958.     break;
  1959.     case  0:
  1960.     switch (colinc) {
  1961.     case -1:
  1962.         while (VALID_CELL(p, currow, curcol) && curcol > 0)
  1963.         curcol--;
  1964.         break;
  1965.     case  1:
  1966.         while (VALID_CELL(p, currow, curcol) && curcol < MAXCOLS-1)
  1967.         curcol++;
  1968.         break;
  1969.     }
  1970.     break;
  1971.     }
  1972.     if (!VALID_CELL(p, currow, curcol)) {
  1973.         currow -= rowinc;
  1974.         curcol -= colinc;
  1975.     }
  1976. }
  1977.  
  1978. doformat(c1,c2,w,p)
  1979. int c1,c2,w,p;
  1980. {
  1981.     register int i;
  1982.  
  1983.     if (w > COLS - RESCOL - 2) {
  1984.     error("Format too large - Maximum = %d", COLS - RESCOL - 2);
  1985.     w = COLS-RESCOL-2;
  1986.     }
  1987.  
  1988.     if (p > w) {
  1989.     error("Precision too large");
  1990.     p = w;
  1991.     }
  1992.  
  1993.     for(i = c1; i<=c2; i++)
  1994.     fwidth[i] = w, precision[i] = p;
  1995.  
  1996.     FullUpdate++;
  1997.     modflg++;
  1998. }
  1999. \SHAR\EOF\
  2000. else
  2001.   echo "will not over write ./cmds.c"
  2002. fi
  2003. if [ `wc -c ./cmds.c | awk '{printf $1}'` -ne 9940 ]
  2004. then
  2005. echo `wc -c ./cmds.c | awk '{print "Got " $1 ", Expected " 9940}'`
  2006. fi
  2007. if `test ! -s ./crypt.c`
  2008. then
  2009. echo "Extracting ./crypt.c"
  2010. cat > ./crypt.c << '\SHAR\EOF\'
  2011. /*
  2012.  * Encryption utilites
  2013.  * Bradley Williams    
  2014.  * {allegra,ihnp4,uiucdcs,ctvax}!convex!williams
  2015.  */
  2016.  
  2017. #include <stdio.h>
  2018. #include <curses.h>
  2019.  
  2020. #if defined(BSD42) || defined(BSD43)
  2021. #include <sys/file.h>
  2022. #else
  2023. #include <fcntl.h>
  2024. #endif
  2025.  
  2026. #include "sc.h"
  2027.  
  2028. extern char curfile[];
  2029. char        *strcpy();
  2030. #ifdef SYSV3
  2031. void exit();
  2032. #endif
  2033.  
  2034. int         Crypt = 0;
  2035.  
  2036. #define DEFWIDTH 10
  2037. #define DEFPREC   2
  2038.  
  2039. creadfile (save, eraseflg)
  2040. char *save;
  2041. {
  2042.     register FILE *f;
  2043.     int pipefd[2];
  2044.     int fildes;
  2045.     int pid;
  2046.  
  2047.     if (eraseflg && strcmp(save, curfile) && modcheck(" first")) return;
  2048.  
  2049.     fildes = open (save, O_RDONLY, 0);
  2050.     if (fildes < 0)
  2051.     {
  2052.     error ("Can't read %s", save);
  2053.     return;
  2054.     }
  2055.  
  2056.     if (eraseflg) erasedb ();
  2057.  
  2058.     if (pipe(pipefd) < 0) {
  2059.     error("Can't make pipe to child");
  2060.     return;
  2061.     }
  2062.  
  2063.     deraw();
  2064.     if ((pid=fork()) == 0)              /* if child  */
  2065.     {
  2066.     (void) close (0);          /* close stdin */
  2067.     (void) close (1);          /* close stdout */
  2068.     (void) close (pipefd[0]);      /* close pipe input */
  2069.     (void) dup (fildes);          /* standard in from file */
  2070.     (void) dup (pipefd[1]);          /* connect to pipe */
  2071.     (void) fprintf (stderr, " ");
  2072.     (void) execl ("/bin/sh", "sh", "-c", "crypt", 0);
  2073.     exit (-127);
  2074.     }
  2075.     else                  /* else parent */
  2076.     {
  2077.     (void) close (fildes);
  2078.     (void) close (pipefd[1]);      /* close pipe output */
  2079.     f = fdopen (pipefd[0], "r");
  2080.     if (f == 0)
  2081.     {
  2082.         (void) kill (pid, -9);
  2083.         error ("Can't fdopen file %s", save);
  2084.         (void) close (pipefd[0]);
  2085.         return;
  2086.     }
  2087.     }
  2088.  
  2089.     while (fgets(line,sizeof line,f)) {
  2090.     linelim = 0;
  2091.     if (line[0] != '#') (void) yyparse ();
  2092.     }
  2093.     (void) fclose (f);
  2094.     (void) close (pipefd[0]);
  2095.     while (pid != wait(&fildes)) /**/;
  2096.     goraw();
  2097.     linelim = -1;
  2098.     modflg++;
  2099.     if (eraseflg) {
  2100.     (void) strcpy (curfile, save);
  2101.     modflg = 0;
  2102.     }
  2103.     EvalAll();
  2104. }
  2105.  
  2106. cwritefile (fname, r0, c0, rn, cn)
  2107. char *fname;
  2108. {
  2109.     register FILE *f;
  2110.     register struct ent **p;
  2111.     register r, c;
  2112.     int pipefd[2];
  2113.     int fildes;
  2114.     int pid;
  2115.     char save[1024];
  2116.  
  2117.     if (*fname == 0) fname = &curfile[0];
  2118.  
  2119.     (void) strcpy(save,fname);
  2120.  
  2121.     fildes = open (save, O_WRONLY|O_CREAT, 0600);
  2122.     if (fildes < 0)
  2123.     {
  2124.     error ("Can't create %s", save);
  2125.     return(-1);
  2126.     }
  2127.  
  2128.     if (pipe (pipefd) < 0) {
  2129.     error ("Can't make pipe to child\n");
  2130.     return(-1);
  2131.     }
  2132.  
  2133.     deraw();
  2134.     if ((pid=fork()) == 0)              /* if child  */
  2135.     {
  2136.     (void) close (0);              /* close stdin */
  2137.     (void) close (1);              /* close stdout */
  2138.     (void) close (pipefd[1]);          /* close pipe output */
  2139.     (void) dup (pipefd[0]);              /* connect to pipe input */
  2140.     (void) dup (fildes);              /* standard out to file */
  2141.     (void) fprintf (stderr, " ");
  2142.     (void) execl ("/bin/sh", "sh", "-c", "crypt", 0);
  2143.     exit (-127);
  2144.     }
  2145.     else                  /* else parent */
  2146.     {
  2147.     (void) close (fildes);
  2148.     (void) close (pipefd[0]);          /* close pipe input */
  2149.     f = fdopen (pipefd[1], "w");
  2150.     if (f == 0)
  2151.     {
  2152.         (void) kill (pid, -9);
  2153.         error ("Can't fdopen file %s", save);
  2154.         (void) close (pipefd[1]);
  2155.         return(-1);
  2156.     }
  2157.     }
  2158.  
  2159.     (void) fprintf (f, "# This data file was generated by the Spreadsheet ");
  2160.     (void) fprintf (f, "Calculator.\n");
  2161.     (void) fprintf (f, "# You almost certainly shouldn't edit it.\n\n");
  2162.     for (c=0; c<MAXCOLS; c++)
  2163.     if (fwidth[c] != DEFWIDTH || precision[c] != DEFPREC)
  2164.         (void)fprintf(f,"format %s %d %d\n",coltoa(c),fwidth[c],precision[c]);
  2165.     write_range(f);
  2166.     if (mdir)
  2167.     (void) fprintf(f, "mdir \"%s\"\n", mdir);
  2168.     for (r=r0; r<=rn; r++) {
  2169.     p = &tbl[r][0];
  2170.     for (c=c0; c<=cn; c++, p++)
  2171.         if (*p) {
  2172.         if ((*p)->label) {
  2173.             edits(r, c);
  2174.             (void) fprintf(f, "%s\n", line);
  2175.         }
  2176.         if ((*p)->flags&is_valid) {
  2177.             editv(r, c);
  2178.             (void) fprintf (f, "%s\n",line);
  2179.         }
  2180.         }
  2181.     }
  2182.     (void) fclose (f);
  2183.     (void) close (pipefd[1]);
  2184.     while (pid != wait(&fildes)) /**/;
  2185.     (void) strcpy(curfile,save);
  2186.  
  2187.     modflg = 0;
  2188.     error("File '%s' written.",curfile);
  2189.     goraw();
  2190.     return(0);
  2191. }
  2192. \SHAR\EOF\
  2193. else
  2194.   echo "will not over write ./crypt.c"
  2195. fi
  2196. if [ `wc -c ./crypt.c | awk '{printf $1}'` -ne 3930 ]
  2197. then
  2198. echo `wc -c ./crypt.c | awk '{print "Got " $1 ", Expected " 3930}'`
  2199. fi
  2200. if `test ! -s ./xmalloc.c`
  2201. then
  2202. echo "Extracting ./xmalloc.c"
  2203. cat > ./xmalloc.c << '\SHAR\EOF\'
  2204. /*
  2205.  * A safer saner malloc, for careless programmers
  2206.  */
  2207.  
  2208. #include <stdio.h>
  2209. #include <curses.h>
  2210.  
  2211. extern char *malloc();
  2212. #ifdef SYSV3
  2213. extern void free();
  2214. extern void exit();
  2215. #endif
  2216.  
  2217. char *
  2218. xmalloc(n)
  2219. unsigned n;
  2220. {
  2221. register char *ptr;
  2222.  
  2223. if ((ptr = malloc(n + sizeof(int))) == NULL)
  2224.     fatal("xmalloc: no memory");
  2225. *((int *) ptr) = 12345;        /* magic number */
  2226. return(ptr + sizeof(int));
  2227. }
  2228.  
  2229. xfree(p)
  2230. char *p;
  2231. {
  2232. if (p == NULL)
  2233.     fatal("xfree: NULL");
  2234. p -= sizeof(int);
  2235. if (*((int *) p) != 12345)
  2236.     fatal("xfree: storage not malloc'ed");
  2237. free(p);
  2238. }
  2239.  
  2240. fatal(str)
  2241. char *str;
  2242. {
  2243.     deraw();
  2244.     (void) fprintf(stderr,"%s\n", str);
  2245.     exit(1);
  2246. }
  2247. \SHAR\EOF\
  2248. else
  2249.   echo "will not over write ./xmalloc.c"
  2250. fi
  2251. if [ `wc -c ./xmalloc.c | awk '{printf $1}'` -ne 640 ]
  2252. then
  2253. echo `wc -c ./xmalloc.c | awk '{print "Got " $1 ", Expected " 640}'`
  2254. fi
  2255. if `test ! -s ./range.c`
  2256. then
  2257. echo "Extracting ./range.c"
  2258. cat > ./range.c << '\SHAR\EOF\'
  2259.  
  2260. /*    SC    A Spreadsheet Calculator
  2261.  *        Range Manipulations
  2262.  *
  2263.  *              Robert Bond, 4/87
  2264.  *
  2265.  */
  2266.  
  2267. #include <stdio.h>
  2268. #include <curses.h>
  2269. #include <ctype.h>
  2270. #include "sc.h"
  2271.  
  2272. #ifdef BSD42
  2273. #include <strings.h>
  2274. #else
  2275. #ifndef SYSIII
  2276. #include <string.h>
  2277. #endif
  2278. #endif
  2279.  
  2280. static struct range *rng_base;
  2281.  
  2282. add_range(name, left, right, is_range)
  2283. char *name;
  2284. struct ent_ptr left, right;
  2285. int is_range;
  2286. {
  2287.     struct range *r;
  2288.     register char *p;
  2289.     int len;
  2290.     int minr,minc,maxr,maxc;
  2291.     int minrf, mincf, maxrf, maxcf;
  2292.  
  2293.     if (left.vp->row < right.vp->row) {
  2294.     minr = left.vp->row; minrf = left.vf & FIX_ROW;
  2295.     maxr = right.vp->row; maxrf = right.vf & FIX_ROW;
  2296.     } else {
  2297.     minr = right.vp->row; minrf = right.vf & FIX_ROW;
  2298.     maxr = left.vp->row; maxrf = right.vf & FIX_ROW;
  2299.     } 
  2300.  
  2301.     if (left.vp->col < right.vp->col) {
  2302.     minc = left.vp->col; mincf = left.vf & FIX_COL;
  2303.     maxc = right.vp->col; maxcf = right.vf & FIX_COL;
  2304.     } else {
  2305.     minc = right.vp->col; mincf = right.vf & FIX_COL;
  2306.     maxc = left.vp->col; maxcf = left.vf & FIX_COL;
  2307.     } 
  2308.  
  2309.     left.vp = lookat(minr, minc);
  2310.     left.vf = minrf | mincf;
  2311.     right.vp = lookat(maxr, maxc);
  2312.     right.vf = maxrf | maxcf;
  2313.  
  2314.     if (find_range(name, strlen(name), (struct ent *)0, (struct ent *)0)) {
  2315.     error("Error: range name already defined");
  2316.     xfree(name);
  2317.     return;
  2318.     }
  2319.  
  2320.     if (strlen(name) <= 2) {
  2321.     error("Invalid range name - too short");
  2322.     xfree(name);
  2323.     return;
  2324.     }
  2325.  
  2326.     for(p=name, len=0; *p; p++, len++)
  2327.     if (!((isalpha(*p) && (len<=2)) ||
  2328.         ((isdigit(*p) || isalpha(*p) || (*p == '_')) && (len>2)))) {
  2329.         error("Invalid range name - illegal combination");
  2330.         xfree(name);
  2331.         return;
  2332.         }
  2333.  
  2334.     r = (struct range *)xmalloc((unsigned)sizeof(struct range));
  2335.     r->r_name = name;
  2336.     r->r_left = left;
  2337.     r->r_right = right;
  2338.     r->r_next = rng_base;
  2339.     r->r_prev = 0;
  2340.     r->r_is_range = is_range;
  2341.     if (rng_base)
  2342.         rng_base->r_prev = r;
  2343.     rng_base = r;
  2344. }
  2345.  
  2346. del_range(left, right)
  2347. struct ent *left, *right;
  2348. {
  2349.     register struct range *r;
  2350.     int minr,minc,maxr,maxc;
  2351.  
  2352.     minr = left->row < right->row ? left->row : right->row;
  2353.     minc = left->col < right->col ? left->col : right->col;
  2354.     maxr = left->row > right->row ? left->row : right->row;
  2355.     maxc = left->col > right->col ? left->col : right->col;
  2356.  
  2357.     left = lookat(minr, minc);
  2358.     right = lookat(maxr, maxc);
  2359.  
  2360.     if (!(r = find_range((char *)0, 0, left, right))) 
  2361.     return;
  2362.  
  2363.     if (r->r_next)
  2364.         r->r_next->r_prev = r->r_prev;
  2365.     if (r->r_prev)
  2366.         r->r_prev->r_next = r->r_next;
  2367.     else
  2368.     rng_base = r->r_next;
  2369.     xfree((char *)(r->r_name));
  2370.     xfree((char *)r);
  2371. }
  2372.  
  2373. clean_range()
  2374. {
  2375.     register struct range *r;
  2376.     register struct range *nextr;
  2377.  
  2378.     r = rng_base;
  2379.     rng_base = 0;
  2380.  
  2381.     while (r) {
  2382.     nextr = r->r_next;
  2383.     xfree((char *)(r->r_name));
  2384.     xfree((char *)r);
  2385.     r = nextr;
  2386.     }
  2387. }
  2388.  
  2389. /* Match on name or lmatch, rmatch */
  2390.  
  2391. struct range *
  2392. find_range(name, len, lmatch, rmatch)
  2393. char *name;
  2394. int len;
  2395. struct ent *lmatch;
  2396. struct ent *rmatch;
  2397. {
  2398.     struct range *r;
  2399.     register char *rp, *np;
  2400.     register int c;
  2401.  
  2402.     if (name) {
  2403.     for (r = rng_base; r; r = r->r_next) {
  2404.         for (np = name, rp = r->r_name, c = len;
  2405.          c && *rp && (*rp == *np);
  2406.          rp++, np++, c--) /* */;
  2407.         if (!c && !*rp)
  2408.         return(r);
  2409.     }
  2410.     return(0);
  2411.     }
  2412.  
  2413.     for (r = rng_base; r; r= r->r_next) {
  2414.     if ((lmatch == r->r_left.vp) && (rmatch == r->r_right.vp)) 
  2415.         return(r);
  2416.     }
  2417.     return(0);
  2418. }
  2419.  
  2420. sync_ranges()
  2421. {
  2422.     register struct range *r;
  2423.  
  2424.     r = rng_base;
  2425.     while(r) {
  2426.     r->r_left.vp = lookat(r->r_left.vp->row, r->r_left.vp->col);
  2427.     r->r_right.vp = lookat(r->r_right.vp->row, r->r_right.vp->col);
  2428.     r = r->r_next;
  2429.     }
  2430. }
  2431.  
  2432. write_range(f)
  2433. FILE *f;
  2434. {
  2435.     register struct range *r;
  2436.  
  2437.     for (r = rng_base; r; r = r->r_next) {
  2438.     (void) fprintf(f, "define \"%s\" %s%s%s%d",
  2439.             r->r_name,
  2440.             r->r_left.vf & FIX_COL ? "$":"",
  2441.             coltoa(r->r_left.vp->col), 
  2442.             r->r_left.vf & FIX_ROW ? "$":"",
  2443.             r->r_left.vp->row);
  2444.     if (r->r_is_range)
  2445.         (void) fprintf(f, ":%s%s%s%d\n",
  2446.                 r->r_right.vf & FIX_COL ? "$":"",
  2447.                 coltoa(r->r_right.vp->col), 
  2448.                 r->r_right.vf & FIX_ROW ? "$":"",
  2449.                 r->r_right.vp->row);
  2450.     else
  2451.         (void) fprintf(f, "\n");
  2452.     }
  2453. }
  2454.  
  2455. list_range(f)
  2456. FILE *f;
  2457. {
  2458.     register struct range *r;
  2459.  
  2460.     for (r = rng_base; r; r = r->r_next) {
  2461.     (void) fprintf(f, "%-30s %s%s%s%d",
  2462.                 r->r_name,
  2463.                 r->r_left.vf & FIX_COL ? "$":"",
  2464.                 coltoa(r->r_left.vp->col), 
  2465.                 r->r_left.vf & FIX_ROW ? "$":"",
  2466.                 r->r_left.vp->row);
  2467.     if (r->r_is_range)
  2468.         (void) fprintf(f, ":%s%s%s%d\n",
  2469.                 r->r_right.vf & FIX_COL ? "$":"",
  2470.                 coltoa(r->r_right.vp->col), 
  2471.                 r->r_right.vf & FIX_ROW ? "$":"",
  2472.                 r->r_right.vp->row);
  2473.     else
  2474.         (void) fprintf(f, "\n");
  2475.     }
  2476. }
  2477.  
  2478. char *
  2479. v_name(row, col)
  2480. int row, col;
  2481. {
  2482.     struct ent *v;
  2483.     struct range *r;
  2484.     static char buf[20];
  2485.  
  2486.     v = lookat(row, col);
  2487.     if (r = find_range((char *)0, 0, v, v)) {
  2488.     return(r->r_name);
  2489.     } else {
  2490.         (void) sprintf(buf, "%s%d", coltoa(col), row);
  2491.     return(buf);
  2492.     }
  2493. }
  2494.  
  2495. char *
  2496. r_name(r1, c1, r2, c2)
  2497. int r1, c1, r2, c2;
  2498. {
  2499.     struct ent *v1, *v2;
  2500.     struct range *r;
  2501.     static char buf[100];
  2502.  
  2503.     v1 = lookat(r1, c1);
  2504.     v2 = lookat(r2, c2);
  2505.     if (r = find_range((char *)0, 0, v1, v2)) {
  2506.     return(r->r_name);
  2507.     } else {
  2508.         (void) sprintf(buf, "%s", v_name(r1, c1));
  2509.     (void) sprintf(buf+strlen(buf), ":%s", v_name(r2, c2));
  2510.     return(buf);
  2511.     }
  2512. }
  2513. \SHAR\EOF\
  2514. else
  2515.   echo "will not over write ./range.c"
  2516. fi
  2517. if [ `wc -c ./range.c | awk '{printf $1}'` -ne 5412 ]
  2518. then
  2519. echo `wc -c ./range.c | awk '{print "Got " $1 ", Expected " 5412}'`
  2520. fi
  2521. if `test ! -s ./eres.sed`
  2522. then
  2523. echo "Extracting ./eres.sed"
  2524. cat > ./eres.sed << '\SHAR\EOF\'
  2525. /%token.*K_/!d
  2526. /%token.*K_\(.*\)/s//    "\1",    K_\1,/
  2527. \SHAR\EOF\
  2528. else
  2529.   echo "will not over write ./eres.sed"
  2530. fi
  2531. if [ `wc -c ./eres.sed | awk '{printf $1}'` -ne 50 ]
  2532. then
  2533. echo `wc -c ./eres.sed | awk '{print "Got " $1 ", Expected " 50}'`
  2534. fi
  2535. if `test ! -s ./sres.sed`
  2536. then
  2537. echo "Extracting ./sres.sed"
  2538. cat > ./sres.sed << '\SHAR\EOF\'
  2539. /%token.*S_/!d
  2540. /%token.*S_\(.*\)/s//    "\1",    S_\1,/
  2541. \SHAR\EOF\
  2542. else
  2543.   echo "will not over write ./sres.sed"
  2544. fi
  2545. if [ `wc -c ./sres.sed | awk '{printf $1}'` -ne 50 ]
  2546. then
  2547. echo `wc -c ./sres.sed | awk '{print "Got " $1 ", Expected " 50}'`
  2548. fi
  2549. if `test ! -s ./Makefile`
  2550. then
  2551. echo "Extracting ./Makefile"
  2552. cat > ./Makefile << '\SHAR\EOF\'
  2553.  
  2554. # Specify the name of the program.
  2555. # All documentation and installation keys on this value.
  2556. name=sc
  2557. NAME=SC
  2558.  
  2559. # This is where the install step puts it.
  2560. EXDIR=/a/rgb/bin
  2561.  
  2562. # This is where the man page goes.
  2563. MANDIR=/usr/man/man1
  2564.  
  2565. # All of the source files
  2566. SRC=sc.h sc.c lex.c gram.y interp.c cmds.c crypt.c xmalloc.c range.c eres.sed\
  2567.     sres.sed Makefile cvt.sed psc.c
  2568.  
  2569. # The documents in the Archive
  2570. DOCS=README sc.doc psc.doc tutorial.sc
  2571.  
  2572. # Set SIMPLE for lex.c if you don't want arrow keys or lex.c blows up
  2573. #SIMPLE=-DSIMPLE
  2574.  
  2575. # Use this for system V.2
  2576. #CFLAGS= -O -DSYSV2
  2577. #LDFLAGS=
  2578. #LIB=-lm -lcurses
  2579.  
  2580. # Use this for system V.3
  2581. #CFLAGS= -O -DSYSV3
  2582. #LDFLAGS=
  2583. #LIB=-lm -lcurses
  2584.  
  2585. # Use this for BSD 4.2
  2586. #CFLAGS= -O -DBSD42
  2587. #LDFLAGS=
  2588. #LIB=-lm -lcurses -ltermcap
  2589.  
  2590. # Use this for BSD 4.3
  2591. CFLAGS= -O -DBSD43
  2592. LDFLAGS=
  2593. LIB=-lm -lcurses -ltermcap
  2594.  
  2595. # Use this for system III (XENIX)
  2596. #CFLAGS= -O -DSYSIII
  2597. #LDFLAGS= -i
  2598. #LIB=-lm -lcurses -ltermcap
  2599.  
  2600. # Use this for VENIX
  2601. #CFLAGS= -DVENIX -DBSD42 -DV7
  2602. #LDFLAGS= -z -i 
  2603. #LIB=-lm -lcurses -ltermcap
  2604.  
  2605. # The objects
  2606. OBJS=sc.o lex.o gram.o interp.o cmds.o crypt.o xmalloc.o range.o
  2607.  
  2608. $(name):    $(OBJS)
  2609.     cc ${CFLAGS} ${LDFLAGS} ${OBJS} ${LIB} -o $(name)
  2610.  
  2611. diff_to_sc:    diff_to_sc.c
  2612.     cc ${CFLAGS} -o dtv diff_to_sc.c
  2613.  
  2614. p$(name):    psc.c
  2615.     cc ${CFLAGS} -o p$(name) psc.c
  2616.     cp p$(name) $(EXDIR)/p$(name)
  2617.  
  2618. lex.o:    sc.h y.tab.h gram.o
  2619.     cc ${CFLAGS} ${SIMPLE} -c lex.c
  2620.  
  2621. sc.o:    sc.h sc.c
  2622.     cc ${CFLAGS} ${QUICK} -c sc.c
  2623.  
  2624. interp.o:    interp.c sc.h
  2625.  
  2626. gram.o:    sc.h y.tab.h
  2627.  
  2628. cmds.o: cmds.c sc.h
  2629.  
  2630. crypt.o: crypt.c sc.h
  2631.  
  2632. range.o: range.c sc.h
  2633.  
  2634. y.tab.h:    gram.y
  2635.  
  2636. gram.o:    sc.h y.tab.h gram.c
  2637.     cc ${CFLAGS} -c gram.c
  2638.     sed<gram.y >experres.h -f eres.sed;sed < gram.y > statres.h -f sres.sed
  2639.  
  2640. gram.c:    gram.y
  2641.     yacc -d gram.y; mv y.tab.c gram.c
  2642.  
  2643. clean:
  2644.     rm -f *.o *res.h y.tab.h $(name) p$(name) debug core gram.c $(name).1 \
  2645.     $(name).man p$(name).man p$(name).1 y.output
  2646.  
  2647. shar: ${SRC} ${DOCS}
  2648.     shar -c -m 64000 -f shar ${DOCS} ${SRC}
  2649.  
  2650. lint: sc.h sc.c lex.c gram.c interp.c cmds.c crypt.c
  2651.     lint ${CFLAGS} ${SIMPLE} sc.c lex.c gram.c interp.c cmds.c crypt.c \
  2652.     range.c xmalloc.c -lcurses -lm
  2653.  
  2654. print: sc.h gram.y sc.c lex.c interp.c cmds.c crypt.c 
  2655.     prc sc.h gram.y sc.c lex.c interp.c cmds.c crypt.c | lpr
  2656.  
  2657. $(name).1:    sc.doc
  2658.     sed -e s/pname/$(name)/g -e s/PNAME/$(NAME)/g sc.doc >  $(name).1
  2659.  
  2660. $(name).man:    $(name).1
  2661.     nroff -man $(name).1 > $(name).man
  2662.  
  2663. p$(name).1:    psc.doc
  2664.     sed -e s/pname/$(name)/g -e s/PNAME/$(NAME)/g psc.doc >  p$(name).1
  2665.  
  2666. p$(name).man:    p$(name).1
  2667.     nroff -man p$(name).1 > p$(name).man
  2668.  
  2669. install: $(EXDIR)/$(name)
  2670.  
  2671. inst-man: $(MANDIR)/$(name).1
  2672.  
  2673. $(EXDIR)/$(name): $(name)
  2674.     -mv $(EXDIR)/$(name) $(EXDIR)/$(name).old
  2675.     strip $(name)
  2676.     cp $(name) $(EXDIR)
  2677.  
  2678. $(MANDIR)/$(name).1: $(name).1
  2679.     cp $(name).1 $(MANDIR)
  2680.  
  2681. diffs: ${SRC}
  2682.     for i in ${SRC} ;\
  2683.         do \
  2684.         rcsdiff -c $$i ;\
  2685.         done
  2686. \SHAR\EOF\
  2687. else
  2688.   echo "will not over write ./Makefile"
  2689. fi
  2690. if [ `wc -c ./Makefile | awk '{printf $1}'` -ne 2787 ]
  2691. then
  2692. echo `wc -c ./Makefile | awk '{print "Got " $1 ", Expected " 2787}'`
  2693. fi
  2694. if `test ! -s ./cvt.sed`
  2695. then
  2696. echo "Extracting ./cvt.sed"
  2697. cat > ./cvt.sed << '\SHAR\EOF\'
  2698. s!+/\(r.*c.*:r.*c[0-9]*\)!@sum(\1)!
  2699. s/\(r[0-9]*\)\(c[0-9]*\)/\2\1/g
  2700. s/c10/k/g
  2701. s/c11/l/g
  2702. s/c12/m/g
  2703. s/c13/n/g
  2704. s/c14/o/g
  2705. s/c15/p/g
  2706. s/c16/q/g
  2707. s/c17/r/g
  2708. s/c18/s/g
  2709. s/c19/t/g
  2710. s/c20/u/g
  2711. s/c21/v/g
  2712. s/c22/w/g
  2713. s/c23/x/g
  2714. s/c24/y/g
  2715. s/c25/z/g
  2716. s/c26/aa/g
  2717. s/c27/ab/g
  2718. s/c28/ac/g
  2719. s/c29/ad/g
  2720. s/c30/ae/g
  2721. s/c31/af/g
  2722. s/c32/ag/g
  2723. s/c33/ah/g
  2724. s/c34/ai/g
  2725. s/c35/aj/g
  2726. s/c36/ak/g
  2727. s/c37/al/g
  2728. s/c38/am/g
  2729. s/c39/an/g
  2730. s/c0/a/g
  2731. s/c1/b/g
  2732. s/c2/c/g
  2733. s/c3/d/g
  2734. s/c4/e/g
  2735. s/c5/f/g
  2736. s/c6/g/g
  2737. s/c7/h/g
  2738. s/c8/i/g
  2739. s/c9/j/g
  2740. s/r\([0-9][0-9]*\)/\1/g
  2741. s/format 10/format k/g
  2742. s/format 11/format l/g
  2743. s/format 12/format m/g
  2744. s/format 13/format n/g
  2745. s/format 14/format o/g
  2746. s/format 15/format p/g
  2747. s/format 16/format q/g
  2748. s/format 17/format r/g
  2749. s/format 18/format s/g
  2750. s/format 19/format t/g
  2751. s/format 20/format u/g
  2752. s/format 21/format v/g
  2753. s/format 22/format w/g
  2754. s/format 23/format x/g
  2755. s/format 24/format y/g
  2756. s/format 25/format z/g
  2757. s/format 26/format aa/g
  2758. s/format 27/format ab/g
  2759. s/format 28/format ac/g
  2760. s/format 29/format ad/g
  2761. s/format 30/format ae/g
  2762. s/format 31/format af/g
  2763. s/format 32/format ag/g
  2764. s/format 33/format ah/g
  2765. s/format 34/format ai/g
  2766. s/format 35/format aj/g
  2767. s/format 36/format ak/g
  2768. s/format 37/format al/g
  2769. s/format 38/format am/g
  2770. s/format 39/format an/g
  2771. s/format 0/format a/g
  2772. s/format 1/format b/g
  2773. s/format 2/format c/g
  2774. s/format 3/format d/g
  2775. s/format 4/format e/g
  2776. s/format 5/format f/g
  2777. s/format 6/format g/g
  2778. s/format 7/format h/g
  2779. s/format 8/format i/g
  2780. s/format 9/format j/g
  2781. \SHAR\EOF\
  2782. else
  2783.   echo "will not over write ./cvt.sed"
  2784. fi
  2785. if [ `wc -c ./cvt.sed | awk '{printf $1}'` -ne 1420 ]
  2786. then
  2787. echo `wc -c ./cvt.sed | awk '{print "Got " $1 ", Expected " 1420}'`
  2788. fi
  2789. if `test ! -s ./psc.c`
  2790. then
  2791. echo "Extracting ./psc.c"
  2792. cat > ./psc.c << '\SHAR\EOF\'
  2793. /* Sc parse routine
  2794.  *
  2795.  * usage psc options
  2796.  * options:
  2797.  *   -L        Left justify strings.  Default is right justify.
  2798.  *   -r        Assemble data into rows first, not columns.
  2799.  *   -R    n    Increment by n between rows 
  2800.  *   -C n    Increment by n between columns
  2801.  *   -n n    Length of the row (column) should be n.
  2802.  *   -s v    Top left location in the spreadsheet should be v; eg, k5
  2803.  *   -d c       Use c as the delimiter between the fields.
  2804.  *   -k         Keep all delimiters - Default is strip multiple delimiters to 1.
  2805.  *   
  2806.  *  Author: Robert Bond
  2807.  */
  2808.  
  2809. #include <ctype.h>
  2810. #include <stdio.h>
  2811. #include "sc.h"
  2812.  
  2813. #define END 0
  2814. #define NUM 1
  2815. #define ALPHA 2
  2816. #define SPACE 3
  2817. #define EOL 4
  2818.  
  2819. extern char *optarg;
  2820. extern int   optind;
  2821. char *coltoa();
  2822. char *progname;
  2823.  
  2824. int colfirst = 0;
  2825. int r0 = 0;
  2826. int c0 = 0;
  2827. int rinc = 1;
  2828. int cinc = 1;
  2829. int leftadj = 0;
  2830. int len = 20000;
  2831. char delim1 = ' ';
  2832. char delim2 = '\t';
  2833. int strip_delim = 1;
  2834. int fwidth[MAXCOLS];
  2835. int precision[MAXCOLS];
  2836.  
  2837. char token[1000];
  2838.  
  2839. main(argc, argv)
  2840. int argc;
  2841. char **argv;
  2842. {
  2843.     int curlen;
  2844.     int curcol, coff;
  2845.     int currow, roff;
  2846.     int first;
  2847.     int c;
  2848.     register effr, effc;
  2849.     int i,j;
  2850.     register char *p;
  2851.  
  2852.     progname = argv[0];
  2853.     while ((c = getopt(argc, argv, "rLks:R:C:n:d:")) != EOF) {
  2854.     switch(c) {
  2855.     case 'r':
  2856.         colfirst = 1;
  2857.         break;
  2858.     case 'L':
  2859.         leftadj = 1;
  2860.         break;
  2861.     case 's':
  2862.         c0 = getcol(optarg);
  2863.         r0 = getrow(optarg);
  2864.         break;
  2865.     case 'R':
  2866.         rinc = atoi(optarg);
  2867.         break;
  2868.     case 'C':
  2869.         cinc = atoi(optarg);
  2870.         break;
  2871.     case 'n':
  2872.         len = atoi(optarg);
  2873.         break;
  2874.     case 'd':
  2875.         delim1 = optarg[0];
  2876.         delim2 = 0;
  2877.         break;
  2878.     case 'k':
  2879.         strip_delim = 0;
  2880.         break;
  2881.     default:
  2882.         (void) fprintf(stderr,"Usage: %s [-rkL] [-s v] [-R i] [-C i] [-n i] [-d c]\n", progname);
  2883.         exit(1);
  2884.         }
  2885.     }
  2886.  
  2887.     if (optind < argc) {
  2888.         (void) fprintf(stderr,"Usage: %s [-rL] [-s v] [-R i] [-C i] [-n i] [-d c]\n", progname);
  2889.         exit(1);
  2890.     }
  2891.  
  2892.     curlen = 0;
  2893.     curcol = c0; coff = 0;
  2894.     currow = r0; roff = 0;
  2895.     first = 1;
  2896.  
  2897.     while(1) {
  2898.  
  2899.     effr = currow+roff;
  2900.     effc = curcol+coff;
  2901.  
  2902.     switch(scan()) {
  2903.     case END:
  2904.         for (i = 0; i<MAXCOLS; i++) {
  2905.         if (precision[i])
  2906.             (void) printf("format %s %d %d\n", coltoa(i), precision[i]+1,
  2907.             fwidth[i]);
  2908.         }
  2909.         exit(0);
  2910.     case NUM:
  2911.         first = 0;
  2912.         (void) printf("let %s%d = %s\n", coltoa(effc), effr, token);
  2913.         if (effc > MAXCOLS-1)
  2914.         (void) fprintf(stderr, "Invalid column used: %s\n", coltoa(effc));
  2915.         else {
  2916.         i = 0;
  2917.         j = 0;
  2918.         p = token;
  2919.         while (*p && *p != '.') {
  2920.             p++; i++;
  2921.         }
  2922.         if (*p) {
  2923.             p++; i++;
  2924.         }
  2925.         while (*p) {
  2926.             p++; i++; j++;
  2927.         }
  2928.         if (precision[effc] < i)
  2929.             precision[effc] = i;
  2930.         if (fwidth[effc] < j)
  2931.             fwidth[effc] = j;
  2932.         }
  2933.         break;
  2934.     case ALPHA:
  2935.         first = 0;
  2936.         if (leftadj)
  2937.         (void) printf("leftstring %s%d = \"%s\"\n", coltoa(effc),effr,token); 
  2938.         else
  2939.         (void) printf("rightstring %s%d = \"%s\"\n",coltoa(effc),effr,token); 
  2940.         if (effc > MAXCOLS-1)
  2941.         (void) fprintf(stderr, "Invalid column used: %s\n", coltoa(effc));
  2942.         else {
  2943.         i = strlen(token);
  2944.         if (i > precision[effc])
  2945.             precision[effc] = i;
  2946.         }
  2947.         break;
  2948.     case SPACE:
  2949.         if (first && strip_delim)
  2950.         break;
  2951.         if (colfirst)
  2952.         roff++;
  2953.         else
  2954.         coff++;
  2955.         break;
  2956.     case EOL:
  2957.         curlen++;
  2958.         roff = 0;
  2959.         coff = 0;
  2960.         first = 1;
  2961.         if (colfirst) {
  2962.         if (curlen >= len) {
  2963.             curcol = c0;
  2964.             currow += rinc;
  2965.             curlen = 0;
  2966.         } else {
  2967.             curcol += cinc;
  2968.         }
  2969.         } else {
  2970.         if (curlen >= len) {
  2971.             currow = r0;
  2972.             curcol += cinc;
  2973.             curlen = 0;
  2974.         } else {
  2975.             currow += rinc;
  2976.         }
  2977.         }
  2978.         break;
  2979.     }
  2980.     }
  2981. }
  2982.  
  2983. scan()
  2984. {
  2985.     register int c;
  2986.     register char *p;
  2987.  
  2988.     p = token;
  2989.     c = getchar();
  2990.  
  2991.     if (c == EOF)
  2992.     return(END);
  2993.  
  2994.     if (c == '\n')
  2995.     return(EOL);
  2996.  
  2997.     if (c == delim1 || c == delim2) {
  2998.         if (strip_delim) {
  2999.         while ((c = getchar()) && (c == delim1 || c == delim2))
  3000.             ;
  3001.         (void)ungetc(c, stdin);
  3002.     } 
  3003.     return(SPACE);
  3004.     }
  3005.  
  3006.     if (c == '\"') {
  3007.     while ((c = getchar()) && c != '\"' && c != '\n' && c != EOF)
  3008.         *p++ = c;
  3009.     if (c != '\"')
  3010.         (void)ungetc(c, stdin);
  3011.     *p = 0;
  3012.     return(ALPHA);
  3013.     }
  3014.  
  3015.     while (c != delim1 && c != delim2 && c!= '\n' && c != EOF) {
  3016.     *p++ = c;
  3017.     c = getchar();
  3018.     }
  3019.     *p = 0;
  3020.     (void)ungetc(c, stdin);
  3021.  
  3022.     p = token;
  3023.     c = *p;
  3024.     if (isdigit(c) || c == '.' || c == '-' || c == '+') {
  3025.     while(isdigit(c) || c == '.' || c == '-' || c == '+' || c == 'e'
  3026.         || c == 'E') {
  3027.         c = *p++;
  3028.     }
  3029.     if (c == 0)
  3030.         return(NUM);
  3031.     else
  3032.         return(ALPHA);
  3033.     }
  3034.  
  3035.     return(ALPHA);
  3036. }
  3037.     
  3038. getcol(p)
  3039. char *p;
  3040. {
  3041.     register  col;
  3042.  
  3043.     if (!p)
  3044.     return(0);
  3045.     while(*p && !isalpha(*p)) 
  3046.     p++; 
  3047.     if (!*p)
  3048.     return(0);
  3049.     col = ((*p & 0137) - 'A');
  3050.     if (isalpha(*++p)) 
  3051.     col = (col + 1)*26 + ((*p & 0137) - 'A');
  3052.     return(col);
  3053. }
  3054.  
  3055. getrow(p)
  3056. char *p;
  3057. {
  3058.     int row;
  3059.  
  3060.     if (!p)
  3061.     return(0);
  3062.     while(*p && !isdigit(*p))
  3063.     p++; 
  3064.     if (!*p)
  3065.     return(0);
  3066.     if (sscanf(p, "%d", &row) != 1)
  3067.     return(0);
  3068.     return(row);
  3069. }
  3070.  
  3071. char *
  3072. coltoa(col)
  3073. int col;
  3074. {
  3075.     static char rname[3];
  3076.     register char *p = rname;
  3077.  
  3078.     if (col < 0 || col > 25*26) 
  3079.     (void) fprintf(stderr,"coltoa: invalid col: %d", col);
  3080.  
  3081.     if (col > 25) {
  3082.     *p++ = col/26 + 'A' - 1;
  3083.     col %= 26;
  3084.     }
  3085.     *p++ = col+'A';
  3086.     *p = 0;
  3087.     return(rname);
  3088. }
  3089.  
  3090. \SHAR\EOF\
  3091. else
  3092.   echo "will not over write ./psc.c"
  3093. fi
  3094. if [ `wc -c ./psc.c | awk '{printf $1}'` -ne 5321 ]
  3095. then
  3096. echo `wc -c ./psc.c | awk '{print "Got " $1 ", Expected " 5321}'`
  3097. fi
  3098. echo "Finished archive 3 of 3"
  3099. # if you want to concatenate archives, remove anything after this line
  3100. exit
  3101.