home *** CD-ROM | disk | FTP | other *** search
Text File | 1987-08-17 | 48.8 KB | 2,338 lines |
- Path: uunet!rs
- From: rs@uunet.UU.NET (Rich Salz)
- Newsgroups: comp.sources.unix
- Subject: v11i017: Spread sheet program, sc 4.1, Part01/03
- Message-ID: <997@uunet.UU.NET>
- Date: 18 Aug 87 22:51:37 GMT
- Organization: UUNET Communications Services, Arlington, VA
- Lines: 2327
- Approved: rs@uunet.UU.NET
-
- Submitted-by: Robert Bond <rgb@nscpdc.nsc.com>
- Posting-number: Volume 11, Issue 17
- Archive-name: sc4.1/Part01
-
- This is release 4.1 of the spread sheet calculator SC. Unpack the
- three archives and check out the README file for details.
-
- Bob Bond
-
- # This is a shell archive. Remove anything before this line
- # then unpack it by saving it in a file and typing "sh file"
- # (Files unpacked will be owned by you and have default permissions).
- # This archive contains the following files:
- # ./gram.y
- # ./interp.c
- # ./cmds.c
- # ./crypt.c
- # ./xmalloc.c
- # ./range.c
- # ./eres.sed
- # ./sres.sed
- # ./makefile
- # ./cvt.sed
- #
- if `test ! -s ./gram.y`
- then
- echo "writing ./gram.y"
- cat > ./gram.y << '\SHAR\EOF\'
- /* SC A Spreadsheet Calculator
- * Command and expression parser
- *
- * original by James Gosling, September 1982
- * modified by Mark Weiser and Bruce Israel,
- * University of Maryland
- *
- * more mods Robert Bond 12/86
- *
- */
-
-
-
- %{
- #include <curses.h>
- #include "sc.h"
- %}
-
- %union {
- int ival;
- double fval;
- struct ent *ent;
- struct enode *enode;
- char *sval;
- RANGE_S rval;
- }
-
- %type <ent> var
- %type <fval> num
- %type <rval> range
- %type <enode> e term
- %token <sval> STRING
- %token <ival> NUMBER
- %token <fval> FNUMBER
- %token <rval> RANGE
- %token <sval> WORD
- %token <ival> COL
- %token S_FORMAT
- %token S_LABEL
- %token S_LEFTSTRING
- %token S_RIGHTSTRING
- %token S_GET
- %token S_PUT
- %token S_MERGE
- %token S_LET
- %token S_WRITE
- %token S_TBL
- %token S_COPY
- %token S_SHOW
- %token S_ERASE
- %token S_FILL
- %token S_GOTO
- %token S_DEFINE
- %token S_UNDEFINE
-
- %token K_FIXED
- %token K_SUM
- %token K_PROD
- %token K_AVG
- %token K_STDDEV
- %token K_ACOS
- %token K_ASIN
- %token K_ATAN
- %token K_CEIL
- %token K_COS
- %token K_EXP
- %token K_FABS
- %token K_FLOOR
- %token K_HYPOT
- %token K_LN
- %token K_LOG
- %token K_PI
- %token K_POW
- %token K_SIN
- %token K_SQRT
- %token K_TAN
- %token K_DTR
- %token K_RTD
- %token K_MAX
- %token K_MIN
- %token K_RND
-
- %left '?' ':'
- %left '|'
- %left '&'
- %nonassoc '<' '=' '>'
- %left '+' '-'
- %left '*' '/'
- %left '^'
-
- %%
- command: S_LET var '=' e { let ($2, $4); }
- | S_LABEL var '=' STRING
- { label ($2, $4, 0); }
- | S_LEFTSTRING var '=' STRING
- { label ($2, $4, -1); }
- | S_RIGHTSTRING var '=' STRING
- { label ($2, $4, 1); }
- | S_FORMAT COL ':' COL NUMBER NUMBER
- { int i;
- for(i = $2; i<=$4; i++)
- fwidth[i] = $5, precision[i] = $6;
- FullUpdate++;
- modflg++;}
- | S_FORMAT COL NUMBER NUMBER
- { fwidth[$2] = $3;
- FullUpdate++;
- modflg++;
- precision[$2] = $4; }
- | S_GET STRING { readfile ($2,1); }
- | S_MERGE STRING { readfile ($2,0); }
- | S_PUT STRING { (void) writefile ($2); }
- | S_WRITE STRING { printfile ($2); }
- | S_TBL STRING { tblprintfile ($2); }
- | S_SHOW COL ':' COL { showcol( $2, $4); }
- | S_SHOW NUMBER ':' NUMBER { showrow( $2, $4); }
- | S_COPY var range { copy($2, $3.left, $3.right); }
- | S_ERASE range { eraser($2.left, $2.right); }
- | S_FILL range num num { fill($2.left, $2.right, $3, $4); }
- | S_GOTO var {moveto($2); }
- | S_DEFINE STRING range { add_range($2, $3.left, $3.right); }
- | S_DEFINE STRING var { add_range($2, $3, $3); }
- | S_UNDEFINE range { del_range($2.left, $2.right); }
- | /* nothing */
- | error;
-
- term: var { $$ = new_var('v', $1); }
- | K_FIXED term { $$ = new ('f', (struct enode *)0, $2); }
- | '@' K_SUM '(' range ')'
- { $$ = new (O_REDUCE('+'),
- (struct enode *)$4.left,
- (struct enode *)$4.right); }
- | '@' K_PROD '(' range ')'
- { $$ = new (O_REDUCE('*'),
- (struct enode *)$4.left,
- (struct enode *)$4.right); }
- | '@' K_AVG '(' range ')'
- { $$ = new (O_REDUCE('a'),
- (struct enode *)$4.left,
- (struct enode *)$4.right); }
- | '@' K_STDDEV '(' range ')'
- { $$ = new (O_REDUCE('s'),
- (struct enode *)$4.left,
- (struct enode *)$4.right); }
- | '@' K_MAX '(' range ')'
- { $$ = new (O_REDUCE(MAX),
- (struct enode *)$4.left,
- (struct enode *)$4.right); }
- | '@' K_MIN '(' range ')'
- { $$ = new (O_REDUCE(MIN),
- (struct enode *)$4.left,
- (struct enode *)$4.right); }
- | '@' K_ACOS '(' e ')' { $$ = new(ACOS, (struct enode *)0, $4); }
- | '@' K_ASIN '(' e ')' { $$ = new(ASIN, (struct enode *)0, $4); }
- | '@' K_ATAN '(' e ')' { $$ = new(ATAN, (struct enode *)0, $4); }
- | '@' K_CEIL '(' e ')' { $$ = new(CEIL, (struct enode *)0, $4); }
- | '@' K_COS '(' e ')' { $$ = new(COS, (struct enode *)0, $4); }
- | '@' K_EXP '(' e ')' { $$ = new(EXP, (struct enode *)0, $4); }
- | '@' K_FABS '(' e ')' { $$ = new(FABS, (struct enode *)0, $4); }
- | '@' K_FLOOR '(' e ')' { $$ = new(FLOOR, (struct enode *)0, $4); }
- | '@' K_HYPOT '(' e ',' e ')' { $$ = new(HYPOT, $4, $6); }
- | '@' K_LN '(' e ')' { $$ = new(LOG, (struct enode *)0, $4); }
- | '@' K_LOG '(' e ')' { $$ = new(LOG10, (struct enode *)0, $4); }
- | '@' K_POW '(' e ',' e ')' { $$ = new(POW, $4, $6); }
- | '@' K_SIN '(' e ')' { $$ = new(SIN, (struct enode *)0, $4); }
- | '@' K_SQRT '(' e ')' { $$ = new(SQRT, (struct enode *)0, $4); }
- | '@' K_TAN '(' e ')' { $$ = new(TAN, (struct enode *)0, $4); }
- | '@' K_DTR '(' e ')' { $$ = new(DTR, (struct enode *)0, $4); }
- | '@' K_RTD '(' e ')' { $$ = new(RTD, (struct enode *)0, $4); }
- | '@' K_RND '(' e ')' { $$ = new(RND, (struct enode *)0, $4); }
- | '(' e ')' { $$ = $2; }
- | '+' term { $$ = $2; }
- | '-' term { $$ = new ('m', (struct enode *)0, $2); }
- | NUMBER { $$ = new_const('k', (double) $1); }
- | FNUMBER { $$ = new_const('k', $1); }
- | K_PI { $$ = new_const('k', (double)3.14159265358979323846); }
- | '~' term { $$ = new ('~', (struct enode *)0, $2); }
- | '!' term { $$ = new ('~', (struct enode *)0, $2); }
- ;
-
- e: e '+' e { $$ = new ('+', $1, $3); }
- | e '-' e { $$ = new ('-', $1, $3); }
- | e '*' e { $$ = new ('*', $1, $3); }
- | e '/' e { $$ = new ('/', $1, $3); }
- | e '^' e { $$ = new ('^', $1, $3); }
- | term
- | e '?' e ':' e { $$ = new ('?', $1, new(':', $3, $5)); }
- | e '<' e { $$ = new ('<', $1, $3); }
- | e '=' e { $$ = new ('=', $1, $3); }
- | e '>' e { $$ = new ('>', $1, $3); }
- | e '&' e { $$ = new ('&', $1, $3); }
- | e '|' e { $$ = new ('|', $1, $3); }
- | e '<' '=' e { $$ = new ('~', (struct enode *)0,
- new ('>', $1, $4)); }
- | e '!' '=' e { $$ = new ('~', (struct enode *)0,
- new ('=', $1, $4)); }
- | e '>' '=' e { $$ = new ('~', (struct enode *)0,
- new ('<', $1, $4)); }
- ;
-
- range: var ':' var { $$.left = $1;
- $$.right = $3; }
- | RANGE { $$ = $1; }
- ;
-
- var: COL NUMBER { $$ = lookat($2 , $1); }
- | RANGE { $$ = $1.left; }
- ;
-
- num: NUMBER { $$ = (double) $1; }
- | FNUMBER { $$ = $1; }
- | '-' num { $$ = -$2; }
- | '+' num { $$ = $2; }
- ;
- \SHAR\EOF\
- else
- echo "will not over write ./gram.y"
- fi
- if [ `wc -c ./gram.y | awk '{printf $1}'` -ne 5891 ]
- then
- echo `wc -c ./gram.y | awk '{print "Got " $1 ", Expected " 5891}'`
- fi
- if `test ! -s ./interp.c`
- then
- echo "writing ./interp.c"
- cat > ./interp.c << '\SHAR\EOF\'
- /* SC A Spreadsheet Calculator
- * Expression interpreter and assorted support routines.
- *
- * original by James Gosling, September 1982
- * modified by Mark Weiser and Bruce Israel,
- * University of Maryland
- *
- * More mods Robert Bond, 12/86
- */
-
- #include <math.h>
- #include <stdio.h>
-
- #ifdef BSD42
- #include <strings.h>
- #else
- #ifndef SYSIII
- #include <string.h>
- #endif
- #endif
-
- #include <curses.h>
- #include "sc.h"
- #define DEFCOLDELIM ':'
-
- char *xmalloc();
- #define PI (double)3.14159265358979323846
- #define dtr(x) ((x)*(PI/(double)180.0))
- #define rtd(x) ((x)*(180.0/(double)PI))
-
- double dosum(minr, minc, maxr, maxc)
- int minr, minc, maxr, maxc;
- {
- double v;
- register r,c;
- register struct ent *p;
-
- v = 0;
- for (r = minr; r<=maxr; r++)
- for (c = minc; c<=maxc; c++)
- if ((p = tbl[r][c]) && p->flags&is_valid)
- v += p->v;
- return v;
- }
-
- double doprod(minr, minc, maxr, maxc)
- int minr, minc, maxr, maxc;
- {
- double v;
- register r,c;
- register struct ent *p;
-
- v = 1;
- for (r = minr; r<=maxr; r++)
- for (c = minc; c<=maxc; c++)
- if ((p = tbl[r][c]) && p->flags&is_valid)
- v *= p->v;
- return v;
- }
-
- double doavg(minr, minc, maxr, maxc)
- int minr, minc, maxr, maxc;
- {
- double v;
- register r,c,count;
- register struct ent *p;
-
- v = 0;
- count = 0;
- for (r = minr; r<=maxr; r++)
- for (c = minc; c<=maxc; c++)
- if ((p = tbl[r][c]) && p->flags&is_valid) {
- v += p->v;
- count++;
- }
-
- if (count == 0)
- return ((double) 0);
-
- return (v / (double)count);
- }
-
- double dostddev(minr, minc, maxr, maxc)
- int minr, minc, maxr, maxc;
- {
- double lp, rp, v, nd;
- register r,c,n;
- register struct ent *p;
-
- n = 0;
- lp = 0;
- rp = 0;
- for (r = minr; r<=maxr; r++)
- for (c = minc; c<=maxc; c++)
- if ((p = tbl[r][c]) && p->flags&is_valid) {
- v = p->v;
- lp += v*v;
- rp += v;
- n++;
- }
-
- if ((n == 0) || (n == 1))
- return ((double) 0);
- nd = (double)n;
- return (sqrt((nd*lp-rp*rp)/(nd*(nd-1))));
- }
-
- double domax(minr, minc, maxr, maxc)
- int minr, minc, maxr, maxc;
- {
- double v;
- register r,c,count;
- register struct ent *p;
-
- count = 0;
- for (r = minr; r<=maxr; r++)
- for (c = minc; c<=maxc; c++)
- if ((p = tbl[r][c]) && p->flags&is_valid) {
- if (!count) {
- v = p->v;
- count++;
- } else if (p->v > v)
- v = p->v;
- }
-
- if (count == 0)
- return ((double) 0);
-
- return (v);
- }
-
- double domin(minr, minc, maxr, maxc)
- int minr, minc, maxr, maxc;
- {
- double v;
- register r,c,count;
- register struct ent *p;
-
- count = 0;
- for (r = minr; r<=maxr; r++)
- for (c = minc; c<=maxc; c++)
- if ((p = tbl[r][c]) && p->flags&is_valid) {
- if (!count) {
- v = p->v;
- count++;
- } else if (p->v < v)
- v = p->v;
- }
-
- if (count == 0)
- return ((double) 0);
-
- return (v);
- }
-
- double eval(e)
- register struct enode *e; {
- if (e==0) return 0;
- switch (e->op) {
- case '+': return (eval(e->e.o.left) + eval(e->e.o.right));
- case '-': return (eval(e->e.o.left) - eval(e->e.o.right));
- case '*': return (eval(e->e.o.left) * eval(e->e.o.right));
- case '/': { double denom = eval (e->e.o.right);
- return denom ? eval(e->e.o.left) / denom : 0; }
- case '^': return (pow(eval(e->e.o.left), eval(e->e.o.right)));
- case '<': return (eval(e->e.o.left) < eval(e->e.o.right));
- case '=': return (eval(e->e.o.left) == eval(e->e.o.right));
- case '>': return (eval(e->e.o.left) > eval(e->e.o.right));
- case '&': return (eval(e->e.o.left) && eval(e->e.o.right));
- case '|': return (eval(e->e.o.left) || eval(e->e.o.right));
- case '?': return eval(e->e.o.left) ? eval(e->e.o.right->e.o.left)
- : eval(e->e.o.right->e.o.right);
- case 'm': return (-eval(e->e.o.right));
- case 'f': return (eval(e->e.o.right));
- case '~': return ((double)!(int)eval(e->e.o.right));
- case 'k': return (e->e.k);
- case 'v': return (e->e.v->v);
- case O_REDUCE('+'):
- case O_REDUCE('*'):
- case O_REDUCE('a'):
- case O_REDUCE('s'):
- case O_REDUCE(MAX):
- case O_REDUCE(MIN):
- { register r,c;
- register maxr, maxc;
- register minr, minc;
- maxr = ((struct ent *) e->e.o.right) -> row;
- maxc = ((struct ent *) e->e.o.right) -> col;
- minr = ((struct ent *) e->e.o.left) -> row;
- minc = ((struct ent *) e->e.o.left) -> col;
- if (minr>maxr) r = maxr, maxr = minr, minr = r;
- if (minc>maxc) c = maxc, maxc = minc, minc = c;
- switch (e->op) {
- case O_REDUCE('+'): return dosum(minr, minc, maxr, maxc);
- case O_REDUCE('*'): return doprod(minr, minc, maxr, maxc);
- case O_REDUCE('a'): return doavg(minr, minc, maxr, maxc);
- case O_REDUCE('s'): return dostddev(minr, minc, maxr, maxc);
- case O_REDUCE(MAX): return domax(minr, minc, maxr, maxc);
- case O_REDUCE(MIN): return domin(minr, minc, maxr, maxc);
- }
- }
- case ACOS: return (acos(eval(e->e.o.right)));
- case ASIN: return (asin(eval(e->e.o.right)));
- case ATAN: return (atan(eval(e->e.o.right)));
- case CEIL: return (ceil(eval(e->e.o.right)));
- case COS: return (cos(eval(e->e.o.right)));
- case EXP: return (exp(eval(e->e.o.right)));
- case FABS: return (fabs(eval(e->e.o.right)));
- case FLOOR: return (floor(eval(e->e.o.right)));
- case HYPOT: return (hypot(eval(e->e.o.left), eval(e->e.o.right)));
- case LOG: { double arg = eval(e->e.o.right);
- return arg ? log(arg) : 0; }
- case LOG10: { double arg = eval(e->e.o.right);
- return arg ? log10(arg) : 0; }
- case POW: return (pow(eval(e->e.o.left), eval(e->e.o.right)));
- case SIN: return (sin(eval(e->e.o.right)));
- case SQRT: return (sqrt(eval(e->e.o.right)));
- case TAN: return (tan(eval(e->e.o.right)));
- case DTR: return (dtr(eval(e->e.o.right)));
- case RTD: return (rtd(eval(e->e.o.right)));
- case RND: {
- double temp;
- temp = eval(e->e.o.right);
- return(temp-floor(temp) < 0.5 ?
- floor(temp) : ceil(temp));
- }
- }
- return((double) 0.0); /* safety net */
- }
-
- #define MAXPROP 7
-
- EvalAll () {
- int repct = 0;
-
- while (RealEvalAll() && (repct++ <= MAXPROP));
- }
-
- int RealEvalAll () {
- register i,j;
- int chgct = 0;
- register struct ent *p;
- for (i=0; i<=maxrow; i++)
- for (j=0; j<=maxcol; j++)
- if ((p=tbl[i][j]) && p->expr) {
- double v = eval (p->expr);
- if (v != p->v) {
- p->v = v; chgct++;
- p->flags |= (is_changed|is_valid);
- }
- }
- return(chgct);
- }
-
- struct enode *new(op, a1, a2)
- struct enode *a1, *a2;
- {
- register struct enode *p = (struct enode *) xmalloc ((unsigned)sizeof (struct enode));
- p->op = op;
- p->e.o.left = a1;
- p->e.o.right = a2;
- return p;
- }
-
- struct enode *new_var(op, a1)
- struct ent *a1;
- {
- register struct enode *p = (struct enode *) xmalloc ((unsigned)sizeof (struct enode));
- p->op = op;
- p->e.v = a1;
- return p;
- }
-
- struct enode *new_const(op, a1)
- double a1;
- {
- register struct enode *p = (struct enode *) xmalloc ((unsigned)sizeof (struct enode));
- p->op = op;
- p->e.k = a1;
- return p;
- }
-
- copy (dv, v1, v2)
- struct ent *dv, *v1, *v2;
- {
- register r,c;
- register struct ent *p;
- register struct ent *n;
- register deltar, deltac;
- int maxr, maxc;
- int minr, minc;
- int dr, dc;
-
- dr = dv->row;
- dc = dv->col;
- maxr = v2->row;
- maxc = v2->col;
- minr = v1->row;
- minc = v1->col;
- if (minr>maxr) r = maxr, maxr = minr, minr = r;
- if (minc>maxc) c = maxc, maxc = minc, minc = c;
- if (dr+maxr-minr >= MAXROWS ||
- dc+maxc-minc >= MAXCOLS) {
- error ("The table can't be any bigger");
- return;
- }
- deltar = dr-minr;
- deltac = dc-minc;
- FullUpdate++;
- for (r = minr; r<=maxr; r++)
- for (c = minc; c<=maxc; c++) {
- n = lookat (r+deltar, c+deltac);
- clearent(n);
- if (p = tbl[r][c]) {
- n -> v = p -> v;
- n -> flags = p -> flags;
- n -> expr = copye(p->expr, deltar, deltac);
- n -> label = 0;
- if (p -> label) {
- n -> label = xmalloc ((unsigned)(strlen (p -> label) + 1));
- strcpy (n -> label, p -> label);
- }
- }
- }
- }
-
- eraser(v1, v2)
- struct ent *v1, *v2;
- {
- FullUpdate++;
- flush_saved();
- erase_area(v1->row, v1->col, v2->row, v2->col);
- sync_refs();
- }
-
- moveto(v)
- struct ent *v;
- {
- currow = v->row;
- curcol = v->col;
- }
-
- fill (v1, v2, start, inc)
- struct ent *v1, *v2;
- double start, inc;
- {
- register r,c;
- register struct ent *n;
- int maxr, maxc;
- int minr, minc;
-
- maxr = v2->row;
- maxc = v2->col;
- minr = v1->row;
- minc = v1->col;
- if (minr>maxr) r = maxr, maxr = minr, minr = r;
- if (minc>maxc) c = maxc, maxc = minc, minc = c;
- if (maxr >= MAXROWS) maxr = MAXROWS-1;
- if (maxc >= MAXCOLS) maxc = MAXCOLS-1;
- if (minr < 0) minr = 0;
- if (minr < 0) minr = 0;
-
- FullUpdate++;
- for (r = minr; r<=maxr; r++)
- for (c = minc; c<=maxc; c++) {
- n = lookat (r, c);
- clearent(n);
- n->v = start;
- start += inc;
- n->flags |= (is_changed|is_valid);
- }
- }
-
- let (v, e)
- struct ent *v;
- struct enode *e; {
- efree (v->expr);
- if (constant(e)) {
- v->v = eval(e);
- v->expr = 0;
- efree(e);
- } else
- v->expr = e;
- v->flags |= (is_changed|is_valid);
- changed++;
- modflg++;
- }
-
- clearent (v)
- struct ent *v; {
- if (!v)
- return;
- label(v,"",-1);
- v->v = 0;
- if (v->expr)
- efree(v->expr);
- v->expr = 0;
- v->flags |= (is_changed);
- v->flags &= ~(is_valid);
- changed++;
- modflg++;
- }
-
- constant(e)
- register struct enode *e; {
- return e==0 || e->op == O_CONST
- || (e->op != O_VAR
- && (e->op&~0177) != O_REDUCE(0)
- && constant (e->e.o.left)
- && constant(e->e.o.right));
- }
-
- efree (e)
- register struct enode *e; {
- if (e) {
- if (e->op != O_VAR && e->op !=O_CONST && (e->op&~0177) != O_REDUCE(0)) {
- efree (e->e.o.left);
- efree (e->e.o.right);
- }
- xfree ((char *)e);
- }
- }
-
- label (v, s, flushdir)
- register struct ent *v;
- register char *s; {
- if (v) {
- if (flushdir==0 && v->flags&is_valid) {
- register struct ent *tv;
- if (v->col>0 && ((tv=lookat(v->row,v->col-1))->flags&is_valid)==0)
- v = tv, flushdir = 1;
- else if (((tv=lookat (v->row,v->col+1))->flags&is_valid)==0)
- v = tv, flushdir = -1;
- else flushdir = -1;
- }
- if (v->label) xfree((char *)(v->label));
- if (s && s[0]) {
- v->label = xmalloc ((unsigned)(strlen(s)+1));
- strcpy (v->label, s);
- } else v->label = 0;
- v->flags |= is_lchanged;
- if (flushdir<0) v->flags |= is_leftflush;
- else v->flags &= ~is_leftflush;
- FullUpdate++;
- modflg++;
- }
- }
-
- decodev (v)
- register struct ent *v;
- {
- register struct range *r;
-
- if (!v) sprintf (line+linelim,"VAR?");
- else if (r = find_range((char *)0, 0, v, v))
- sprintf(line+linelim, "%s", r->r_name);
- else
- sprintf (line+linelim, "%s%d", coltoa(v->col), v->row);
- linelim += strlen (line+linelim);
- }
-
- char *
- coltoa(col)
- int col;
- {
- static char rname[3];
- register char *p = rname;
-
- if (col > 25) {
- *p++ = col/26 + 'A' - 1;
- col %= 26;
- }
- *p++ = col+'A';
- *p = 0;
- return(rname);
- }
-
- decompile(e, priority)
- register struct enode *e; {
- register char *s;
- if (e) {
- int mypriority;
- switch (e->op) {
- default: mypriority = 99; break;
- case '?': mypriority = 1; break;
- case ':': mypriority = 2; break;
- case '|': mypriority = 3; break;
- case '&': mypriority = 4; break;
- case '<': case '=': case '>': mypriority = 6; break;
- case '+': case '-': mypriority = 8; break;
- case '*': case '/': mypriority = 10; break;
- case '^': mypriority = 12; break;
- }
- if (mypriority<priority) line[linelim++] = '(';
- switch (e->op) {
- case 'f': {
- for (s="fixed "; line[linelim++] = *s++;);
- linelim--;
- decompile (e->e.o.right, 30);
- break;
- }
- case 'm': line[linelim++] = '-';
- decompile (e->e.o.right, 30);
- break;
- case '~': line[linelim++] = '~';
- decompile (e->e.o.right, 30);
- break;
- case 'v': decodev (e->e.v);
- break;
- case 'k': sprintf (line+linelim,"%.15g",e->e.k);
- linelim += strlen (line+linelim);
- break;
- case O_REDUCE('+'):
- s = "@sum("; goto more;
- case O_REDUCE('*'):
- s = "@prod("; goto more;
- case O_REDUCE('s'):
- s = "@stddev("; goto more;
- case O_REDUCE(MAX):
- s = "@max("; goto more;
- case O_REDUCE(MIN):
- s = "@min("; goto more;
- case O_REDUCE('a'):
- s = "@avg("; /* fall though to more; */
- more: {
- struct range *r;
-
- for (; line[linelim++] = *s++;);
- linelim--;
- if (r = find_range((char *)0, 0,
- (struct ent *) e->e.o.left,
- (struct ent *) e->e.o.right)) {
- sprintf(line+linelim, "%s", r->r_name);
- linelim += strlen(line+linelim);
- } else {
- decodev ((struct ent *) e->e.o.left);
- line[linelim++] = ':';
- decodev ((struct ent *) e->e.o.right);
- }
- line[linelim++] = ')';
- break;
- }
- case ACOS: s = "@acos("; goto more1;
- case ASIN: s = "@asin("; goto more1;
- case ATAN: s = "@atan("; goto more1;
- case CEIL: s = "@ceil("; goto more1;
- case COS: s = "@cos("; goto more1;
- case EXP: s = "@exp("; goto more1;
- case FABS: s = "@fabs("; goto more1;
- case FLOOR: s = "@floor("; goto more1;
- case HYPOT: s = "@hypot("; goto more2;
- case LOG: s = "@ln("; goto more1;
- case LOG10: s = "@log("; goto more1;
- case POW: s = "@pow("; goto more2;
- case SIN: s = "@sin("; goto more1;
- case SQRT: s = "@sqrt("; goto more1;
- case TAN: s = "@tan("; goto more1;
- case DTR: s = "@dtr("; goto more1;
- case RTD: s = "@rtd("; goto more1;
- case RND: s = "@rnd("; goto more1;
- more1: for (; line[linelim++] = *s++;);
- linelim--;
- decompile (e->e.o.right, 0);
- line[linelim++] = ')';
- break;
- more2: for (; line[linelim++] = *s++;);
- linelim--;
- decompile (e->e.o.left, 0);
- line[linelim++] = ',';
- decompile (e->e.o.right, 0);
- line[linelim++] = ')';
- break;
-
- default: decompile (e->e.o.left, mypriority);
- line[linelim++] = e->op;
- decompile (e->e.o.right, mypriority+1);
- break;
- }
- if (mypriority<priority) line[linelim++] = ')';
- } else line[linelim++] = '?';
- }
-
- editv (row, col) {
- sprintf (line, "let %s = ", v_name(row, col));
- linelim = strlen(line);
- editexp(row,col);
- }
-
- editexp(row,col) {
- register struct ent *p;
- p = lookat (row, col);
- if (p->flags&is_valid)
- if (p->expr) {
- decompile (p->expr, 0);
- line[linelim] = 0;
- } else {
- sprintf (line+linelim, "%.15g", p->v);
- linelim += strlen (line+linelim);
- }
- }
-
- edits (row, col) {
- register struct ent *p = lookat (row, col);
- sprintf (line, "%sstring %s = \"",
- ((p->flags&is_leftflush) ? "left" : "right"),
- v_name(row, col));
- linelim = strlen(line);
- if (p->label) {
- sprintf (line+linelim, "%s", p->label);
- linelim += strlen (line+linelim);
- }
- }
-
- printfile (fname)
- char *fname;
- {
- FILE *f;
- char pline[1000];
- int plinelim;
- int pid;
- register row, col;
- register struct ent **p;
-
- f = openout(fname, &pid);
-
- if (f==0) {
- error ("Can't create %s", fname);
- return;
- }
- for (row=0;row<=maxrow; row++) {
- register c = 0;
- pline[plinelim=0] = '\0';
- for (p = &tbl[row][col=0]; col<=maxcol; col++, p++) {
- if (*p) {
- char *s;
- while (plinelim<c) pline[plinelim++] = ' ';
- plinelim = c;
- if ((*p)->flags&is_valid) {
- sprintf (pline+plinelim,"%*.*f",fwidth[col],precision[col],
- (*p)->v);
- plinelim += strlen (pline+plinelim);
- }
- if (s = (*p)->label) {
- register char *d;
- d = pline+((*p)->flags&is_leftflush
- ? c : c-strlen(s)+fwidth[col]);
- while (d>pline+plinelim) pline[plinelim++] = ' ';
- if (d<pline) d = pline;
- while (*s) *d++ = *s++;
- if (d-pline>plinelim) plinelim = d-pline;
- }
- }
- c += fwidth [col];
- }
- fprintf (f,"%.*s\n",plinelim,pline);
- }
-
- closeout(f, pid);
- }
-
- tblprintfile (fname)
- char *fname;
- {
- FILE *f;
- char pline[1000];
- int pid;
- register row, col;
- register struct ent **p;
- char coldelim = DEFCOLDELIM;
-
- f = openout(fname, &pid);
-
- if (f==0) {
- error ("Can't create %s", fname);
- return;
- }
- for (row=0;row<=maxrow; row++) {
- for (p = &tbl[row][col=0]; col<=maxcol; col++, p++) {
- if (*p) {
- char *s;
- if ((*p)->flags&is_valid) {
- fprintf (f,"%.*f",precision[col],
- (*p)->v);
- }
- if (s = (*p)->label) {
- fprintf (f,"%s",s);
- }
- }
- fprintf(f,"%c",coldelim);
- }
- fprintf (f,"\n",pline);
- }
-
- closeout(f, pid);
- }
-
- struct enode *copye (e, Rdelta, Cdelta)
- register struct enode *e; {
- register struct enode *ret;
- if (e==0) ret = 0;
- else {
- ret = (struct enode *) xmalloc ((unsigned) sizeof (struct enode));
- ret->op = e->op;
- switch (ret->op) {
- case 'v':
- ret->e.v = lookat (e->e.v->row+Rdelta, e->e.v->col+Cdelta);
- break;
- case 'k':
- ret->e.k = e->e.k;
- break;
- case 'f':
- ret->e.o.right = copye (e->e.o.right,0,0);
- ret->e.o.left = 0;
- break;
- case O_REDUCE('+'):
- case O_REDUCE('*'):
- case O_REDUCE('a'):
- case O_REDUCE('s'):
- case O_REDUCE(MAX):
- case O_REDUCE(MIN):
- ret->e.o.right = (struct enode *) lookat (
- ((struct ent *)e->e.o.right)->row+Rdelta,
- ((struct ent *)e->e.o.right)->col+Cdelta
- );
- ret->e.o.left = (struct enode *) lookat (
- ((struct ent *)e->e.o.left)->row+Rdelta,
- ((struct ent *)e->e.o.left)->col+Cdelta
- );
- break;
- default:
- ret->e.o.right = copye (e->e.o.right,Rdelta,Cdelta);
- ret->e.o.left = copye (e->e.o.left,Rdelta,Cdelta);
- break;
- }
- }
- return ret;
- }
-
- /*
- * sync_refs and syncref are used to remove references to
- * deleted struct ents. Note that the deleted structure must still
- * be hanging around before the call, but not referenced by an entry
- * in tbl. Thus the free_ent, fix_ent calls in sc.c
- */
-
- sync_refs () {
- register i,j;
- register struct ent *p;
- sync_ranges();
- for (i=0; i<=maxrow; i++)
- for (j=0; j<=maxcol; j++)
- if ((p=tbl[i][j]) && p->expr)
- syncref(p->expr);
- }
-
-
- syncref(e)
- register struct enode *e;
- {
- if (e==0)
- return;
- else {
- switch (e->op) {
- case 'v':
- e->e.v = lookat(e->e.v->row, e->e.v->col);
- break;
- case 'k':
- break;
- case O_REDUCE('+'):
- case O_REDUCE('*'):
- case O_REDUCE('a'):
- case O_REDUCE('s'):
- case O_REDUCE(MAX):
- case O_REDUCE(MIN):
- e->e.o.right = (struct enode *) lookat (
- ((struct ent *)e->e.o.right)->row,
- ((struct ent *)e->e.o.right)->col
- );
- e->e.o.left = (struct enode *) lookat (
- ((struct ent *)e->e.o.left)->row,
- ((struct ent *)e->e.o.left)->col
- );
- break;
- default:
- syncref(e->e.o.right);
- syncref(e->e.o.left);
- break;
- }
- }
- }
-
- hiderow(arg)
- {
- register int r1;
- register int r2;
-
- r1 = currow;
- r2 = r1 + arg - 1;
- if (r1 < 0 || r1 > r2) {
- error("Invalid Range");
- return;
- }
- if (r2 > MAXROWS-2) {
- error("You can't hide the last row");
- return;
- }
- FullUpdate++;
- while (r1 <= r2)
- row_hidden[r1++] = 1;
- }
-
- hidecol(arg)
- {
- register int c1;
- register int c2;
-
- c1 = curcol;
- c2 = c1 + arg - 1;
- if (c1 < 0 || c1 > c2) {
- error("Invalid Range");
- return;
- }
- if (c2 > MAXCOLS-2) {
- error("You can't hide the last col");
- return;
- }
- FullUpdate++;
- while (c1 <= c2)
- col_hidden[c1++] = 1;
- }
-
- showrow(r1, r2)
- {
- if (r1 < 0 || r1 > r2) {
- error("Invalid Range");
- return;
- }
- if (r2 > MAXROWS-1) {
- r2 = MAXROWS-1;
- }
- FullUpdate++;
- while (r1 <= r2)
- row_hidden[r1++] = 0;
- }
-
- showcol(c1, c2)
- {
- if (c1 < 0 || c1 > c2) {
- error("Invalid Range");
- return;
- }
- if (c2 > MAXCOLS-1) {
- c2 = MAXCOLS-1;
- }
- FullUpdate++;
- while (c1 <= c2)
- col_hidden[c1++] = 0;
- }
-
- /* Open the output file, setting up a pipe if needed */
-
- FILE *
- openout(fname, rpid)
- char *fname;
- int *rpid;
- {
- int pipefd[2];
- int pid;
- FILE *f;
-
- while (*fname && (*fname == ' ')) /* Skip leading blanks */
- fname++;
-
- if (*fname != '|') { /* Open file if not pipe */
- *rpid = 0;
- return(fopen(fname, "w"));
- }
-
- fname++; /* Skip | */
- deraw();
- pipe (pipefd); /* make pipe to child */
-
- if ((pid=fork()) == 0) /* if child */
- {
- close (0); /* close stdin */
- close (pipefd[1]);
- dup (pipefd[0]); /* connect to pipe input */
- execl ("/bin/sh", "sh", "-c", fname, 0);
- exit (-127);
- }
- else /* else parent */
- {
- *rpid = pid;
- f = fdopen (pipefd[1], "w");
- if (f == 0)
- {
- kill (pid, -9);
- error ("Can't fdopen output");
- close (pipefd[1]);
- *rpid = 0;
- return(0);
- }
- }
- return(f);
- }
-
- closeout(f, pid)
- FILE *f;
- int pid;
- {
- int temp;
-
- fclose (f);
- if (pid) {
- while (pid != wait(&temp)) /**/;
- printf("Press <return> to continue\n");
- (void)nmgetch();
- goraw();
- }
- }
- \SHAR\EOF\
- else
- echo "will not over write ./interp.c"
- fi
- if [ `wc -c ./interp.c | awk '{printf $1}'` -ne 20553 ]
- then
- echo `wc -c ./interp.c | awk '{print "Got " $1 ", Expected " 20553}'`
- fi
- if `test ! -s ./cmds.c`
- then
- echo "writing ./cmds.c"
- cat > ./cmds.c << '\SHAR\EOF\'
- /* SC A Spreadsheet Calculator
- * Main driver
- *
- * original by James Gosling, September 1982
- * modifications by Mark Weiser and Bruce Israel,
- * University of Maryland
- *
- * More mods Robert Bond, 12/86
- *
- */
-
- #include <curses.h>
- #include "sc.h"
-
- #ifdef BSD42
- #include <strings.h>
- #else
- #ifndef SYSIII
- #include <string.h>
- #endif
- #endif
-
- char *xmalloc();
-
- duprow()
- {
- if (currow >= MAXROWS - 1 || maxrow >= MAXROWS - 1) {
- error ("The table can't be any bigger");
- return;
- }
- modflg++;
- currow++;
- openrow (currow);
- for (curcol = 0; curcol <= maxcol; curcol++) {
- register struct ent *p = tbl[currow - 1][curcol];
- if (p) {
- register struct ent *n;
- n = lookat (currow, curcol);
- n -> v = p -> v;
- n -> flags = p -> flags;
- n -> expr = copye (p -> expr, 1, 0);
- n -> label = 0;
- if (p -> label) {
- n -> label = (char *)
- xmalloc ((unsigned)(strlen (p -> label) + 1));
- strcpy (n -> label, p -> label);
- }
- }
- }
- for (curcol = 0; curcol <= maxcol; curcol++) {
- register struct ent *p = tbl[currow][curcol];
- if (p && (p -> flags & is_valid) && !p -> expr)
- break;
- }
- if (curcol > maxcol)
- curcol = 0;
- }
-
- dupcol()
- {
- if (curcol >= MAXCOLS - 1 || maxcol >= MAXCOLS - 1) {
- error ("The table can't be any wider");
- return;
- }
- modflg++;
- curcol++;
- opencol (curcol);
- for (currow = 0; currow <= maxrow; currow++) {
- register struct ent *p = tbl[currow][curcol - 1];
- if (p) {
- register struct ent *n;
- n = lookat (currow, curcol);
- n -> v = p -> v;
- n -> flags = p -> flags;
- n -> expr = copye (p -> expr, 0, 1);
- n -> label = 0;
- if (p -> label) {
- n -> label = (char *)
- xmalloc ((unsigned) (strlen (p -> label) + 1));
- strcpy (n -> label, p -> label);
- }
- }
- }
- for (currow = 0; currow <= maxrow; currow++) {
- register struct ent *p = tbl[currow][curcol];
- if (p && (p -> flags & is_valid) && !p -> expr)
- break;
- }
- if (currow > maxrow)
- currow = 0;
- }
-
- insertrow(arg)
- {
- while (--arg>=0) openrow (currow);
- }
-
- deleterow(arg)
- {
- flush_saved();
- erase_area(currow, 0, currow + arg - 1, maxcol);
- currow += arg;
- while (--arg>=0) closerow (--currow);
- sync_refs();
- }
-
- insertcol(arg)
- {
- while (--arg>=0) opencol(curcol);
- }
-
- deletecol(arg)
- {
- flush_saved();
- erase_area(0, curcol, maxrow, curcol + arg - 1);
- curcol += arg;
- while (--arg>=0) closecol (--curcol);
- sync_refs();
- }
-
- rowvalueize(arg)
- {
- valueize_area(currow, 0, currow + arg - 1, maxcol);
- }
-
- colvalueize(arg)
- {
- valueize_area(0, curcol, maxrow, curcol + arg - 1);
- }
-
- erase_area(sr, sc, er, ec)
- int sr, sc, er, ec;
- {
- register int r, c;
- register struct ent **p;
-
- if (sr > er) {
- r = sr; sr = er; er= r;
- }
-
- if (sc > ec) {
- c = sc; sc = ec; ec= c;
- }
-
- if (sr < 0)
- sr = 0;
- if (sc < 0)
- sc = 0;
- if (er >= MAXROWS)
- er = MAXROWS-1;
- if (ec >= MAXCOLS)
- ec = MAXCOLS-1;
-
- for (r = sr; r <= er; r++) {
- for (c = sc; c <= ec; c++) {
- p = &tbl[r][c];
- if (*p) {
- free_ent(*p);
- *p = 0;
- }
- }
- }
-
- }
-
- valueize_area(sr, sc, er, ec)
- int sr, sc, er, ec;
- {
- register int r, c;
- register struct ent *p;
-
- if (sr > er) {
- r = sr; sr = er; er= r;
- }
-
- if (sc > ec) {
- c = sc; sc = ec; ec= c;
- }
-
- if (sr < 0)
- sr = 0;
- if (sc < 0)
- sc = 0;
- if (er >= MAXROWS)
- er = MAXROWS-1;
- if (ec >= MAXCOLS)
- ec = MAXCOLS-1;
-
- for (r = sr; r <= er; r++) {
- for (c = sc; c <= ec; c++) {
- p = tbl[r][c];
- if (p && p->expr) {
- efree(p->expr);
- p->expr = 0;
- }
- }
- }
-
- }
-
- pullcells(to_insert)
- {
- register struct ent *p, *n;
- register int deltar, deltac;
- int minrow, mincol;
- int maxrow, maxcol;
- int numrows, numcols;
-
- if (!to_fix)
- return;
-
- switch (to_insert) {
- case 'm':
- case 'r':
- case 'c':
- break;
- default:
- error("Invalid pull command");
- return;
- }
-
- minrow = MAXROWS;
- mincol = MAXCOLS;
- maxrow = 0;
- maxcol = 0;
-
- for (p = to_fix; p; p = p->next) {
- if (p->row < minrow)
- minrow = p->row;
- if (p->row > maxrow)
- maxrow = p->row;
- if (p->col < mincol)
- mincol = p->col;
- if (p->col > maxcol)
- maxcol = p->col;
- }
-
- numrows = maxrow - minrow + 1;
- numcols = maxcol - mincol + 1;
- deltar = currow - minrow;
- deltac = curcol - mincol;
-
- if (to_insert == 'r') {
- insertrow(numrows);
- deltac = 0;
- } else if (to_insert == 'c') {
- insertcol(numcols);
- deltar = 0;
- }
-
- FullUpdate++;
- modflg++;
-
- for (p = to_fix; p; p = p->next) {
- n = lookat (p->row + deltar, p->col + deltac);
- clearent(n);
- n -> flags = p -> flags & ~is_deleted;
- n -> v = p -> v;
- n -> expr = copye(p->expr, deltar, deltac);
- n -> label = 0;
- if (p -> label) {
- n -> label = (char *)
- xmalloc((unsigned)(strlen(p->label)+1));
- strcpy (n -> label, p -> label);
- }
- }
- }
-
- colshow_op()
- {
- register int i,j;
- for (i=0; i<MAXCOLS; i++)
- if (col_hidden[i])
- break;
- for(j=i; j<MAXCOLS; j++)
- if (!col_hidden[j])
- break;
- j--;
- if (i<MAXCOLS) {
- sprintf(line,"show %s:", coltoa(i));
- sprintf(line + strlen(line),"%s",coltoa(j));
- linelim = strlen (line);
- }
- }
-
- rowshow_op()
- {
- register int i,j;
- for (i=0; i<MAXROWS; i++)
- if (row_hidden[i])
- break;
- for(j=i; j<MAXROWS; j++)
- if (!row_hidden[j]) {
- break;
- }
- j--;
- if (i<MAXROWS) {
- sprintf(line,"show %d:%d", i, j);
- linelim = strlen (line);
- }
- }
-
- get_qual()
- {
- register int c;
-
- c = nmgetch();
- switch (c) {
- case 'c':
- case 'j':
- case 'k':
- case ctl(p):
- case ctl(n):
- return('c');
- case 'r':
- case 'l':
- case 'h':
- case ctl(f):
- case ctl(b):
- return('r');
- default:
- return(c);
- }
- /*NOTREACHED*/
- }
-
- openrow (rs) {
- register r;
- register struct ent **p;
- register c;
- register i;
-
- if (rs > maxrow) maxrow = rs;
- if (maxrow >= MAXROWS - 1 || rs > MAXROWS - 1) {
- error ("The table can't be any longer");
- return;
- }
- for (i = maxrow+1; i > rs; i--) {
- row_hidden[i] = row_hidden[i-1];
- }
- for (r = ++maxrow; r > rs; r--)
- for (c = maxcol + 1, p = &tbl[r][0]; --c >= 0; p++)
- if (p[0] = p[-MAXCOLS])
- p[0] -> row++;
- p = &tbl[rs][0];
- for (c = maxcol + 1; --c >= 0;)
- *p++ = 0;
- FullUpdate++;
- modflg++;
- }
-
- closerow (r)
- register r; {
- register struct ent **p;
- register c;
- register int i;
-
- if (r > maxrow) return;
-
- p = &tbl[r][0];
- for (c=maxcol+1; --c>=0; ) {
- if (*p)
- free_ent(*p);
- *p++ = 0;
- }
-
- for (i = r; i < MAXROWS - 1; i++) {
- row_hidden[i] = row_hidden[i+1];
- }
-
- while (r<maxrow) {
- for (c = maxcol+1, p = &tbl[r][0]; --c>=0; p++)
- if (p[0] = p[MAXCOLS])
- p[0]->row--;
- r++;
- }
-
- p = &tbl[maxrow][0];
- for (c=maxcol+1; --c>=0; ) *p++ = 0;
- maxrow--;
- FullUpdate++;
- modflg++;
- }
-
- opencol (cs) {
- register r;
- register struct ent **p;
- register c;
- register lim = maxcol-cs+1;
- int i;
-
- if (cs > maxcol) maxcol = cs;
- if (maxcol >= MAXCOLS - 1 || cs > MAXCOLS - 1) {
- error ("The table can't be any wider");
- return;
- }
- for (i = maxcol+1; i > cs; i--) {
- fwidth[i] = fwidth[i-1];
- precision[i] = precision[i-1];
- col_hidden[i] = col_hidden[i-1];
- }
- /* fwidth[cs] = DEFWIDTH;
- precision[i] = DEFPREC; */
-
- for (r=0; r<=maxrow; r++) {
- p = &tbl[r][maxcol+1];
- for (c=lim; --c>=0; p--)
- if (p[0] = p[-1])
- p[0]->col++;
- p[0] = 0;
- }
- maxcol++;
- FullUpdate++;
- modflg++;
- }
-
- closecol (cs) {
- register r;
- register struct ent **p;
- register struct ent *q;
- register c;
- register lim = maxcol-cs;
- int i;
-
- if (lim < 0) return;
-
- for (r=0; r<=maxrow; r++)
- if (q = tbl[r][cs]) {
- free_ent(q);
- }
-
- for (r=0; r<=maxrow; r++) {
- p = &tbl[r][cs];
- for (c=lim; --c>=0; p++)
- if (p[0] = p[1])
- p[0]->col--;
- p[0] = 0;
- }
-
- for (i = cs; i < MAXCOLS - 1; i++) {
- fwidth[i] = fwidth[i+1];
- precision[i] = precision[i+1];
- col_hidden[i] = col_hidden[i+1];
- }
-
- maxcol--;
- FullUpdate++;
- modflg++;
- }
-
- \SHAR\EOF\
- else
- echo "will not over write ./cmds.c"
- fi
- if [ `wc -c ./cmds.c | awk '{printf $1}'` -ne 8123 ]
- then
- echo `wc -c ./cmds.c | awk '{print "Got " $1 ", Expected " 8123}'`
- fi
- if `test ! -s ./crypt.c`
- then
- echo "writing ./crypt.c"
- cat > ./crypt.c << '\SHAR\EOF\'
- /*
- * Encryption utilites
- * Bradley Williams
- * {allegra,ihnp4,uiucdcs,ctvax}!convex!williams
- */
-
- #include <stdio.h>
- #include <curses.h>
-
- #if defined(BSD42) || defined(BSD43)
- #include <sys/file.h>
- #else
- #include <sys/fcntl.h>
- #endif
-
- #include "sc.h"
-
- extern char curfile[];
- char *strcpy();
- int Crypt = 0;
-
- #define DEFWIDTH 10
- #define DEFPREC 2
-
- creadfile (fname, eraseflg)
- char *fname;
- {
- register FILE *f;
- int pipefd[2];
- int fildes;
- int pid;
- char save[1024];
-
- if (*fname == 0) fname = &curfile[0];
- strcpy(save,fname);
-
- if (eraseflg && strcmp(fname,curfile) && modcheck(" first")) return;
-
- fildes = open (save, O_RDONLY, 0);
- if (fildes < 0)
- {
- error ("Can't read %s", save);
- return;
- }
-
- if (eraseflg) erasedb ();
-
- pipe (pipefd); /* make pipe to child */
- deraw();
- if ((pid=fork()) == 0) /* if child */
- {
- close (0); /* close stdin */
- close (1); /* close stdout */
- close (pipefd[0]); /* close pipe input */
- dup (fildes); /* standard in from file */
- dup (pipefd[1]); /* connect to pipe */
- fprintf (stderr, " ");
- execl ("/bin/sh", "sh", "-c", "crypt", 0);
- exit (-127);
- }
- else /* else parent */
- {
- close (fildes);
- close (pipefd[1]); /* close pipe output */
- f = fdopen (pipefd[0], "r");
- if (f == 0)
- {
- kill (pid, -9);
- error ("Can't fdopen file %s", save);
- close (pipefd[0]);
- return;
- }
- }
-
- while (fgets(line,sizeof line,f)) {
- linelim = 0;
- if (line[0] != '#') yyparse ();
- }
- fclose (f);
- close (pipefd[0]);
- while (pid != wait(&fildes)) /**/;
- goraw();
- linelim = -1;
- modflg++;
- if (eraseflg) {
- strcpy (curfile,save);
- modflg = 0;
- }
- EvalAll();
- }
-
- cwritefile (fname)
- char *fname;
- {
- register FILE *f;
- register struct ent **p;
- register r, c;
- int pipefd[2];
- int fildes;
- int pid;
- char save[1024];
-
- if (*fname == 0) fname = &curfile[0];
-
- strcpy(save,fname);
-
- fildes = open (save, O_WRONLY|O_CREAT, 0600);
- if (fildes < 0)
- {
- error ("Can't create %s", save);
- return(-1);
- }
-
- pipe (pipefd); /* make pipe to child */
- deraw();
- if ((pid=fork()) == 0) /* if child */
- {
- close (0); /* close stdin */
- close (1); /* close stdout */
- close (pipefd[1]); /* close pipe output */
- dup (pipefd[0]); /* connect to pipe input */
- dup (fildes); /* standard out to file */
- fprintf (stderr, " ");
- execl ("/bin/sh", "sh", "-c", "crypt", 0);
- exit (-127);
- }
- else /* else parent */
- {
- close (fildes);
- close (pipefd[0]); /* close pipe input */
- f = fdopen (pipefd[1], "w");
- if (f == 0)
- {
- kill (pid, -9);
- error ("Can't fdopen file %s", save);
- close (pipefd[1]);
- return(-1);
- }
- }
-
- fprintf (f, "# This data file was generated by the Spreadsheet ");
- fprintf (f, "Calculator.\n");
- fprintf (f, "# You almost certainly shouldn't edit it.\n\n");
- for (c=0; c<MAXCOLS; c++)
- if (fwidth[c] != DEFWIDTH || precision[c] != DEFPREC)
- fprintf (f, "format %s %d %d\n",coltoa(c),fwidth[c],precision[c]);
- for (r=0; r<=maxrow; r++) {
- p = &tbl[r][0];
- for (c=0; c<=maxcol; c++, p++)
- if (*p) {
- if ((*p)->label)
- fprintf (f, "%sstring %s%d = \"%s\"\n",
- (*p)->flags&is_leftflush ? "left" : "right",
- coltoa(c),r,(*p)->label);
- if ((*p)->flags&is_valid) {
- editv (r, c);
- fprintf (f, "%s\n",line);
- }
- }
- }
- fclose (f);
- close (pipefd[1]);
- while (pid != wait(&fildes)) /**/;
- strcpy(curfile,save);
-
- modflg = 0;
- error("File '%s' written.",curfile);
- goraw();
- return(0);
- }
- \SHAR\EOF\
- else
- echo "will not over write ./crypt.c"
- fi
- if [ `wc -c ./crypt.c | awk '{printf $1}'` -ne 3654 ]
- then
- echo `wc -c ./crypt.c | awk '{print "Got " $1 ", Expected " 3654}'`
- fi
- if `test ! -s ./xmalloc.c`
- then
- echo "writing ./xmalloc.c"
- cat > ./xmalloc.c << '\SHAR\EOF\'
- /*
- * A safer saner malloc, for careless programmers
- * (I guess I qualify! - rgb)
- */
-
- #include <stdio.h>
- #include <curses.h>
-
- extern char *malloc();
-
- char *
- xmalloc(n)
- unsigned n;
- {
- register char *ptr;
-
- if ((ptr = malloc(n + sizeof(int))) == NULL)
- fatal("xmalloc: no memory");
- *((int *) ptr) = 12345; /* magic number */
- return(ptr + sizeof(int));
- }
-
- xfree(p)
- char *p;
- {
- if (p == NULL)
- fatal("xfree: NULL");
- p -= sizeof(int);
- if (*((int *) p) != 12345)
- fatal("xfree: storage not malloc'ed");
- free(p);
- }
-
- fatal(str)
- char *str;
- {
- deraw();
- fprintf(stderr,"%s\n", str);
- exit(1);
- }
- \SHAR\EOF\
- else
- echo "will not over write ./xmalloc.c"
- fi
- if [ `wc -c ./xmalloc.c | awk '{printf $1}'` -ne 603 ]
- then
- echo `wc -c ./xmalloc.c | awk '{print "Got " $1 ", Expected " 603}'`
- fi
- if `test ! -s ./range.c`
- then
- echo "writing ./range.c"
- cat > ./range.c << '\SHAR\EOF\'
-
- /* SC A Spreadsheet Calculator
- * Range Manipulations
- *
- * Robert Bond, 4/87
- *
- */
-
- #include <stdio.h>
- #include <curses.h>
- #include <ctype.h>
- #include "sc.h"
-
- #ifdef BSD42
- #include <strings.h>
- #else
- #ifndef SYSIII
- #include <string.h>
- #endif
- #endif
-
- char *xmalloc();
-
- static struct range *rng_base;
-
- add_range(name, left, right)
- char *name;
- struct ent *left, *right;
- {
- struct range *r;
- register char *p;
- int len;
-
- if (find_range(name, strlen(name), (struct ent *)0, (struct ent *)0)) {
- error("Error: range name already defined");
- return;
- }
-
- if (strlen(name) <=2) {
- error("Invalid range name - too short");
- return;
- }
-
- for(p=name, len=0; *p; p++, len++)
- if (!((isalpha(*p) && (len<=2)) ||
- ((isdigit(*p) || isalpha(*p) || (*p == '_')) && (len>2)))) {
- error("Invalid range name - illegal combination");
- return;
- }
-
- r = (struct range *)xmalloc((unsigned)sizeof(struct range));
- r->r_name = name;
- r->r_left = left;
- r->r_right = right;
- r->r_next = rng_base;
- r->r_prev = 0;
- if (rng_base)
- rng_base->r_prev = r;
- rng_base = r;
- }
-
- del_range(left, right)
- struct ent *left, *right;
- {
- register struct range *r;
-
- if (!(r = find_range((char *)0, 0, left, right)))
- return;
-
- if (r->r_next)
- r->r_next->r_prev = r->r_prev;
- if (r->r_prev)
- r->r_prev->r_next = r->r_next;
- else
- rng_base = r->r_next;
- xfree((char *)(r->r_name));
- xfree((char *)r);
- }
-
- /* Match on name or lmatch, rmatch */
-
- struct range *
- find_range(name, len, lmatch, rmatch)
- char *name;
- int len;
- struct ent *lmatch;
- struct ent *rmatch;
- {
- struct range *r;
- register char *rp, *np;
- register int c;
-
- if (name) {
- for (r = rng_base; r; r = r->r_next) {
- for (np = name, rp = r->r_name, c = len;
- c && *rp && (*rp == *np);
- rp++, np++, c--) /* */;
- if (!c && !*rp)
- return(r);
- }
- return(0);
- }
-
- for (r = rng_base; r; r= r->r_next) {
- if ((lmatch == r->r_left) && (rmatch == r->r_right))
- return(r);
- }
- return(0);
- }
-
- sync_ranges()
- {
- register struct range *r;
-
- r = rng_base;
- while(r) {
- r->r_left = lookat(r->r_left->row, r->r_left->col);
- r->r_right = lookat(r->r_right->row, r->r_right->col);
- r = r->r_next;
- }
- }
-
- write_range(f)
- FILE *f;
- {
- register struct range *r;
-
- for (r = rng_base; r; r = r->r_next) {
- fprintf(f, "define \"%s\" %s%d", r->r_name, coltoa(r->r_left->col),
- r->r_left->row);
- if (r->r_left != r->r_right)
- fprintf(f, ":%s%d\n", coltoa(r->r_right->col), r->r_right->row);
- else
- fprintf(f, "\n");
- }
- }
-
- list_range(f)
- FILE *f;
- {
- register struct range *r;
-
- for (r = rng_base; r; r = r->r_next) {
- fprintf(f, "%-30s %s%d", r->r_name, coltoa(r->r_left->col),
- r->r_left->row);
- if (r->r_left != r->r_right)
- fprintf(f, ":%s%d\n", coltoa(r->r_right->col), r->r_right->row);
- else
- fprintf(f, "\n");
-
- }
- }
-
- char *
- v_name(row, col)
- int row, col;
- {
- struct ent *v;
- struct range *r;
- static char buf[20];
-
- v = lookat(row, col);
- if (r = find_range((char *)0, 0, v, v)) {
- return(r->r_name);
- } else {
- sprintf(buf, "%s%d", coltoa(col), row);
- return buf;
- }
- }
- \SHAR\EOF\
- else
- echo "will not over write ./range.c"
- fi
- if [ `wc -c ./range.c | awk '{printf $1}'` -ne 3211 ]
- then
- echo `wc -c ./range.c | awk '{print "Got " $1 ", Expected " 3211}'`
- fi
- if `test ! -s ./eres.sed`
- then
- echo "writing ./eres.sed"
- cat > ./eres.sed << '\SHAR\EOF\'
- /%token.*K_/!d
- /%token.*K_\(.*\)/s// "\1", K_\1,/
- \SHAR\EOF\
- else
- echo "will not over write ./eres.sed"
- fi
- if [ `wc -c ./eres.sed | awk '{printf $1}'` -ne 50 ]
- then
- echo `wc -c ./eres.sed | awk '{print "Got " $1 ", Expected " 50}'`
- fi
- if `test ! -s ./sres.sed`
- then
- echo "writing ./sres.sed"
- cat > ./sres.sed << '\SHAR\EOF\'
- /%token.*S_/!d
- /%token.*S_\(.*\)/s// "\1", S_\1,/
- \SHAR\EOF\
- else
- echo "will not over write ./sres.sed"
- fi
- if [ `wc -c ./sres.sed | awk '{printf $1}'` -ne 50 ]
- then
- echo `wc -c ./sres.sed | awk '{print "Got " $1 ", Expected " 50}'`
- fi
- if `test ! -s ./makefile`
- then
- echo "writing ./makefile"
- cat > ./makefile << '\SHAR\EOF\'
-
- # Specify the name of the program.
- # All documentation and installation keys on this value.
- #
- name=sc
- NAME=SC
-
- # This is where the install step puts it.
- EXDIR=/a/rgb/bin
-
- # This is where the man page goes.
- MANDIR=/usr/man/man1
-
- # All of the source files
- SRC=sc.h sc.c lex.c gram.y interp.c cmds.c crypt.c xmalloc.c range.c eres.sed\
- sres.sed makefile cvt.sed
-
- # The documents in the Archive
- DOCS=README $(name).man sc.doc
-
- # Set SIMPLE for lex.c if you don't want arrow keys or lex.c blows up
- #SIMPLE=-DSIMPLE
-
- # Set QUICK if you want to enter numbers without "=" first
- #QUICK=-DQUICK
-
- # Use this for system V.2
- #CFLAGS= -O -DSYSV2
- #LDFLAGS=
- #LIB=-lm -lcurses
-
- # Use this for system V.3
- #CFLAGS= -O -DSYSV3
- #LDFLAGS=
- #LIB=-lm -lcurses
-
- # Use this for BSD 4.2
- #CFLAGS= -O -DBSD42
- #LDFLAGS=
- #LIB=-lm -lcurses -ltermcap
-
- # Use this for BSD 4.3
- CFLAGS= -O -DBSD43
- LDFLAGS=
- LIB=-lm -lcurses -ltermcap
-
- # Use this for system III (XENIX)
- #CFLAGS= -O -DSYSIII
- #LDFLAGS= -i
- #LIB=-lm -lcurses -ltermcap
-
- # Use this for VENIX
- #CFLAGS= -DVENIX -DBSD42 -DV7
- #LDFLAGS= -z -i
- #LIB=-lm -lcurses -ltermcap
-
- # The objects
- OBJS=sc.o lex.o gram.o interp.o cmds.o crypt.o xmalloc.o range.o
-
- $(name): $(OBJS)
- cc ${CFLAGS} ${LDFLAGS} ${OBJS} ${LIB} -o $(name)
-
- diff_to_sc: diff_to_sc.c
- cc ${CFLAGS} -o dtv diff_to_sc.c
-
- pvc: pvc.c
- cc ${CFLAGS} -o pvc pvc.c
- cp pvc $(EXDIR)/pvc
-
- lex.o: sc.h y.tab.h gram.o
- cc ${CFLAGS} ${SIMPLE} -c lex.c
-
- sc.o: sc.h sc.c
- cc ${CFLAGS} ${QUICK} -c sc.c
-
- interp.o: interp.c sc.h
-
- gram.o: sc.h y.tab.h
-
- cmds.o: cmds.c sc.h
-
- crypt.o: crypt.c sc.h
-
- range.o: range.c sc.h
-
- y.tab.h: gram.y
-
- gram.o: sc.h y.tab.h gram.c
- cc ${CFLAGS} -c gram.c
- sed<gram.y >experres.h -f eres.sed;sed < gram.y > statres.h -f sres.sed
-
- gram.c: gram.y
- yacc -d gram.y; mv y.tab.c gram.c
-
- clean:
- rm -f *.o *res.h y.tab.h $(name) debug core gram.c
-
- shar: ${SRC} ${DOCS}
- shar -c -m 55000 -f shar ${DOCS} ${SRC}
-
- lint: sc.h sc.c lex.c gram.c interp.c cmds.c crypt.c
- lint ${CFLAGS} ${SIMPLE} ${QUICK} sc.c lex.c gram.c interp.c cmds.c crypt.c range.c -lcurses -lm
-
- print: sc.h gram.y sc.c lex.c interp.c cmds.c crypt.c
- prc sc.h gram.y sc.c lex.c interp.c cmds.c crypt.c | lpr
-
- $(name).1: sc.doc
- sed -e s/pname/$(name)/g -e s/PNAME/$(NAME)/g sc.doc > $(name).1
-
- $(name).man: $(name).1
- -mv $(name).man $(name).mold
- nroff -man $(name).1 > $(name).man
-
- install: $(EXDIR)/$(name)
-
- inst-man: $(MANDIR)/$(name).1
-
- $(EXDIR)/$(name): $(name)
- -mv $(EXDIR)/$(name) $(EXDIR)/$(name).old
- strip $(name)
- cp $(name) $(EXDIR)
-
- $(MANDIR)/$(name).1: $(name).1
- cp $(name).1 $(MANDIR)
- \SHAR\EOF\
- else
- echo "will not over write ./makefile"
- fi
- if [ `wc -c ./makefile | awk '{printf $1}'` -ne 2566 ]
- then
- echo `wc -c ./makefile | awk '{print "Got " $1 ", Expected " 2566}'`
- fi
- if `test ! -s ./cvt.sed`
- then
- echo "writing ./cvt.sed"
- cat > ./cvt.sed << '\SHAR\EOF\'
- s!+/\(r.*c.*:r.*c[0-9]*\)!@sum(\1)!
- s/\(r[0-9]*\)\(c[0-9]*\)/\2\1/g
- s/c10/k/g
- s/c11/l/g
- s/c12/m/g
- s/c13/n/g
- s/c14/o/g
- s/c15/p/g
- s/c16/q/g
- s/c17/r/g
- s/c18/s/g
- s/c19/t/g
- s/c20/u/g
- s/c21/v/g
- s/c22/w/g
- s/c23/x/g
- s/c24/y/g
- s/c25/z/g
- s/c26/aa/g
- s/c27/ab/g
- s/c28/ac/g
- s/c29/ad/g
- s/c30/ae/g
- s/c31/af/g
- s/c32/ag/g
- s/c33/ah/g
- s/c34/ai/g
- s/c35/aj/g
- s/c36/ak/g
- s/c37/al/g
- s/c38/am/g
- s/c39/an/g
- s/c0/a/g
- s/c1/b/g
- s/c2/c/g
- s/c3/d/g
- s/c4/e/g
- s/c5/f/g
- s/c6/g/g
- s/c7/h/g
- s/c8/i/g
- s/c9/j/g
- s/r\([0-9][0-9]*\)/\1/g
- s/format 10/format k/g
- s/format 11/format l/g
- s/format 12/format m/g
- s/format 13/format n/g
- s/format 14/format o/g
- s/format 15/format p/g
- s/format 16/format q/g
- s/format 17/format r/g
- s/format 18/format s/g
- s/format 19/format t/g
- s/format 20/format u/g
- s/format 21/format v/g
- s/format 22/format w/g
- s/format 23/format x/g
- s/format 24/format y/g
- s/format 25/format z/g
- s/format 26/format aa/g
- s/format 27/format ab/g
- s/format 28/format ac/g
- s/format 29/format ad/g
- s/format 30/format ae/g
- s/format 31/format af/g
- s/format 32/format ag/g
- s/format 33/format ah/g
- s/format 34/format ai/g
- s/format 35/format aj/g
- s/format 36/format ak/g
- s/format 37/format al/g
- s/format 38/format am/g
- s/format 39/format an/g
- s/format 0/format a/g
- s/format 1/format b/g
- s/format 2/format c/g
- s/format 3/format d/g
- s/format 4/format e/g
- s/format 5/format f/g
- s/format 6/format g/g
- s/format 7/format h/g
- s/format 8/format i/g
- s/format 9/format j/g
- \SHAR\EOF\
- else
- echo "will not over write ./cvt.sed"
- fi
- if [ `wc -c ./cvt.sed | awk '{printf $1}'` -ne 1420 ]
- then
- echo `wc -c ./cvt.sed | awk '{print "Got " $1 ", Expected " 1420}'`
- fi
- echo "Finished archive 1 of 3"
- # if you want to concatenate archives, remove anything after this line
- exit
-
- --
-
- Rich $alz
- Cronus Project, BBN Labs rsalz@bbn.com
- Moderator, comp.sources.unix sources@uunet.uu.net
-