home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume11 / sc4.1 / part01 next >
Encoding:
Text File  |  1987-08-17  |  48.8 KB  |  2,338 lines

  1. Path: uunet!rs
  2. From: rs@uunet.UU.NET (Rich Salz)
  3. Newsgroups: comp.sources.unix
  4. Subject: v11i017:  Spread sheet program, sc 4.1, Part01/03
  5. Message-ID: <997@uunet.UU.NET>
  6. Date: 18 Aug 87 22:51:37 GMT
  7. Organization: UUNET Communications Services, Arlington, VA
  8. Lines: 2327
  9. Approved: rs@uunet.UU.NET
  10.  
  11. Submitted-by: Robert Bond <rgb@nscpdc.nsc.com>
  12. Posting-number: Volume 11, Issue 17
  13. Archive-name: sc4.1/Part01
  14.  
  15. This is release 4.1 of the spread sheet calculator SC.  Unpack the
  16. three archives and check out the README file for details.
  17.  
  18.                     Bob Bond
  19.  
  20. # This is a shell archive.  Remove anything before this line
  21. # then unpack it by saving it in a file and typing "sh file"
  22. # (Files unpacked will be owned by you and have default permissions).
  23. # This archive contains the following files:
  24. #    ./gram.y
  25. #    ./interp.c
  26. #    ./cmds.c
  27. #    ./crypt.c
  28. #    ./xmalloc.c
  29. #    ./range.c
  30. #    ./eres.sed
  31. #    ./sres.sed
  32. #    ./makefile
  33. #    ./cvt.sed
  34. #
  35. if `test ! -s ./gram.y`
  36. then
  37. echo "writing ./gram.y"
  38. cat > ./gram.y << '\SHAR\EOF\'
  39. /*    SC    A Spreadsheet Calculator
  40.  *        Command and expression parser
  41.  *
  42.  *        original by James Gosling, September 1982
  43.  *        modified by Mark Weiser and Bruce Israel,
  44.  *            University of Maryland
  45.  *
  46.  *         more mods Robert Bond 12/86
  47.  *
  48.  */
  49.  
  50.  
  51.  
  52. %{
  53. #include <curses.h>
  54. #include "sc.h"
  55. %}
  56.  
  57. %union {
  58.     int ival;
  59.     double fval;
  60.     struct ent *ent;
  61.     struct enode *enode;
  62.     char *sval;
  63.     RANGE_S rval;
  64. }
  65.  
  66. %type <ent> var
  67. %type <fval> num
  68. %type <rval> range
  69. %type <enode> e term
  70. %token <sval> STRING
  71. %token <ival> NUMBER
  72. %token <fval> FNUMBER
  73. %token <rval> RANGE
  74. %token <sval> WORD
  75. %token <ival> COL
  76. %token S_FORMAT
  77. %token S_LABEL
  78. %token S_LEFTSTRING
  79. %token S_RIGHTSTRING
  80. %token S_GET
  81. %token S_PUT
  82. %token S_MERGE
  83. %token S_LET
  84. %token S_WRITE
  85. %token S_TBL
  86. %token S_COPY
  87. %token S_SHOW
  88. %token S_ERASE
  89. %token S_FILL
  90. %token S_GOTO
  91. %token S_DEFINE
  92. %token S_UNDEFINE
  93.  
  94. %token K_FIXED
  95. %token K_SUM
  96. %token K_PROD
  97. %token K_AVG
  98. %token K_STDDEV
  99. %token K_ACOS
  100. %token K_ASIN
  101. %token K_ATAN
  102. %token K_CEIL
  103. %token K_COS
  104. %token K_EXP
  105. %token K_FABS
  106. %token K_FLOOR
  107. %token K_HYPOT
  108. %token K_LN
  109. %token K_LOG
  110. %token K_PI
  111. %token K_POW
  112. %token K_SIN
  113. %token K_SQRT
  114. %token K_TAN
  115. %token K_DTR
  116. %token K_RTD
  117. %token K_MAX
  118. %token K_MIN
  119. %token K_RND
  120.  
  121. %left '?' ':'
  122. %left '|'
  123. %left '&'
  124. %nonassoc '<' '=' '>'
  125. %left '+' '-'
  126. %left '*' '/'
  127. %left '^'
  128.  
  129. %%
  130. command:    S_LET var '=' e    { let ($2, $4); }
  131.     |    S_LABEL var '=' STRING
  132.                 { label ($2, $4, 0); }
  133.     |    S_LEFTSTRING var '=' STRING
  134.                 { label ($2, $4, -1); }
  135.     |    S_RIGHTSTRING var '=' STRING
  136.                 { label ($2, $4, 1); }
  137.     |    S_FORMAT COL ':' COL NUMBER NUMBER
  138.                 { int i;
  139.                   for(i = $2; i<=$4; i++)
  140.                       fwidth[i] = $5, precision[i] = $6;
  141.                   FullUpdate++;
  142.                   modflg++;}
  143.     |    S_FORMAT COL NUMBER NUMBER
  144.                 { fwidth[$2] = $3;
  145.                   FullUpdate++;
  146.                   modflg++;
  147.                   precision[$2] = $4; }
  148.     |    S_GET STRING    { readfile ($2,1); }
  149.     |    S_MERGE STRING    { readfile ($2,0); }
  150.     |    S_PUT STRING    { (void) writefile ($2); }
  151.     |    S_WRITE STRING    { printfile ($2); }
  152.     |    S_TBL STRING    { tblprintfile ($2); }
  153.     |       S_SHOW COL ':' COL  { showcol( $2, $4); }
  154.     |       S_SHOW NUMBER ':' NUMBER  { showrow( $2, $4); }
  155.     |    S_COPY var range { copy($2, $3.left, $3.right); }
  156.     |    S_ERASE range { eraser($2.left, $2.right); }
  157.     |    S_FILL range num num { fill($2.left, $2.right, $3, $4); }
  158.     |    S_GOTO var     {moveto($2); }
  159.     |    S_DEFINE STRING range { add_range($2, $3.left, $3.right); }
  160.     |    S_DEFINE STRING var { add_range($2, $3, $3); }
  161.     |    S_UNDEFINE range { del_range($2.left, $2.right); }
  162.     |    /* nothing */
  163.     |    error;
  164.  
  165. term:         var        { $$ = new_var('v', $1); }
  166.     |    K_FIXED term    { $$ = new ('f', (struct enode *)0, $2); }
  167.     |       '@' K_SUM '(' range ')' 
  168.                 { $$ = new (O_REDUCE('+'),
  169.                 (struct enode *)$4.left,
  170.                 (struct enode *)$4.right); }
  171.     |       '@' K_PROD '(' range ')' 
  172.                 { $$ = new (O_REDUCE('*'),
  173.                 (struct enode *)$4.left,
  174.                 (struct enode *)$4.right); }
  175.     |       '@' K_AVG '(' range ')' 
  176.                 { $$ = new (O_REDUCE('a'),
  177.                 (struct enode *)$4.left,
  178.                 (struct enode *)$4.right); }
  179.     |       '@' K_STDDEV '(' range ')' 
  180.                 { $$ = new (O_REDUCE('s'),
  181.                 (struct enode *)$4.left,
  182.                 (struct enode *)$4.right); }
  183.     |       '@' K_MAX '(' range ')' 
  184.                 { $$ = new (O_REDUCE(MAX),
  185.                 (struct enode *)$4.left,
  186.                 (struct enode *)$4.right); }
  187.     |       '@' K_MIN '(' range ')' 
  188.                 { $$ = new (O_REDUCE(MIN),
  189.                 (struct enode *)$4.left,
  190.                 (struct enode *)$4.right); }
  191.     | '@' K_ACOS '(' e ')'    { $$ = new(ACOS, (struct enode *)0, $4); }
  192.     | '@' K_ASIN '(' e ')'    { $$ = new(ASIN, (struct enode *)0, $4); }
  193.     | '@' K_ATAN '(' e ')'    { $$ = new(ATAN, (struct enode *)0, $4); }
  194.     | '@' K_CEIL '(' e ')'    { $$ = new(CEIL, (struct enode *)0, $4); }
  195.     | '@' K_COS '(' e ')'    { $$ = new(COS, (struct enode *)0, $4); }
  196.     | '@' K_EXP '(' e ')'    { $$ = new(EXP, (struct enode *)0, $4); }
  197.     | '@' K_FABS '(' e ')'    { $$ = new(FABS, (struct enode *)0, $4); }
  198.     | '@' K_FLOOR '(' e ')'    { $$ = new(FLOOR, (struct enode *)0, $4); }
  199.     | '@' K_HYPOT '(' e ',' e ')'    { $$ = new(HYPOT, $4, $6); }
  200.     | '@' K_LN '(' e ')'    { $$ = new(LOG, (struct enode *)0, $4); }
  201.     | '@' K_LOG '(' e ')'    { $$ = new(LOG10, (struct enode *)0, $4); }
  202.     | '@' K_POW '(' e ',' e ')'    { $$ = new(POW, $4, $6); }
  203.     | '@' K_SIN '(' e ')'    { $$ = new(SIN, (struct enode *)0, $4); }
  204.     | '@' K_SQRT '(' e ')'    { $$ = new(SQRT, (struct enode *)0, $4); }
  205.     | '@' K_TAN '(' e ')'    { $$ = new(TAN, (struct enode *)0, $4); }
  206.     | '@' K_DTR '(' e ')'    { $$ = new(DTR, (struct enode *)0, $4); }
  207.     | '@' K_RTD '(' e ')'    { $$ = new(RTD, (struct enode *)0, $4); }
  208.     | '@' K_RND '(' e ')'    { $$ = new(RND, (struct enode *)0, $4); }
  209.     |    '(' e ')'    { $$ = $2; }
  210.     |    '+' term    { $$ = $2; }
  211.     |    '-' term    { $$ = new ('m', (struct enode *)0, $2); }
  212.     |    NUMBER        { $$ = new_const('k', (double) $1); }
  213.     |    FNUMBER        { $$ = new_const('k', $1); }
  214.     |    K_PI    { $$ = new_const('k', (double)3.14159265358979323846); }
  215.     |    '~' term    { $$ = new ('~', (struct enode *)0, $2); }
  216.     |    '!' term    { $$ = new ('~', (struct enode *)0, $2); }
  217.     ;
  218.  
  219. e:        e '+' e        { $$ = new ('+', $1, $3); }
  220.     |    e '-' e        { $$ = new ('-', $1, $3); }
  221.     |    e '*' e        { $$ = new ('*', $1, $3); }
  222.     |    e '/' e        { $$ = new ('/', $1, $3); }
  223.     |    e '^' e        { $$ = new ('^', $1, $3); }
  224.     |    term
  225.     |    e '?' e ':' e    { $$ = new ('?', $1, new(':', $3, $5)); }
  226.     |    e '<' e        { $$ = new ('<', $1, $3); }
  227.     |    e '=' e        { $$ = new ('=', $1, $3); }
  228.     |    e '>' e        { $$ = new ('>', $1, $3); }
  229.     |    e '&' e        { $$ = new ('&', $1, $3); }
  230.     |    e '|' e        { $$ = new ('|', $1, $3); }
  231.     |    e '<' '=' e    { $$ = new ('~', (struct enode *)0,
  232.                         new ('>', $1, $4)); }
  233.     |    e '!' '=' e    { $$ = new ('~', (struct enode *)0, 
  234.                         new ('=', $1, $4)); }
  235.     |    e '>' '=' e    { $$ = new ('~', (struct enode *)0, 
  236.                         new ('<', $1, $4)); }
  237.     ;
  238.  
  239. range:        var ':' var    { $$.left = $1;
  240.                   $$.right = $3; }
  241.     |     RANGE        { $$ = $1; }
  242.     ;
  243.  
  244. var:        COL NUMBER    { $$ = lookat($2 , $1); }
  245.     |    RANGE        { $$ = $1.left; }
  246.     ;
  247.  
  248. num:        NUMBER        { $$ = (double) $1; }
  249.     |    FNUMBER        { $$ = $1; }
  250.     |    '-' num        { $$ = -$2; }
  251.     |    '+' num        { $$ = $2; }
  252.     ;
  253. \SHAR\EOF\
  254. else
  255.   echo "will not over write ./gram.y"
  256. fi
  257. if [ `wc -c ./gram.y | awk '{printf $1}'` -ne 5891 ]
  258. then
  259. echo `wc -c ./gram.y | awk '{print "Got " $1 ", Expected " 5891}'`
  260. fi
  261. if `test ! -s ./interp.c`
  262. then
  263. echo "writing ./interp.c"
  264. cat > ./interp.c << '\SHAR\EOF\'
  265. /*    SC    A Spreadsheet Calculator
  266.  *        Expression interpreter and assorted support routines.
  267.  *
  268.  *        original by James Gosling, September 1982
  269.  *        modified by Mark Weiser and Bruce Israel, 
  270.  *            University of Maryland
  271.  *
  272.  *              More mods Robert Bond, 12/86
  273.  */
  274.  
  275. #include <math.h>
  276. #include <stdio.h>
  277.  
  278. #ifdef BSD42
  279. #include <strings.h>
  280. #else
  281. #ifndef SYSIII
  282. #include <string.h>
  283. #endif
  284. #endif
  285.  
  286. #include <curses.h>
  287. #include "sc.h"
  288. #define DEFCOLDELIM ':'
  289.  
  290. char *xmalloc();
  291. #define PI (double)3.14159265358979323846
  292. #define dtr(x) ((x)*(PI/(double)180.0))
  293. #define rtd(x) ((x)*(180.0/(double)PI))
  294.  
  295. double dosum(minr, minc, maxr, maxc)
  296. int minr, minc, maxr, maxc;
  297. {
  298.     double v;
  299.     register r,c;
  300.     register struct ent *p;
  301.  
  302.     v = 0;
  303.     for (r = minr; r<=maxr; r++)
  304.     for (c = minc; c<=maxc; c++)
  305.         if ((p = tbl[r][c]) && p->flags&is_valid)
  306.         v += p->v;
  307.     return v;
  308. }
  309.  
  310. double doprod(minr, minc, maxr, maxc)
  311. int minr, minc, maxr, maxc;
  312. {
  313.     double v;
  314.     register r,c;
  315.     register struct ent *p;
  316.  
  317.     v = 1;
  318.     for (r = minr; r<=maxr; r++)
  319.     for (c = minc; c<=maxc; c++)
  320.         if ((p = tbl[r][c]) && p->flags&is_valid)
  321.         v *= p->v;
  322.     return v;
  323. }
  324.  
  325. double doavg(minr, minc, maxr, maxc)
  326. int minr, minc, maxr, maxc;
  327. {
  328.     double v;
  329.     register r,c,count;
  330.     register struct ent *p;
  331.  
  332.     v = 0;
  333.     count = 0;
  334.     for (r = minr; r<=maxr; r++)
  335.     for (c = minc; c<=maxc; c++)
  336.         if ((p = tbl[r][c]) && p->flags&is_valid) {
  337.         v += p->v;
  338.         count++;
  339.         }
  340.  
  341.     if (count == 0) 
  342.     return ((double) 0);
  343.  
  344.     return (v / (double)count);
  345. }
  346.  
  347. double dostddev(minr, minc, maxr, maxc)
  348. int minr, minc, maxr, maxc;
  349. {
  350.     double lp, rp, v, nd;
  351.     register r,c,n;
  352.     register struct ent *p;
  353.  
  354.     n = 0;
  355.     lp = 0;
  356.     rp = 0;
  357.     for (r = minr; r<=maxr; r++)
  358.     for (c = minc; c<=maxc; c++)
  359.         if ((p = tbl[r][c]) && p->flags&is_valid) {
  360.         v = p->v;
  361.         lp += v*v;
  362.         rp += v;
  363.         n++;
  364.         }
  365.  
  366.     if ((n == 0) || (n == 1)) 
  367.     return ((double) 0);
  368.     nd = (double)n;
  369.     return (sqrt((nd*lp-rp*rp)/(nd*(nd-1))));
  370. }
  371.  
  372. double domax(minr, minc, maxr, maxc)
  373. int minr, minc, maxr, maxc;
  374. {
  375.     double v;
  376.     register r,c,count;
  377.     register struct ent *p;
  378.  
  379.     count = 0;
  380.     for (r = minr; r<=maxr; r++)
  381.     for (c = minc; c<=maxc; c++)
  382.         if ((p = tbl[r][c]) && p->flags&is_valid) {
  383.         if (!count) {
  384.             v = p->v;
  385.             count++;
  386.         } else if (p->v > v)
  387.             v = p->v;
  388.         }
  389.  
  390.     if (count == 0) 
  391.     return ((double) 0);
  392.  
  393.     return (v);
  394. }
  395.  
  396. double domin(minr, minc, maxr, maxc)
  397. int minr, minc, maxr, maxc;
  398. {
  399.     double v;
  400.     register r,c,count;
  401.     register struct ent *p;
  402.  
  403.     count = 0;
  404.     for (r = minr; r<=maxr; r++)
  405.     for (c = minc; c<=maxc; c++)
  406.         if ((p = tbl[r][c]) && p->flags&is_valid) {
  407.         if (!count) {
  408.             v = p->v;
  409.             count++;
  410.         } else if (p->v < v)
  411.             v = p->v;
  412.         }
  413.  
  414.     if (count == 0) 
  415.     return ((double) 0);
  416.  
  417.     return (v);
  418. }
  419.  
  420. double eval(e)
  421. register struct enode *e; {
  422.     if (e==0) return 0;
  423.     switch (e->op) {
  424.     case '+':    return (eval(e->e.o.left) + eval(e->e.o.right));
  425.     case '-':    return (eval(e->e.o.left) - eval(e->e.o.right));
  426.     case '*':    return (eval(e->e.o.left) * eval(e->e.o.right));
  427.     case '/':     {    double denom = eval (e->e.o.right);
  428.             return denom ? eval(e->e.o.left) / denom : 0; }
  429.     case '^':    return (pow(eval(e->e.o.left), eval(e->e.o.right)));
  430.     case '<':    return (eval(e->e.o.left) < eval(e->e.o.right));
  431.     case '=':    return (eval(e->e.o.left) == eval(e->e.o.right));
  432.     case '>':    return (eval(e->e.o.left) > eval(e->e.o.right));
  433.     case '&':    return (eval(e->e.o.left) && eval(e->e.o.right));
  434.     case '|':    return (eval(e->e.o.left) || eval(e->e.o.right));
  435.     case '?':    return eval(e->e.o.left) ? eval(e->e.o.right->e.o.left)
  436.                          : eval(e->e.o.right->e.o.right);
  437.     case 'm':    return (-eval(e->e.o.right));
  438.     case 'f':    return (eval(e->e.o.right));
  439.     case '~':    return ((double)!(int)eval(e->e.o.right));
  440.     case 'k':    return (e->e.k);
  441.     case 'v':    return (e->e.v->v);
  442.     case O_REDUCE('+'):
  443.      case O_REDUCE('*'):
  444.      case O_REDUCE('a'):
  445.      case O_REDUCE('s'):
  446.     case O_REDUCE(MAX):
  447.     case O_REDUCE(MIN):
  448.         {    register r,c;
  449.         register maxr, maxc;
  450.         register minr, minc;
  451.         maxr = ((struct ent *) e->e.o.right) -> row;
  452.         maxc = ((struct ent *) e->e.o.right) -> col;
  453.         minr = ((struct ent *) e->e.o.left) -> row;
  454.         minc = ((struct ent *) e->e.o.left) -> col;
  455.         if (minr>maxr) r = maxr, maxr = minr, minr = r;
  456.         if (minc>maxc) c = maxc, maxc = minc, minc = c;
  457.             switch (e->op) {
  458.                 case O_REDUCE('+'): return dosum(minr, minc, maxr, maxc);
  459.                  case O_REDUCE('*'): return doprod(minr, minc, maxr, maxc);
  460.                  case O_REDUCE('a'): return doavg(minr, minc, maxr, maxc);
  461.                  case O_REDUCE('s'): return dostddev(minr, minc, maxr, maxc);
  462.                  case O_REDUCE(MAX): return domax(minr, minc, maxr, maxc);
  463.                  case O_REDUCE(MIN): return domin(minr, minc, maxr, maxc);
  464.         }
  465.         }
  466.     case ACOS:     return (acos(eval(e->e.o.right)));
  467.     case ASIN:     return (asin(eval(e->e.o.right)));
  468.     case ATAN:     return (atan(eval(e->e.o.right)));
  469.     case CEIL:     return (ceil(eval(e->e.o.right)));
  470.     case COS:     return (cos(eval(e->e.o.right)));
  471.     case EXP:     return (exp(eval(e->e.o.right)));
  472.     case FABS:     return (fabs(eval(e->e.o.right)));
  473.     case FLOOR:     return (floor(eval(e->e.o.right)));
  474.     case HYPOT:     return (hypot(eval(e->e.o.left), eval(e->e.o.right)));
  475.     case LOG:     { double arg = eval(e->e.o.right);
  476.                return arg ? log(arg) : 0; }
  477.     case LOG10:     { double arg = eval(e->e.o.right);
  478.                return arg ? log10(arg) : 0; }
  479.     case POW:     return (pow(eval(e->e.o.left), eval(e->e.o.right)));
  480.     case SIN:     return (sin(eval(e->e.o.right)));
  481.     case SQRT:     return (sqrt(eval(e->e.o.right)));
  482.     case TAN:     return (tan(eval(e->e.o.right)));
  483.     case DTR:     return (dtr(eval(e->e.o.right)));
  484.     case RTD:     return (rtd(eval(e->e.o.right)));
  485.     case RND:     {
  486.                 double temp;
  487.                 temp = eval(e->e.o.right);
  488.                 return(temp-floor(temp) < 0.5 ?
  489.                          floor(temp) : ceil(temp));
  490.              }
  491.     }
  492.     return((double) 0.0);     /* safety net */
  493. }
  494.  
  495. #define MAXPROP 7
  496.  
  497. EvalAll () {
  498.     int repct = 0;
  499.  
  500.     while (RealEvalAll() && (repct++ <= MAXPROP));
  501. }
  502.  
  503. int RealEvalAll () {
  504.     register i,j;
  505.     int chgct = 0;
  506.     register struct ent *p;
  507.     for (i=0; i<=maxrow; i++)
  508.     for (j=0; j<=maxcol; j++)
  509.         if ((p=tbl[i][j]) && p->expr) {
  510.         double v = eval (p->expr);
  511.         if (v != p->v) {
  512.             p->v = v; chgct++;
  513.             p->flags |= (is_changed|is_valid);
  514.         }
  515.         }
  516.     return(chgct);
  517. }
  518.  
  519. struct enode *new(op, a1, a2)
  520. struct enode *a1, *a2;
  521. {
  522.     register struct enode *p = (struct enode *) xmalloc ((unsigned)sizeof (struct enode));
  523.     p->op = op;
  524.     p->e.o.left = a1;
  525.     p->e.o.right = a2;
  526.     return p;
  527. }
  528.  
  529. struct enode *new_var(op, a1)
  530. struct ent *a1;
  531. {
  532.     register struct enode *p = (struct enode *) xmalloc ((unsigned)sizeof (struct enode));
  533.     p->op = op;
  534.     p->e.v = a1;
  535.     return p;
  536. }
  537.  
  538. struct enode *new_const(op, a1)
  539. double a1;
  540. {
  541.     register struct enode *p = (struct enode *) xmalloc ((unsigned)sizeof (struct enode));
  542.     p->op = op;
  543.     p->e.k = a1;
  544.     return p;
  545. }
  546.  
  547. copy (dv, v1, v2)
  548. struct ent *dv, *v1, *v2;
  549. {
  550.     register r,c;
  551.     register struct ent *p;
  552.     register struct ent *n;
  553.     register deltar, deltac;
  554.     int maxr, maxc;
  555.     int minr, minc;
  556.     int dr, dc;
  557.  
  558.     dr = dv->row;
  559.     dc = dv->col;
  560.     maxr = v2->row;
  561.     maxc = v2->col;
  562.     minr = v1->row;
  563.     minc = v1->col;
  564.     if (minr>maxr) r = maxr, maxr = minr, minr = r;
  565.     if (minc>maxc) c = maxc, maxc = minc, minc = c;
  566.     if (dr+maxr-minr >= MAXROWS  || 
  567.            dc+maxc-minc >= MAXCOLS) {
  568.     error ("The table can't be any bigger");
  569.     return;
  570.     }
  571.     deltar = dr-minr;
  572.     deltac = dc-minc;
  573.     FullUpdate++;
  574.     for (r = minr; r<=maxr; r++)
  575.     for (c = minc; c<=maxc; c++) {
  576.         n = lookat (r+deltar, c+deltac);
  577.         clearent(n);
  578.         if (p = tbl[r][c]) {
  579.         n -> v = p -> v;
  580.         n -> flags = p -> flags;
  581.         n -> expr = copye(p->expr, deltar, deltac);
  582.         n -> label = 0;
  583.         if (p -> label) {
  584.             n -> label = xmalloc ((unsigned)(strlen (p -> label) + 1));
  585.             strcpy (n -> label, p -> label);
  586.         }
  587.         }
  588.     }
  589. }
  590.  
  591. eraser(v1, v2)
  592. struct ent *v1, *v2;
  593. {
  594.     FullUpdate++;
  595.     flush_saved();
  596.     erase_area(v1->row, v1->col, v2->row, v2->col);
  597.     sync_refs();
  598. }
  599.  
  600. moveto(v)
  601. struct ent *v;
  602. {
  603.     currow = v->row;
  604.     curcol = v->col;
  605. }
  606.  
  607. fill (v1, v2, start, inc)
  608. struct ent *v1, *v2;
  609. double start, inc;
  610. {
  611.     register r,c;
  612.     register struct ent *n;
  613.     int maxr, maxc;
  614.     int minr, minc;
  615.  
  616.     maxr = v2->row;
  617.     maxc = v2->col;
  618.     minr = v1->row;
  619.     minc = v1->col;
  620.     if (minr>maxr) r = maxr, maxr = minr, minr = r;
  621.     if (minc>maxc) c = maxc, maxc = minc, minc = c;
  622.     if (maxr >= MAXROWS) maxr = MAXROWS-1;
  623.     if (maxc >= MAXCOLS) maxc = MAXCOLS-1;
  624.     if (minr < 0) minr = 0;
  625.     if (minr < 0) minr = 0;
  626.  
  627.     FullUpdate++;
  628.     for (r = minr; r<=maxr; r++)
  629.     for (c = minc; c<=maxc; c++) {
  630.         n = lookat (r, c);
  631.         clearent(n);
  632.         n->v = start;
  633.         start += inc;
  634.         n->flags |= (is_changed|is_valid);
  635.     }
  636. }
  637.  
  638. let (v, e)
  639. struct ent *v;
  640. struct enode *e; {
  641.     efree (v->expr);
  642.     if (constant(e)) {
  643.     v->v = eval(e);
  644.     v->expr = 0;
  645.     efree(e);
  646.     } else
  647.     v->expr = e;
  648.     v->flags |= (is_changed|is_valid);
  649.     changed++;
  650.     modflg++;
  651. }
  652.  
  653. clearent (v)
  654. struct ent *v; {
  655.     if (!v)
  656.     return;
  657.     label(v,"",-1);
  658.     v->v = 0;
  659.     if (v->expr)
  660.     efree(v->expr);
  661.     v->expr = 0;
  662.     v->flags |= (is_changed);
  663.     v->flags &= ~(is_valid);
  664.     changed++;
  665.     modflg++;
  666. }
  667.  
  668. constant(e)
  669. register struct enode *e; {
  670.     return e==0 || e->op == O_CONST 
  671.     || (e->op != O_VAR
  672.      && (e->op&~0177) != O_REDUCE(0)
  673.      && constant (e->e.o.left)
  674.      && constant(e->e.o.right));
  675. }
  676.  
  677. efree (e)
  678. register struct enode *e; {
  679.     if (e) {
  680.     if (e->op != O_VAR && e->op !=O_CONST && (e->op&~0177) != O_REDUCE(0)) {
  681.         efree (e->e.o.left);
  682.         efree (e->e.o.right);
  683.     }
  684.     xfree ((char *)e);
  685.     }
  686. }
  687.  
  688. label (v, s, flushdir)
  689. register struct ent *v;
  690. register char *s; {
  691.     if (v) {
  692.     if (flushdir==0 && v->flags&is_valid) {
  693.         register struct ent *tv;
  694.         if (v->col>0 && ((tv=lookat(v->row,v->col-1))->flags&is_valid)==0)
  695.         v = tv, flushdir = 1;
  696.         else if (((tv=lookat (v->row,v->col+1))->flags&is_valid)==0)
  697.         v = tv, flushdir = -1;
  698.         else flushdir = -1;
  699.     }
  700.     if (v->label) xfree((char *)(v->label));
  701.     if (s && s[0]) {
  702.         v->label = xmalloc ((unsigned)(strlen(s)+1));
  703.         strcpy (v->label, s);
  704.     } else v->label = 0;
  705.     v->flags |= is_lchanged;
  706.     if (flushdir<0) v->flags |= is_leftflush;
  707.     else v->flags &= ~is_leftflush;
  708.     FullUpdate++;
  709.     modflg++;
  710.     }
  711. }
  712.  
  713. decodev (v)
  714. register struct ent *v; 
  715. {
  716.     register struct range *r;
  717.  
  718.     if (!v) sprintf (line+linelim,"VAR?");
  719.     else if (r = find_range((char *)0, 0, v, v))
  720.         sprintf(line+linelim, "%s", r->r_name);
  721.     else
  722.         sprintf (line+linelim, "%s%d", coltoa(v->col), v->row);
  723.     linelim += strlen (line+linelim);
  724. }
  725.  
  726. char *
  727. coltoa(col)
  728. int col;
  729. {
  730.     static char rname[3];
  731.     register char *p = rname;
  732.  
  733.     if (col > 25) {
  734.     *p++ = col/26 + 'A' - 1;
  735.     col %= 26;
  736.     }
  737.     *p++ = col+'A';
  738.     *p = 0;
  739.     return(rname);
  740. }
  741.  
  742. decompile(e, priority)
  743. register struct enode *e; {
  744.     register char *s;
  745.     if (e) {
  746.     int mypriority;
  747.     switch (e->op) {
  748.     default: mypriority = 99; break;
  749.     case '?': mypriority = 1; break;
  750.     case ':': mypriority = 2; break;
  751.     case '|': mypriority = 3; break;
  752.     case '&': mypriority = 4; break;
  753.     case '<': case '=': case '>': mypriority = 6; break;
  754.     case '+': case '-': mypriority = 8; break;
  755.     case '*': case '/': mypriority = 10; break;
  756.     case '^': mypriority = 12; break;
  757.     }
  758.     if (mypriority<priority) line[linelim++] = '(';
  759.     switch (e->op) {
  760.     case 'f':    { 
  761.                 for (s="fixed "; line[linelim++] = *s++;);
  762.                 linelim--;
  763.                 decompile (e->e.o.right, 30);
  764.                 break;
  765.             }
  766.     case 'm':    line[linelim++] = '-';
  767.             decompile (e->e.o.right, 30);
  768.             break;
  769.     case '~':    line[linelim++] = '~';
  770.             decompile (e->e.o.right, 30);
  771.             break;
  772.     case 'v':    decodev (e->e.v);
  773.             break;
  774.     case 'k':    sprintf (line+linelim,"%.15g",e->e.k);
  775.             linelim += strlen (line+linelim);
  776.             break;
  777.     case O_REDUCE('+'):
  778.             s = "@sum("; goto more;
  779.     case O_REDUCE('*'):
  780.             s = "@prod("; goto more;
  781.     case O_REDUCE('s'):
  782.             s = "@stddev("; goto more;
  783.     case O_REDUCE(MAX):
  784.             s = "@max("; goto more;
  785.     case O_REDUCE(MIN):
  786.             s = "@min("; goto more;
  787.     case O_REDUCE('a'):
  788.             s = "@avg("; /* fall though to more; */
  789.     more:        {
  790.             struct range *r;
  791.  
  792.             for (; line[linelim++] = *s++;);
  793.             linelim--;
  794.             if (r = find_range((char *)0, 0,
  795.                          (struct ent *) e->e.o.left,
  796.                          (struct ent *) e->e.o.right)) {
  797.                 sprintf(line+linelim, "%s", r->r_name);
  798.                 linelim += strlen(line+linelim);
  799.             } else {
  800.                 decodev ((struct ent *) e->e.o.left);
  801.                 line[linelim++] = ':';
  802.                 decodev ((struct ent *) e->e.o.right);
  803.             }
  804.             line[linelim++] = ')';
  805.             break;
  806.             }
  807.     case ACOS:    s = "@acos("; goto more1;
  808.     case ASIN:    s = "@asin("; goto more1;
  809.     case ATAN:    s = "@atan("; goto more1;
  810.     case CEIL:    s = "@ceil("; goto more1;
  811.     case COS:    s = "@cos("; goto more1;
  812.     case EXP:    s = "@exp("; goto more1;
  813.     case FABS:    s = "@fabs("; goto more1;
  814.     case FLOOR:    s = "@floor("; goto more1;
  815.     case HYPOT:    s = "@hypot("; goto more2;
  816.     case LOG:    s = "@ln("; goto more1;
  817.     case LOG10:    s = "@log("; goto more1;
  818.     case POW:    s = "@pow("; goto more2;
  819.     case SIN:    s = "@sin("; goto more1;
  820.     case SQRT:    s = "@sqrt("; goto more1;
  821.     case TAN:    s = "@tan("; goto more1;
  822.     case DTR:    s = "@dtr("; goto more1;
  823.     case RTD:    s = "@rtd("; goto more1;
  824.     case RND:    s = "@rnd("; goto more1;
  825.     more1:        for (; line[linelim++] = *s++;);
  826.             linelim--;
  827.             decompile (e->e.o.right, 0);
  828.             line[linelim++] = ')';
  829.             break;
  830.     more2:        for (; line[linelim++] = *s++;);
  831.             linelim--;
  832.             decompile (e->e.o.left, 0);
  833.             line[linelim++] = ',';
  834.             decompile (e->e.o.right, 0);
  835.             line[linelim++] = ')';
  836.             break;
  837.  
  838.     default:    decompile (e->e.o.left, mypriority);
  839.             line[linelim++] = e->op;
  840.             decompile (e->e.o.right, mypriority+1);
  841.             break;
  842.     }
  843.     if (mypriority<priority) line[linelim++] = ')';
  844.     } else line[linelim++] = '?';
  845. }
  846.  
  847. editv (row, col) {
  848.     sprintf (line, "let %s = ", v_name(row, col));
  849.     linelim = strlen(line);
  850.     editexp(row,col);
  851. }
  852.  
  853. editexp(row,col) {
  854.     register struct ent *p;
  855.     p = lookat (row, col);
  856.     if (p->flags&is_valid)
  857.     if (p->expr) {
  858.         decompile (p->expr, 0);
  859.         line[linelim] = 0;
  860.     } else {
  861.         sprintf (line+linelim, "%.15g", p->v);
  862.         linelim += strlen (line+linelim);
  863.     }
  864. }
  865.  
  866. edits (row, col) {
  867.     register struct ent *p = lookat (row, col);
  868.     sprintf (line, "%sstring %s = \"",
  869.             ((p->flags&is_leftflush) ? "left" : "right"),
  870.             v_name(row, col));
  871.     linelim = strlen(line);
  872.     if (p->label) {
  873.         sprintf (line+linelim, "%s", p->label);
  874.         linelim += strlen (line+linelim);
  875.     }
  876. }
  877.  
  878. printfile (fname)
  879. char *fname;
  880. {
  881.     FILE *f;
  882.     char pline[1000];
  883.     int plinelim;
  884.     int pid;
  885.     register row, col;
  886.     register struct ent **p;
  887.  
  888.     f = openout(fname, &pid);
  889.  
  890.     if (f==0) {
  891.     error ("Can't create %s", fname);
  892.     return;
  893.     }
  894.     for (row=0;row<=maxrow; row++) {
  895.     register c = 0;
  896.     pline[plinelim=0] = '\0';
  897.     for (p = &tbl[row][col=0]; col<=maxcol; col++, p++) {
  898.         if (*p) {
  899.         char *s;
  900.         while (plinelim<c) pline[plinelim++] = ' ';
  901.         plinelim = c;
  902.         if ((*p)->flags&is_valid) {
  903.             sprintf (pline+plinelim,"%*.*f",fwidth[col],precision[col],
  904.                 (*p)->v);
  905.             plinelim += strlen (pline+plinelim);
  906.         }
  907.         if (s = (*p)->label) {
  908.             register char *d;
  909.             d = pline+((*p)->flags&is_leftflush
  910.             ? c : c-strlen(s)+fwidth[col]);
  911.             while (d>pline+plinelim) pline[plinelim++] = ' ';
  912.             if (d<pline) d = pline;
  913.             while (*s) *d++ = *s++;
  914.             if (d-pline>plinelim) plinelim = d-pline;
  915.         }
  916.         }
  917.         c += fwidth [col];
  918.     }
  919.     fprintf (f,"%.*s\n",plinelim,pline);
  920.     }
  921.  
  922.     closeout(f, pid);
  923. }
  924.  
  925. tblprintfile (fname)
  926. char *fname;
  927. {
  928.     FILE *f;
  929.     char pline[1000];
  930.     int pid;
  931.     register row, col;
  932.     register struct ent **p;
  933.     char coldelim = DEFCOLDELIM;
  934.  
  935.     f = openout(fname, &pid);
  936.  
  937.     if (f==0) {
  938.     error ("Can't create %s", fname);
  939.     return;
  940.     }
  941.     for (row=0;row<=maxrow; row++) {
  942.     for (p = &tbl[row][col=0]; col<=maxcol; col++, p++) {
  943.         if (*p) {
  944.         char *s;
  945.         if ((*p)->flags&is_valid) {
  946.             fprintf (f,"%.*f",precision[col],
  947.                 (*p)->v);
  948.         }
  949.         if (s = (*p)->label) {
  950.                 fprintf (f,"%s",s);
  951.         }
  952.         }
  953.         fprintf(f,"%c",coldelim);
  954.     }
  955.     fprintf (f,"\n",pline);
  956.     }
  957.  
  958.     closeout(f, pid);
  959. }
  960.  
  961. struct enode *copye (e, Rdelta, Cdelta)
  962. register struct enode *e; {
  963.     register struct enode *ret;
  964.     if (e==0) ret = 0;
  965.     else {
  966.     ret = (struct enode *) xmalloc ((unsigned) sizeof (struct enode));
  967.     ret->op = e->op;
  968.     switch (ret->op) {
  969.     case 'v':
  970.         ret->e.v = lookat (e->e.v->row+Rdelta, e->e.v->col+Cdelta);
  971.         break;
  972.     case 'k':
  973.         ret->e.k = e->e.k;
  974.         break;
  975.     case 'f':
  976.         ret->e.o.right = copye (e->e.o.right,0,0);
  977.         ret->e.o.left = 0;
  978.          break;
  979.      case O_REDUCE('+'):
  980.      case O_REDUCE('*'):
  981.      case O_REDUCE('a'):
  982.      case O_REDUCE('s'):
  983.      case O_REDUCE(MAX):
  984.      case O_REDUCE(MIN):
  985.          ret->e.o.right = (struct enode *) lookat (
  986.                    ((struct ent *)e->e.o.right)->row+Rdelta,
  987.                    ((struct ent *)e->e.o.right)->col+Cdelta
  988.             );
  989.          ret->e.o.left = (struct enode *) lookat (
  990.                    ((struct ent *)e->e.o.left)->row+Rdelta,
  991.                    ((struct ent *)e->e.o.left)->col+Cdelta
  992.             );
  993.         break;
  994.     default:
  995.         ret->e.o.right = copye (e->e.o.right,Rdelta,Cdelta);
  996.         ret->e.o.left = copye (e->e.o.left,Rdelta,Cdelta);
  997.         break;
  998.     }
  999.     }
  1000.     return ret;
  1001. }
  1002.  
  1003. /*
  1004.  * sync_refs and syncref are used to remove references to
  1005.  * deleted struct ents.  Note that the deleted structure must still
  1006.  * be hanging around before the call, but not referenced by an entry
  1007.  * in tbl.  Thus the free_ent, fix_ent calls in sc.c
  1008.  */
  1009.  
  1010. sync_refs () {
  1011.     register i,j;
  1012.     register struct ent *p;
  1013.     sync_ranges();
  1014.     for (i=0; i<=maxrow; i++)
  1015.     for (j=0; j<=maxcol; j++)
  1016.         if ((p=tbl[i][j]) && p->expr)
  1017.         syncref(p->expr);
  1018. }
  1019.  
  1020.  
  1021. syncref(e)
  1022. register struct enode *e;
  1023. {
  1024.     if (e==0)
  1025.     return;
  1026.     else {
  1027.     switch (e->op) {
  1028.     case 'v':
  1029.         e->e.v = lookat(e->e.v->row, e->e.v->col);
  1030.         break;
  1031.     case 'k':
  1032.         break;
  1033.      case O_REDUCE('+'):
  1034.      case O_REDUCE('*'):
  1035.      case O_REDUCE('a'):
  1036.      case O_REDUCE('s'):
  1037.      case O_REDUCE(MAX):
  1038.      case O_REDUCE(MIN):
  1039.          e->e.o.right = (struct enode *) lookat (
  1040.                    ((struct ent *)e->e.o.right)->row,
  1041.                    ((struct ent *)e->e.o.right)->col
  1042.             );
  1043.          e->e.o.left = (struct enode *) lookat (
  1044.                    ((struct ent *)e->e.o.left)->row,
  1045.                    ((struct ent *)e->e.o.left)->col
  1046.             );
  1047.         break;
  1048.     default:
  1049.         syncref(e->e.o.right);
  1050.         syncref(e->e.o.left);
  1051.         break;
  1052.     }
  1053.     }
  1054. }
  1055.  
  1056. hiderow(arg)
  1057. {
  1058.     register int r1;
  1059.     register int r2;
  1060.  
  1061.     r1 = currow;
  1062.     r2 = r1 + arg - 1;
  1063.     if (r1 < 0 || r1 > r2) {
  1064.     error("Invalid Range");
  1065.     return;
  1066.     }
  1067.     if (r2 > MAXROWS-2) {
  1068.     error("You can't hide the last row");
  1069.     return;
  1070.     }
  1071.     FullUpdate++;
  1072.     while (r1 <= r2)
  1073.     row_hidden[r1++] = 1;
  1074. }
  1075.  
  1076. hidecol(arg)
  1077. {
  1078.     register int c1;
  1079.     register int c2;
  1080.  
  1081.     c1 = curcol;
  1082.     c2 = c1 + arg - 1;
  1083.     if (c1 < 0 || c1 > c2) {
  1084.     error("Invalid Range");
  1085.     return;
  1086.     }
  1087.     if (c2 > MAXCOLS-2) {
  1088.     error("You can't hide the last col");
  1089.     return;
  1090.     }
  1091.     FullUpdate++;
  1092.     while (c1 <= c2)
  1093.     col_hidden[c1++] = 1;
  1094. }
  1095.  
  1096. showrow(r1, r2)
  1097. {
  1098.     if (r1 < 0 || r1 > r2) {
  1099.     error("Invalid Range");
  1100.     return;
  1101.     }
  1102.     if (r2 > MAXROWS-1) {
  1103.     r2 = MAXROWS-1;
  1104.     }
  1105.     FullUpdate++;
  1106.     while (r1 <= r2)
  1107.     row_hidden[r1++] = 0;
  1108. }
  1109.  
  1110. showcol(c1, c2)
  1111. {
  1112.     if (c1 < 0 || c1 > c2) {
  1113.     error("Invalid Range");
  1114.     return;
  1115.     }
  1116.     if (c2 > MAXCOLS-1) {
  1117.     c2 = MAXCOLS-1;
  1118.     }
  1119.     FullUpdate++;
  1120.     while (c1 <= c2)
  1121.     col_hidden[c1++] = 0;
  1122. }
  1123.  
  1124. /* Open the output file, setting up a pipe if needed */
  1125.  
  1126. FILE *
  1127. openout(fname, rpid)
  1128. char *fname;
  1129. int *rpid;
  1130. {
  1131.     int pipefd[2];
  1132.     int pid;
  1133.     FILE *f;
  1134.  
  1135.     while (*fname && (*fname == ' '))  /* Skip leading blanks */
  1136.     fname++;
  1137.  
  1138.     if (*fname != '|') {        /* Open file if not pipe */
  1139.     *rpid = 0;
  1140.     return(fopen(fname, "w"));
  1141.     }
  1142.  
  1143.     fname++;                /* Skip | */
  1144.     deraw();
  1145.     pipe (pipefd);              /* make pipe to child */
  1146.  
  1147.     if ((pid=fork()) == 0)              /* if child  */
  1148.     {
  1149.     close (0);              /* close stdin */
  1150.     close (pipefd[1]);
  1151.     dup (pipefd[0]);          /* connect to pipe input */
  1152.     execl ("/bin/sh", "sh", "-c", fname, 0);
  1153.     exit (-127);
  1154.     }
  1155.     else                  /* else parent */
  1156.     {
  1157.     *rpid = pid;
  1158.     f = fdopen (pipefd[1], "w");
  1159.     if (f == 0)
  1160.     {
  1161.         kill (pid, -9);
  1162.         error ("Can't fdopen output");
  1163.         close (pipefd[1]);
  1164.         *rpid = 0;
  1165.         return(0);
  1166.     }
  1167.     }
  1168.     return(f);
  1169. }
  1170.  
  1171. closeout(f, pid)
  1172. FILE *f;
  1173. int pid;
  1174. {
  1175.     int temp;
  1176.  
  1177.     fclose (f);
  1178.     if (pid) {
  1179.          while (pid != wait(&temp)) /**/;
  1180.      printf("Press <return> to continue\n");
  1181.      (void)nmgetch();
  1182.      goraw();
  1183.     }
  1184. }
  1185. \SHAR\EOF\
  1186. else
  1187.   echo "will not over write ./interp.c"
  1188. fi
  1189. if [ `wc -c ./interp.c | awk '{printf $1}'` -ne 20553 ]
  1190. then
  1191. echo `wc -c ./interp.c | awk '{print "Got " $1 ", Expected " 20553}'`
  1192. fi
  1193. if `test ! -s ./cmds.c`
  1194. then
  1195. echo "writing ./cmds.c"
  1196. cat > ./cmds.c << '\SHAR\EOF\'
  1197. /*    SC    A Spreadsheet Calculator
  1198.  *        Main driver
  1199.  *
  1200.  *        original by James Gosling, September 1982
  1201.  *        modifications by Mark Weiser and Bruce Israel,
  1202.  *            University of Maryland
  1203.  *
  1204.  *              More mods Robert Bond, 12/86
  1205.  *
  1206.  */
  1207.  
  1208. #include <curses.h>
  1209. #include "sc.h"
  1210.  
  1211. #ifdef BSD42
  1212. #include <strings.h>
  1213. #else
  1214. #ifndef SYSIII
  1215. #include <string.h>
  1216. #endif
  1217. #endif
  1218.  
  1219. char *xmalloc();
  1220.  
  1221. duprow()
  1222. {
  1223.     if (currow >= MAXROWS - 1 || maxrow >= MAXROWS - 1) {
  1224.     error ("The table can't be any bigger");
  1225.     return;
  1226.     }
  1227.     modflg++;
  1228.     currow++;
  1229.     openrow (currow);
  1230.     for (curcol = 0; curcol <= maxcol; curcol++) {
  1231.     register struct ent *p = tbl[currow - 1][curcol];
  1232.     if (p) {
  1233.         register struct ent *n;
  1234.         n = lookat (currow, curcol);
  1235.         n -> v = p -> v;
  1236.         n -> flags = p -> flags;
  1237.         n -> expr = copye (p -> expr, 1, 0);
  1238.         n -> label = 0;
  1239.         if (p -> label) {
  1240.         n -> label = (char *)
  1241.                  xmalloc ((unsigned)(strlen (p -> label) + 1));
  1242.         strcpy (n -> label, p -> label);
  1243.         }
  1244.     }
  1245.     }
  1246.     for (curcol = 0; curcol <= maxcol; curcol++) {
  1247.     register struct ent *p = tbl[currow][curcol];
  1248.     if (p && (p -> flags & is_valid) && !p -> expr)
  1249.         break;
  1250.     }
  1251.     if (curcol > maxcol)
  1252.     curcol = 0;
  1253. }
  1254.  
  1255. dupcol() 
  1256. {
  1257.     if (curcol >= MAXCOLS - 1 || maxcol >= MAXCOLS - 1) {
  1258.     error ("The table can't be any wider");
  1259.     return;
  1260.     }
  1261.     modflg++;
  1262.     curcol++;
  1263.     opencol (curcol);
  1264.     for (currow = 0; currow <= maxrow; currow++) {
  1265.     register struct ent *p = tbl[currow][curcol - 1];
  1266.     if (p) {
  1267.         register struct ent *n;
  1268.         n = lookat (currow, curcol);
  1269.         n -> v = p -> v;
  1270.         n -> flags = p -> flags;
  1271.         n -> expr = copye (p -> expr, 0, 1);
  1272.         n -> label = 0;
  1273.         if (p -> label) {
  1274.         n -> label = (char *)
  1275.                  xmalloc ((unsigned) (strlen (p -> label) + 1));
  1276.         strcpy (n -> label, p -> label);
  1277.         }
  1278.     }
  1279.     }
  1280.     for (currow = 0; currow <= maxrow; currow++) {
  1281.     register struct ent *p = tbl[currow][curcol];
  1282.     if (p && (p -> flags & is_valid) && !p -> expr)
  1283.         break;
  1284.     }
  1285.     if (currow > maxrow)
  1286.     currow = 0;
  1287. }
  1288.  
  1289. insertrow(arg)
  1290. {
  1291.     while (--arg>=0) openrow (currow);
  1292. }
  1293.  
  1294. deleterow(arg)
  1295. {
  1296.     flush_saved();
  1297.     erase_area(currow, 0, currow + arg - 1, maxcol);
  1298.     currow += arg;
  1299.     while (--arg>=0) closerow (--currow);
  1300.     sync_refs();
  1301. }
  1302.  
  1303. insertcol(arg)
  1304. {
  1305.     while (--arg>=0) opencol(curcol);
  1306. }
  1307.  
  1308. deletecol(arg)
  1309. {
  1310.     flush_saved();
  1311.     erase_area(0, curcol, maxrow, curcol + arg - 1);
  1312.     curcol += arg;
  1313.     while (--arg>=0) closecol (--curcol);
  1314.     sync_refs();
  1315. }
  1316.  
  1317. rowvalueize(arg)
  1318. {
  1319.     valueize_area(currow, 0, currow + arg - 1, maxcol);
  1320. }
  1321.  
  1322. colvalueize(arg)
  1323. {
  1324.     valueize_area(0, curcol, maxrow, curcol + arg - 1);
  1325. }
  1326.  
  1327. erase_area(sr, sc, er, ec)
  1328. int sr, sc, er, ec;
  1329. {
  1330.     register int r, c;
  1331.     register struct ent **p;
  1332.  
  1333.     if (sr > er) {
  1334.     r = sr; sr = er; er= r;    
  1335.     }
  1336.  
  1337.     if (sc > ec) {
  1338.     c = sc; sc = ec; ec= c;    
  1339.     }
  1340.  
  1341.     if (sr < 0)
  1342.     sr = 0; 
  1343.     if (sc < 0)
  1344.     sc = 0;
  1345.     if (er >= MAXROWS)
  1346.     er = MAXROWS-1;
  1347.     if (ec >= MAXCOLS)
  1348.     ec = MAXCOLS-1;
  1349.  
  1350.     for (r = sr; r <= er; r++) {
  1351.     for (c = sc; c <= ec; c++) {
  1352.         p = &tbl[r][c];
  1353.         if (*p) {
  1354.         free_ent(*p);
  1355.         *p = 0;
  1356.         }
  1357.     }
  1358.     }
  1359.  
  1360. }
  1361.  
  1362. valueize_area(sr, sc, er, ec)
  1363. int sr, sc, er, ec;
  1364. {
  1365.     register int r, c;
  1366.     register struct ent *p;
  1367.  
  1368.     if (sr > er) {
  1369.     r = sr; sr = er; er= r;    
  1370.     }
  1371.  
  1372.     if (sc > ec) {
  1373.     c = sc; sc = ec; ec= c;    
  1374.     }
  1375.  
  1376.     if (sr < 0)
  1377.     sr = 0; 
  1378.     if (sc < 0)
  1379.     sc = 0;
  1380.     if (er >= MAXROWS)
  1381.     er = MAXROWS-1;
  1382.     if (ec >= MAXCOLS)
  1383.     ec = MAXCOLS-1;
  1384.  
  1385.     for (r = sr; r <= er; r++) {
  1386.     for (c = sc; c <= ec; c++) {
  1387.         p = tbl[r][c];
  1388.         if (p && p->expr) {
  1389.         efree(p->expr);
  1390.         p->expr = 0;
  1391.         }
  1392.     }
  1393.     }
  1394.  
  1395. }
  1396.  
  1397. pullcells(to_insert)
  1398. {
  1399.     register struct ent *p, *n;
  1400.     register int deltar, deltac;
  1401.     int minrow, mincol;
  1402.     int maxrow, maxcol;
  1403.     int numrows, numcols;
  1404.  
  1405.     if (!to_fix)
  1406.     return;
  1407.  
  1408.     switch (to_insert) {
  1409.     case 'm':
  1410.     case 'r':
  1411.     case 'c':
  1412.     break;
  1413.     default:
  1414.     error("Invalid pull command");
  1415.     return;
  1416.     }
  1417.  
  1418.     minrow = MAXROWS; 
  1419.     mincol = MAXCOLS;
  1420.     maxrow = 0;
  1421.     maxcol = 0;
  1422.  
  1423.     for (p = to_fix; p; p = p->next) {
  1424.     if (p->row < minrow)
  1425.         minrow = p->row;
  1426.     if (p->row > maxrow)
  1427.         maxrow = p->row;
  1428.     if (p->col < mincol)
  1429.         mincol = p->col;
  1430.     if (p->col > maxcol)
  1431.         maxcol = p->col;
  1432.     }
  1433.  
  1434.     numrows = maxrow - minrow + 1;
  1435.     numcols = maxcol - mincol + 1;
  1436.     deltar = currow - minrow;
  1437.     deltac = curcol - mincol;
  1438.  
  1439.     if (to_insert == 'r') {
  1440.     insertrow(numrows);
  1441.     deltac = 0;
  1442.     } else if (to_insert == 'c') {
  1443.     insertcol(numcols);
  1444.     deltar = 0;
  1445.     }
  1446.  
  1447.     FullUpdate++;
  1448.     modflg++;
  1449.  
  1450.     for (p = to_fix; p; p = p->next) {
  1451.     n = lookat (p->row + deltar, p->col + deltac);
  1452.     clearent(n);
  1453.     n -> flags = p -> flags & ~is_deleted;
  1454.     n -> v = p -> v;
  1455.     n -> expr = copye(p->expr, deltar, deltac);
  1456.     n -> label = 0;
  1457.     if (p -> label) {
  1458.         n -> label = (char *)
  1459.              xmalloc((unsigned)(strlen(p->label)+1));
  1460.         strcpy (n -> label, p -> label);
  1461.     }
  1462.     }
  1463. }
  1464.  
  1465. colshow_op()
  1466. {
  1467.     register int i,j;
  1468.     for (i=0; i<MAXCOLS; i++)
  1469.     if (col_hidden[i]) 
  1470.         break;
  1471.     for(j=i; j<MAXCOLS; j++)
  1472.     if (!col_hidden[j])
  1473.         break;
  1474.     j--;
  1475.     if (i<MAXCOLS) {
  1476.     sprintf(line,"show %s:", coltoa(i));
  1477.     sprintf(line + strlen(line),"%s",coltoa(j));
  1478.     linelim = strlen (line);
  1479.     }
  1480. }
  1481.  
  1482. rowshow_op()
  1483. {
  1484.     register int i,j;
  1485.     for (i=0; i<MAXROWS; i++)
  1486.     if (row_hidden[i]) 
  1487.         break;
  1488.     for(j=i; j<MAXROWS; j++)
  1489.     if (!row_hidden[j]) {
  1490.         break;
  1491.     }
  1492.     j--;
  1493.     if (i<MAXROWS) {
  1494.     sprintf(line,"show %d:%d", i, j);
  1495.         linelim = strlen (line);
  1496.     }
  1497. }
  1498.  
  1499. get_qual()
  1500. {
  1501.     register int c;
  1502.  
  1503.     c = nmgetch();
  1504.     switch (c) {
  1505.     case 'c':
  1506.     case 'j':
  1507.     case 'k':
  1508.     case ctl(p):
  1509.     case ctl(n):
  1510.     return('c');
  1511.     case 'r':
  1512.     case 'l':
  1513.     case 'h':
  1514.     case ctl(f):
  1515.     case ctl(b):
  1516.     return('r');
  1517.     default:
  1518.     return(c);
  1519.     }
  1520.     /*NOTREACHED*/
  1521. }
  1522.  
  1523. openrow (rs) {
  1524.     register    r;
  1525.     register struct ent **p;
  1526.     register    c;
  1527.     register    i;
  1528.  
  1529.     if (rs > maxrow) maxrow = rs;
  1530.     if (maxrow >= MAXROWS - 1 || rs > MAXROWS - 1) {
  1531.     error ("The table can't be any longer");
  1532.     return;
  1533.     }
  1534.     for (i = maxrow+1; i > rs; i--) {
  1535.     row_hidden[i] = row_hidden[i-1];
  1536.     }
  1537.     for (r = ++maxrow; r > rs; r--)
  1538.     for (c = maxcol + 1, p = &tbl[r][0]; --c >= 0; p++)
  1539.         if (p[0] = p[-MAXCOLS])
  1540.         p[0] -> row++;
  1541.     p = &tbl[rs][0];
  1542.     for (c = maxcol + 1; --c >= 0;)
  1543.     *p++ = 0;
  1544.     FullUpdate++;
  1545.     modflg++;
  1546. }
  1547.  
  1548. closerow (r)
  1549. register r; {
  1550.     register struct ent **p;
  1551.     register c;
  1552.     register int i;
  1553.  
  1554.     if (r > maxrow) return;
  1555.  
  1556.     p = &tbl[r][0];
  1557.     for (c=maxcol+1; --c>=0; ) {
  1558.     if (*p)
  1559.         free_ent(*p);
  1560.     *p++ = 0;
  1561.     }
  1562.  
  1563.     for (i = r; i < MAXROWS - 1; i++) {
  1564.     row_hidden[i] = row_hidden[i+1];
  1565.     }
  1566.  
  1567.     while (r<maxrow) {
  1568.     for (c = maxcol+1, p = &tbl[r][0]; --c>=0; p++)
  1569.         if (p[0] = p[MAXCOLS])
  1570.         p[0]->row--;
  1571.     r++;
  1572.     }
  1573.  
  1574.     p = &tbl[maxrow][0];
  1575.     for (c=maxcol+1; --c>=0; ) *p++ = 0;
  1576.     maxrow--;
  1577.     FullUpdate++;
  1578.     modflg++;
  1579. }
  1580.  
  1581. opencol (cs) {
  1582.     register r;
  1583.     register struct ent **p;
  1584.     register c;
  1585.     register lim = maxcol-cs+1;
  1586.     int i;
  1587.  
  1588.     if (cs > maxcol) maxcol = cs;
  1589.     if (maxcol >= MAXCOLS - 1 || cs > MAXCOLS - 1) {
  1590.     error ("The table can't be any wider");
  1591.     return;
  1592.     }
  1593.     for (i = maxcol+1; i > cs; i--) {
  1594.     fwidth[i] = fwidth[i-1];
  1595.     precision[i] = precision[i-1];
  1596.     col_hidden[i] = col_hidden[i-1];
  1597.     }
  1598.     /* fwidth[cs] = DEFWIDTH;
  1599.     precision[i] =  DEFPREC;  */
  1600.  
  1601.     for (r=0; r<=maxrow; r++) {
  1602.     p = &tbl[r][maxcol+1];
  1603.     for (c=lim; --c>=0; p--)
  1604.         if (p[0] = p[-1])
  1605.         p[0]->col++;
  1606.     p[0] = 0;
  1607.     }
  1608.     maxcol++;
  1609.     FullUpdate++;
  1610.     modflg++;
  1611. }
  1612.  
  1613. closecol (cs) {
  1614.     register r;
  1615.     register struct ent **p;
  1616.     register struct ent *q;
  1617.     register c;
  1618.     register lim = maxcol-cs;
  1619.     int i;
  1620.  
  1621.     if (lim < 0) return;
  1622.  
  1623.     for (r=0; r<=maxrow; r++)
  1624.     if (q = tbl[r][cs]) {
  1625.         free_ent(q);
  1626.     }
  1627.  
  1628.     for (r=0; r<=maxrow; r++) {
  1629.     p = &tbl[r][cs];
  1630.     for (c=lim; --c>=0; p++)
  1631.         if (p[0] = p[1])
  1632.         p[0]->col--;
  1633.     p[0] = 0;
  1634.     }
  1635.  
  1636.     for (i = cs; i < MAXCOLS - 1; i++) {
  1637.     fwidth[i] = fwidth[i+1];
  1638.     precision[i] = precision[i+1];
  1639.     col_hidden[i] = col_hidden[i+1];
  1640.     }
  1641.  
  1642.     maxcol--;
  1643.     FullUpdate++;
  1644.     modflg++;
  1645. }
  1646.  
  1647. \SHAR\EOF\
  1648. else
  1649.   echo "will not over write ./cmds.c"
  1650. fi
  1651. if [ `wc -c ./cmds.c | awk '{printf $1}'` -ne 8123 ]
  1652. then
  1653. echo `wc -c ./cmds.c | awk '{print "Got " $1 ", Expected " 8123}'`
  1654. fi
  1655. if `test ! -s ./crypt.c`
  1656. then
  1657. echo "writing ./crypt.c"
  1658. cat > ./crypt.c << '\SHAR\EOF\'
  1659. /*
  1660.  * Encryption utilites
  1661.  * Bradley Williams    
  1662.  * {allegra,ihnp4,uiucdcs,ctvax}!convex!williams
  1663.  */
  1664.  
  1665. #include <stdio.h>
  1666. #include <curses.h>
  1667.  
  1668. #if defined(BSD42) || defined(BSD43)
  1669. #include <sys/file.h>
  1670. #else
  1671. #include <sys/fcntl.h>
  1672. #endif
  1673.  
  1674. #include "sc.h"
  1675.  
  1676. extern char curfile[];
  1677. char        *strcpy();
  1678. int         Crypt = 0;
  1679.  
  1680. #define DEFWIDTH 10
  1681. #define DEFPREC   2
  1682.  
  1683. creadfile (fname, eraseflg)
  1684. char *fname;
  1685. {
  1686.     register FILE *f;
  1687.     int pipefd[2];
  1688.     int fildes;
  1689.     int pid;
  1690.     char save[1024];
  1691.  
  1692.     if (*fname == 0) fname = &curfile[0];
  1693.     strcpy(save,fname);
  1694.  
  1695.     if (eraseflg && strcmp(fname,curfile) && modcheck(" first")) return;
  1696.  
  1697.     fildes = open (save, O_RDONLY, 0);
  1698.     if (fildes < 0)
  1699.     {
  1700.     error ("Can't read %s", save);
  1701.     return;
  1702.     }
  1703.  
  1704.     if (eraseflg) erasedb ();
  1705.  
  1706.     pipe (pipefd);              /* make pipe to child */
  1707.     deraw();
  1708.     if ((pid=fork()) == 0)              /* if child  */
  1709.     {
  1710.     close (0);              /* close stdin */
  1711.     close (1);              /* close stdout */
  1712.     close (pipefd[0]);          /* close pipe input */
  1713.     dup (fildes);              /* standard in from file */
  1714.     dup (pipefd[1]);          /* connect to pipe */
  1715.     fprintf (stderr, " ");
  1716.     execl ("/bin/sh", "sh", "-c", "crypt", 0);
  1717.     exit (-127);
  1718.     }
  1719.     else                  /* else parent */
  1720.     {
  1721.     close (fildes);
  1722.     close (pipefd[1]);          /* close pipe output */
  1723.     f = fdopen (pipefd[0], "r");
  1724.     if (f == 0)
  1725.     {
  1726.         kill (pid, -9);
  1727.         error ("Can't fdopen file %s", save);
  1728.         close (pipefd[0]);
  1729.         return;
  1730.     }
  1731.     }
  1732.  
  1733.     while (fgets(line,sizeof line,f)) {
  1734.     linelim = 0;
  1735.     if (line[0] != '#') yyparse ();
  1736.     }
  1737.     fclose (f);
  1738.     close (pipefd[0]);
  1739.     while (pid != wait(&fildes)) /**/;
  1740.     goraw();
  1741.     linelim = -1;
  1742.     modflg++;
  1743.     if (eraseflg) {
  1744.     strcpy (curfile,save);
  1745.     modflg = 0;
  1746.     }
  1747.     EvalAll();
  1748. }
  1749.  
  1750. cwritefile (fname)
  1751. char *fname;
  1752. {
  1753.     register FILE *f;
  1754.     register struct ent **p;
  1755.     register r, c;
  1756.     int pipefd[2];
  1757.     int fildes;
  1758.     int pid;
  1759.     char save[1024];
  1760.  
  1761.     if (*fname == 0) fname = &curfile[0];
  1762.  
  1763.     strcpy(save,fname);
  1764.  
  1765.     fildes = open (save, O_WRONLY|O_CREAT, 0600);
  1766.     if (fildes < 0)
  1767.     {
  1768.     error ("Can't create %s", save);
  1769.     return(-1);
  1770.     }
  1771.  
  1772.     pipe (pipefd);              /* make pipe to child */
  1773.     deraw();
  1774.     if ((pid=fork()) == 0)              /* if child  */
  1775.     {
  1776.     close (0);              /* close stdin */
  1777.     close (1);              /* close stdout */
  1778.     close (pipefd[1]);          /* close pipe output */
  1779.     dup (pipefd[0]);          /* connect to pipe input */
  1780.     dup (fildes);              /* standard out to file */
  1781.     fprintf (stderr, " ");
  1782.     execl ("/bin/sh", "sh", "-c", "crypt", 0);
  1783.     exit (-127);
  1784.     }
  1785.     else                  /* else parent */
  1786.     {
  1787.     close (fildes);
  1788.     close (pipefd[0]);          /* close pipe input */
  1789.     f = fdopen (pipefd[1], "w");
  1790.     if (f == 0)
  1791.     {
  1792.         kill (pid, -9);
  1793.         error ("Can't fdopen file %s", save);
  1794.         close (pipefd[1]);
  1795.         return(-1);
  1796.     }
  1797.     }
  1798.  
  1799.     fprintf (f, "# This data file was generated by the Spreadsheet ");
  1800.     fprintf (f, "Calculator.\n");
  1801.     fprintf (f, "# You almost certainly shouldn't edit it.\n\n");
  1802.     for (c=0; c<MAXCOLS; c++)
  1803.     if (fwidth[c] != DEFWIDTH || precision[c] != DEFPREC)
  1804.         fprintf (f, "format %s %d %d\n",coltoa(c),fwidth[c],precision[c]);
  1805.     for (r=0; r<=maxrow; r++) {
  1806.     p = &tbl[r][0];
  1807.     for (c=0; c<=maxcol; c++, p++)
  1808.         if (*p) {
  1809.         if ((*p)->label)
  1810.             fprintf (f, "%sstring %s%d = \"%s\"\n",
  1811.                 (*p)->flags&is_leftflush ? "left" : "right",
  1812.                 coltoa(c),r,(*p)->label);
  1813.         if ((*p)->flags&is_valid) {
  1814.             editv (r, c);
  1815.             fprintf (f, "%s\n",line);
  1816.         }
  1817.         }
  1818.     }
  1819.     fclose (f);
  1820.     close (pipefd[1]);
  1821.     while (pid != wait(&fildes)) /**/;
  1822.     strcpy(curfile,save);
  1823.  
  1824.     modflg = 0;
  1825.     error("File '%s' written.",curfile);
  1826.     goraw();
  1827.     return(0);
  1828. }
  1829. \SHAR\EOF\
  1830. else
  1831.   echo "will not over write ./crypt.c"
  1832. fi
  1833. if [ `wc -c ./crypt.c | awk '{printf $1}'` -ne 3654 ]
  1834. then
  1835. echo `wc -c ./crypt.c | awk '{print "Got " $1 ", Expected " 3654}'`
  1836. fi
  1837. if `test ! -s ./xmalloc.c`
  1838. then
  1839. echo "writing ./xmalloc.c"
  1840. cat > ./xmalloc.c << '\SHAR\EOF\'
  1841. /*
  1842.  * A safer saner malloc, for careless programmers
  1843.  * (I guess I qualify! - rgb)
  1844.  */
  1845.  
  1846. #include <stdio.h>
  1847. #include <curses.h>
  1848.  
  1849. extern char *malloc();
  1850.  
  1851. char *
  1852. xmalloc(n)
  1853. unsigned n;
  1854. {
  1855. register char *ptr;
  1856.  
  1857. if ((ptr = malloc(n + sizeof(int))) == NULL)
  1858.     fatal("xmalloc: no memory");
  1859. *((int *) ptr) = 12345;        /* magic number */
  1860. return(ptr + sizeof(int));
  1861. }
  1862.  
  1863. xfree(p)
  1864. char *p;
  1865. {
  1866. if (p == NULL)
  1867.     fatal("xfree: NULL");
  1868. p -= sizeof(int);
  1869. if (*((int *) p) != 12345)
  1870.     fatal("xfree: storage not malloc'ed");
  1871. free(p);
  1872. }
  1873.  
  1874. fatal(str)
  1875. char *str;
  1876. {
  1877.     deraw();
  1878.     fprintf(stderr,"%s\n", str);
  1879.     exit(1);
  1880. }
  1881. \SHAR\EOF\
  1882. else
  1883.   echo "will not over write ./xmalloc.c"
  1884. fi
  1885. if [ `wc -c ./xmalloc.c | awk '{printf $1}'` -ne 603 ]
  1886. then
  1887. echo `wc -c ./xmalloc.c | awk '{print "Got " $1 ", Expected " 603}'`
  1888. fi
  1889. if `test ! -s ./range.c`
  1890. then
  1891. echo "writing ./range.c"
  1892. cat > ./range.c << '\SHAR\EOF\'
  1893.  
  1894. /*    SC    A Spreadsheet Calculator
  1895.  *        Range Manipulations
  1896.  *
  1897.  *              Robert Bond, 4/87
  1898.  *
  1899.  */
  1900.  
  1901. #include <stdio.h>
  1902. #include <curses.h>
  1903. #include <ctype.h>
  1904. #include "sc.h"
  1905.  
  1906. #ifdef BSD42
  1907. #include <strings.h>
  1908. #else
  1909. #ifndef SYSIII
  1910. #include <string.h>
  1911. #endif
  1912. #endif
  1913.  
  1914. char *xmalloc();
  1915.  
  1916. static struct range *rng_base;
  1917.  
  1918. add_range(name, left, right)
  1919. char *name;
  1920. struct ent *left, *right;
  1921. {
  1922.     struct range *r;
  1923.     register char *p;
  1924.     int len;
  1925.  
  1926.     if (find_range(name, strlen(name), (struct ent *)0, (struct ent *)0)) {
  1927.     error("Error: range name already defined");
  1928.     return;
  1929.     }
  1930.  
  1931.     if (strlen(name) <=2) {
  1932.     error("Invalid range name - too short");
  1933.     return;
  1934.     }
  1935.  
  1936.     for(p=name, len=0; *p; p++, len++)
  1937.     if (!((isalpha(*p) && (len<=2)) ||
  1938.         ((isdigit(*p) || isalpha(*p) || (*p == '_')) && (len>2)))) {
  1939.         error("Invalid range name - illegal combination");
  1940.         return;
  1941.         }
  1942.  
  1943.     r = (struct range *)xmalloc((unsigned)sizeof(struct range));
  1944.     r->r_name = name;
  1945.     r->r_left = left;
  1946.     r->r_right = right;
  1947.     r->r_next = rng_base;
  1948.     r->r_prev = 0;
  1949.     if (rng_base)
  1950.         rng_base->r_prev = r;
  1951.     rng_base = r;
  1952. }
  1953.  
  1954. del_range(left, right)
  1955. struct ent *left, *right;
  1956. {
  1957.     register struct range *r;
  1958.  
  1959.     if (!(r = find_range((char *)0, 0, left, right))) 
  1960.     return;
  1961.  
  1962.     if (r->r_next)
  1963.         r->r_next->r_prev = r->r_prev;
  1964.     if (r->r_prev)
  1965.         r->r_prev->r_next = r->r_next;
  1966.     else
  1967.     rng_base = r->r_next;
  1968.     xfree((char *)(r->r_name));
  1969.     xfree((char *)r);
  1970. }
  1971.  
  1972. /* Match on name or lmatch, rmatch */
  1973.  
  1974. struct range *
  1975. find_range(name, len, lmatch, rmatch)
  1976. char *name;
  1977. int len;
  1978. struct ent *lmatch;
  1979. struct ent *rmatch;
  1980. {
  1981.     struct range *r;
  1982.     register char *rp, *np;
  1983.     register int c;
  1984.  
  1985.     if (name) {
  1986.     for (r = rng_base; r; r = r->r_next) {
  1987.         for (np = name, rp = r->r_name, c = len;
  1988.          c && *rp && (*rp == *np);
  1989.          rp++, np++, c--) /* */;
  1990.         if (!c && !*rp)
  1991.         return(r);
  1992.     }
  1993.     return(0);
  1994.     }
  1995.  
  1996.     for (r = rng_base; r; r= r->r_next) {
  1997.     if ((lmatch == r->r_left) && (rmatch == r->r_right)) 
  1998.         return(r);
  1999.     }
  2000.     return(0);
  2001. }
  2002.  
  2003. sync_ranges()
  2004. {
  2005.     register struct range *r;
  2006.  
  2007.     r = rng_base;
  2008.     while(r) {
  2009.     r->r_left = lookat(r->r_left->row, r->r_left->col);
  2010.     r->r_right = lookat(r->r_right->row, r->r_right->col);
  2011.     r = r->r_next;
  2012.     }
  2013. }
  2014.  
  2015. write_range(f)
  2016. FILE *f;
  2017. {
  2018.     register struct range *r;
  2019.  
  2020.     for (r = rng_base; r; r = r->r_next) {
  2021.     fprintf(f, "define \"%s\" %s%d", r->r_name, coltoa(r->r_left->col), 
  2022.                    r->r_left->row);
  2023.     if (r->r_left != r->r_right)
  2024.         fprintf(f, ":%s%d\n", coltoa(r->r_right->col), r->r_right->row);
  2025.     else
  2026.         fprintf(f, "\n");
  2027.     }
  2028. }
  2029.  
  2030. list_range(f)
  2031. FILE *f;
  2032. {
  2033.     register struct range *r;
  2034.  
  2035.     for (r = rng_base; r; r = r->r_next) {
  2036.     fprintf(f, "%-30s %s%d", r->r_name, coltoa(r->r_left->col), 
  2037.                    r->r_left->row);
  2038.     if (r->r_left != r->r_right)
  2039.         fprintf(f, ":%s%d\n", coltoa(r->r_right->col), r->r_right->row);
  2040.     else
  2041.         fprintf(f, "\n");
  2042.  
  2043.     }
  2044. }
  2045.  
  2046. char *
  2047. v_name(row, col)
  2048. int row, col;
  2049. {
  2050.     struct ent *v;
  2051.     struct range *r;
  2052.     static char buf[20];
  2053.  
  2054.     v = lookat(row, col);
  2055.     if (r = find_range((char *)0, 0, v, v)) {
  2056.     return(r->r_name);
  2057.     } else {
  2058.         sprintf(buf, "%s%d", coltoa(col), row);
  2059.     return buf;
  2060.     }
  2061. }
  2062. \SHAR\EOF\
  2063. else
  2064.   echo "will not over write ./range.c"
  2065. fi
  2066. if [ `wc -c ./range.c | awk '{printf $1}'` -ne 3211 ]
  2067. then
  2068. echo `wc -c ./range.c | awk '{print "Got " $1 ", Expected " 3211}'`
  2069. fi
  2070. if `test ! -s ./eres.sed`
  2071. then
  2072. echo "writing ./eres.sed"
  2073. cat > ./eres.sed << '\SHAR\EOF\'
  2074. /%token.*K_/!d
  2075. /%token.*K_\(.*\)/s//    "\1",    K_\1,/
  2076. \SHAR\EOF\
  2077. else
  2078.   echo "will not over write ./eres.sed"
  2079. fi
  2080. if [ `wc -c ./eres.sed | awk '{printf $1}'` -ne 50 ]
  2081. then
  2082. echo `wc -c ./eres.sed | awk '{print "Got " $1 ", Expected " 50}'`
  2083. fi
  2084. if `test ! -s ./sres.sed`
  2085. then
  2086. echo "writing ./sres.sed"
  2087. cat > ./sres.sed << '\SHAR\EOF\'
  2088. /%token.*S_/!d
  2089. /%token.*S_\(.*\)/s//    "\1",    S_\1,/
  2090. \SHAR\EOF\
  2091. else
  2092.   echo "will not over write ./sres.sed"
  2093. fi
  2094. if [ `wc -c ./sres.sed | awk '{printf $1}'` -ne 50 ]
  2095. then
  2096. echo `wc -c ./sres.sed | awk '{print "Got " $1 ", Expected " 50}'`
  2097. fi
  2098. if `test ! -s ./makefile`
  2099. then
  2100. echo "writing ./makefile"
  2101. cat > ./makefile << '\SHAR\EOF\'
  2102.  
  2103. # Specify the name of the program.
  2104. # All documentation and installation keys on this value.
  2105. name=sc
  2106. NAME=SC
  2107.  
  2108. # This is where the install step puts it.
  2109. EXDIR=/a/rgb/bin
  2110.  
  2111. # This is where the man page goes.
  2112. MANDIR=/usr/man/man1
  2113.  
  2114. # All of the source files
  2115. SRC=sc.h sc.c lex.c gram.y interp.c cmds.c crypt.c xmalloc.c range.c eres.sed\
  2116.     sres.sed makefile cvt.sed 
  2117.  
  2118. # The documents in the Archive
  2119. DOCS=README $(name).man sc.doc
  2120.  
  2121. # Set SIMPLE for lex.c if you don't want arrow keys or lex.c blows up
  2122. #SIMPLE=-DSIMPLE
  2123.  
  2124. # Set QUICK if you want to enter numbers without "=" first
  2125. #QUICK=-DQUICK
  2126.  
  2127. # Use this for system V.2
  2128. #CFLAGS= -O -DSYSV2
  2129. #LDFLAGS=
  2130. #LIB=-lm -lcurses
  2131.  
  2132. # Use this for system V.3
  2133. #CFLAGS= -O -DSYSV3
  2134. #LDFLAGS=
  2135. #LIB=-lm -lcurses
  2136.  
  2137. # Use this for BSD 4.2
  2138. #CFLAGS= -O -DBSD42
  2139. #LDFLAGS=
  2140. #LIB=-lm -lcurses -ltermcap
  2141.  
  2142. # Use this for BSD 4.3
  2143. CFLAGS= -O -DBSD43
  2144. LDFLAGS=
  2145. LIB=-lm -lcurses -ltermcap
  2146.  
  2147. # Use this for system III (XENIX)
  2148. #CFLAGS= -O -DSYSIII
  2149. #LDFLAGS= -i
  2150. #LIB=-lm -lcurses -ltermcap
  2151.  
  2152. # Use this for VENIX
  2153. #CFLAGS= -DVENIX -DBSD42 -DV7
  2154. #LDFLAGS= -z -i 
  2155. #LIB=-lm -lcurses -ltermcap
  2156.  
  2157. # The objects
  2158. OBJS=sc.o lex.o gram.o interp.o cmds.o crypt.o xmalloc.o range.o
  2159.  
  2160. $(name):    $(OBJS)
  2161.     cc ${CFLAGS} ${LDFLAGS} ${OBJS} ${LIB} -o $(name)
  2162.  
  2163. diff_to_sc:    diff_to_sc.c
  2164.     cc ${CFLAGS} -o dtv diff_to_sc.c
  2165.  
  2166. pvc:    pvc.c
  2167.     cc ${CFLAGS} -o pvc pvc.c
  2168.     cp pvc $(EXDIR)/pvc
  2169.  
  2170. lex.o:    sc.h y.tab.h gram.o
  2171.     cc ${CFLAGS} ${SIMPLE} -c lex.c
  2172.  
  2173. sc.o:    sc.h sc.c
  2174.     cc ${CFLAGS} ${QUICK} -c sc.c
  2175.  
  2176. interp.o:    interp.c sc.h
  2177.  
  2178. gram.o:    sc.h y.tab.h
  2179.  
  2180. cmds.o: cmds.c sc.h
  2181.  
  2182. crypt.o: crypt.c sc.h
  2183.  
  2184. range.o: range.c sc.h
  2185.  
  2186. y.tab.h:    gram.y
  2187.  
  2188. gram.o:    sc.h y.tab.h gram.c
  2189.     cc ${CFLAGS} -c gram.c
  2190.     sed<gram.y >experres.h -f eres.sed;sed < gram.y > statres.h -f sres.sed
  2191.  
  2192. gram.c:    gram.y
  2193.     yacc -d gram.y; mv y.tab.c gram.c
  2194.  
  2195. clean:
  2196.     rm -f *.o *res.h y.tab.h $(name) debug core gram.c 
  2197.  
  2198. shar: ${SRC} ${DOCS}
  2199.     shar -c -m 55000 -f shar ${DOCS} ${SRC}
  2200.  
  2201. lint: sc.h sc.c lex.c gram.c interp.c cmds.c crypt.c
  2202.     lint ${CFLAGS} ${SIMPLE} ${QUICK} sc.c lex.c gram.c interp.c cmds.c crypt.c range.c -lcurses -lm
  2203.  
  2204. print: sc.h gram.y sc.c lex.c interp.c cmds.c crypt.c 
  2205.     prc sc.h gram.y sc.c lex.c interp.c cmds.c crypt.c | lpr
  2206.  
  2207. $(name).1:    sc.doc
  2208.     sed -e s/pname/$(name)/g -e s/PNAME/$(NAME)/g sc.doc >  $(name).1
  2209.  
  2210. $(name).man:    $(name).1
  2211.     -mv $(name).man $(name).mold
  2212.     nroff -man $(name).1 > $(name).man
  2213.  
  2214. install: $(EXDIR)/$(name)
  2215.  
  2216. inst-man: $(MANDIR)/$(name).1
  2217.  
  2218. $(EXDIR)/$(name): $(name)
  2219.     -mv $(EXDIR)/$(name) $(EXDIR)/$(name).old
  2220.     strip $(name)
  2221.     cp $(name) $(EXDIR)
  2222.  
  2223. $(MANDIR)/$(name).1: $(name).1
  2224.     cp $(name).1 $(MANDIR)
  2225. \SHAR\EOF\
  2226. else
  2227.   echo "will not over write ./makefile"
  2228. fi
  2229. if [ `wc -c ./makefile | awk '{printf $1}'` -ne 2566 ]
  2230. then
  2231. echo `wc -c ./makefile | awk '{print "Got " $1 ", Expected " 2566}'`
  2232. fi
  2233. if `test ! -s ./cvt.sed`
  2234. then
  2235. echo "writing ./cvt.sed"
  2236. cat > ./cvt.sed << '\SHAR\EOF\'
  2237. s!+/\(r.*c.*:r.*c[0-9]*\)!@sum(\1)!
  2238. s/\(r[0-9]*\)\(c[0-9]*\)/\2\1/g
  2239. s/c10/k/g
  2240. s/c11/l/g
  2241. s/c12/m/g
  2242. s/c13/n/g
  2243. s/c14/o/g
  2244. s/c15/p/g
  2245. s/c16/q/g
  2246. s/c17/r/g
  2247. s/c18/s/g
  2248. s/c19/t/g
  2249. s/c20/u/g
  2250. s/c21/v/g
  2251. s/c22/w/g
  2252. s/c23/x/g
  2253. s/c24/y/g
  2254. s/c25/z/g
  2255. s/c26/aa/g
  2256. s/c27/ab/g
  2257. s/c28/ac/g
  2258. s/c29/ad/g
  2259. s/c30/ae/g
  2260. s/c31/af/g
  2261. s/c32/ag/g
  2262. s/c33/ah/g
  2263. s/c34/ai/g
  2264. s/c35/aj/g
  2265. s/c36/ak/g
  2266. s/c37/al/g
  2267. s/c38/am/g
  2268. s/c39/an/g
  2269. s/c0/a/g
  2270. s/c1/b/g
  2271. s/c2/c/g
  2272. s/c3/d/g
  2273. s/c4/e/g
  2274. s/c5/f/g
  2275. s/c6/g/g
  2276. s/c7/h/g
  2277. s/c8/i/g
  2278. s/c9/j/g
  2279. s/r\([0-9][0-9]*\)/\1/g
  2280. s/format 10/format k/g
  2281. s/format 11/format l/g
  2282. s/format 12/format m/g
  2283. s/format 13/format n/g
  2284. s/format 14/format o/g
  2285. s/format 15/format p/g
  2286. s/format 16/format q/g
  2287. s/format 17/format r/g
  2288. s/format 18/format s/g
  2289. s/format 19/format t/g
  2290. s/format 20/format u/g
  2291. s/format 21/format v/g
  2292. s/format 22/format w/g
  2293. s/format 23/format x/g
  2294. s/format 24/format y/g
  2295. s/format 25/format z/g
  2296. s/format 26/format aa/g
  2297. s/format 27/format ab/g
  2298. s/format 28/format ac/g
  2299. s/format 29/format ad/g
  2300. s/format 30/format ae/g
  2301. s/format 31/format af/g
  2302. s/format 32/format ag/g
  2303. s/format 33/format ah/g
  2304. s/format 34/format ai/g
  2305. s/format 35/format aj/g
  2306. s/format 36/format ak/g
  2307. s/format 37/format al/g
  2308. s/format 38/format am/g
  2309. s/format 39/format an/g
  2310. s/format 0/format a/g
  2311. s/format 1/format b/g
  2312. s/format 2/format c/g
  2313. s/format 3/format d/g
  2314. s/format 4/format e/g
  2315. s/format 5/format f/g
  2316. s/format 6/format g/g
  2317. s/format 7/format h/g
  2318. s/format 8/format i/g
  2319. s/format 9/format j/g
  2320. \SHAR\EOF\
  2321. else
  2322.   echo "will not over write ./cvt.sed"
  2323. fi
  2324. if [ `wc -c ./cvt.sed | awk '{printf $1}'` -ne 1420 ]
  2325. then
  2326. echo `wc -c ./cvt.sed | awk '{print "Got " $1 ", Expected " 1420}'`
  2327. fi
  2328. echo "Finished archive 1 of 3"
  2329. # if you want to concatenate archives, remove anything after this line
  2330. exit
  2331.  
  2332. -- 
  2333.  
  2334. Rich $alz
  2335. Cronus Project, BBN Labs            rsalz@bbn.com
  2336. Moderator, comp.sources.unix            sources@uunet.uu.net
  2337.