IMD 1.17: 19/01/2010 20:37:47 sc 1 of 2 login system cd /bin restor +l sc bond distribution 0PUniFLEX Backup This is a much modified version of the public domain spread sheet vc, posted a year or two ago by Mark Weiser, orginally by James Gosling. Changes since my last version: 1) Much linting for those who reported coredumps. This version should be more portable. On our 4.3 system, lint only complains about some functions whose values are always ignored. On the 5.2 system it also complains about some hidden variables. This is normal. Yacc will complain about 14 shift reduce conflicts. This is  ܱ ܱjTektronix 44042  !"#$%&'()*+,-./01234('&%$#"! also normal. 2) The @avg bugs are fixed. 3) I added a "^" command to go to row 0 4) Trig and other math functions added. 5) Assorted bug fixes and cleanup. 6) Use crmode() instead of raw() for BSD 7) A couple of new region commands (erase and fill) 8) More cursor movement commands (goto and #) 9) All function names are unique within the first 7 characters. 10) More precision is retained in the saved files. Due to some trademark name problems, I have changed the name back to Gosling's original, sc. I have  ?0  6bond - - Vmodified the makefile to make it easy for you to call it what you want (I saw at least five different names in correspondence and on the net). Just change "name=sc" to "name=myfavoritename" and try "make myfavoritename". Similarly, you can make the documentation with "make myfavoritename.man". "make install" will make and install the code in EXDIR. The installation steps and documentation all key off of the name. The makefile even changes the name in the nroffable man page. If you don't have nroff, you U  READMEbond "- ʀ ʔ ʜʗ- ʘZd ʘ  CE" will have to change sc.man yourself. The code has been tested against a Vax running 4.2 and 4.3 and a National ICM-3216 with system V.2. The ICM has a National Semi 32016. Just check the makefile for the system flags. I have heard reports of lots of other machines which work. I have added ifdefs for system III and for Berkely 4.3. If you have problems with lex.c, and don't care about arrow keys, define SIMPLE (-DSIMPLE in the makefile). SIMPLE causes the arrow keys to not be used. Many thanks to all of the kind souls who wrote with fixes and bug reports. In particular, my "beta" testers, Kim Rochat and Dave Shanks, and to Eric Goldman for the floating point stuff. Disclaimer: Sc is not a product of National Semiconductor. It is supplied as is with no warrenty, express or implied, as a service to Usenet readers. Bob Bond Robert Bond ihnp4!nsc!nscpdc!rgb National Semiconductor tektronix!nscpdc!rgb  { 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);   cmds.cbond "- ʀ ʔ ʜ-- ʘZd ʘ  Cc" n -> v = p -> v; n -> flags = p -> flags; n -> expr = copye (p -> expr, 0, 1); n -> label = 0; if (p -> label) { n -> label = malloc ((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); } /* 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 #include "sc.h" #ifdef BSD42 #include #else #ifndef SYSIII #include #endif #endif char *malloc(); duprow() { if (currow >= MAXROWS - 1 || maxrow >= MAXROWS - 1) { error ("The table can't be any bigger"); return; } modflg+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+; 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 = malloc ((unsigned)(strlen (p -> label) + 1)); strcpy (n -> label, p -> label); } } } for (curcol = 0; curcol <= maxcol; curcol++)(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; } } } },"%s",coltoa(j)); linelim = strlen (line); } } rowshow_op() { register int i,j; for (i=0; inext) { if (p->row < minrow) minrow = p->row; if (p->row > maxrow) ': 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--) { hidden_row[i] = hidden_row[i-1]; } for (r = ++maxrow; r > rs; r--) for (c = maxcol + 1, p = &tbl[r][0]; 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); cleare --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++) { hidden_row[i] = hidden_row[i+1]; } while (r flags = p -> flags & ~is_deleted; n -> v = p -> v; n -> expr = copye(p->expr, deltar, deltac); n -> label = 0; if (p -> label) { n -> label = malloc((unsigned)(strlen(p->label)+1)); strcpy (n -> label, p -> label); } } } colshow_op() { register int i,j; for (i=0; i=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]; hidden_col[i] = hidden_col[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; at 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/formfor (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]; hidden_col[i] = hidden_col[i+1]; } maxcol--; FullUpdate++; modflg++; } maxcol = 0; for (p = to_fix; p; p = p->next) { if (p->row < minrow) minrow = p->row; if (p->row > maxrow) at 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 case 'c': case 'j': case 'k': case ctl(p): case ctl(n): return('c'); case 'r': case 'lY  cvt.sedbond "- ʀ ʔ ʜ-- ʘZd ʘ  Cd"1^ 2 eres.sedbond "- ʀ ʔ ʜ-- ʘZd ʘ  Cd"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/form/%token.*K_/!d /%token.*K_\(.*\)/s// "\1", K_\1,/ (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/forma b gram.ybond "- ʀ ʔ ʜ-- ʘZd ʘ  Cy"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 var ':' var { copy($2, $3, $5); } | S_ERASE var ':' var { eraser($2, $4); } | S_FILL var ':' var num num { fill($2, $4, $5, $6); } | S_GOTO var {moveto($2); } | /* nothing */ | error; term: /* 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 #include "sc.h" %} %union { int ival; double fval; struct ent *ent; struct enode *enode; char *sval; } %type var %type num %type e term %token STRING %token NUMBER %token FNUMBER %token WORD %token 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_PROGLET %token S_COPY %token S_SHOW %token S_ERASE %token S_FILL %token S_GOTO %token K_FIXED %token K_SUM %token K_PROD %token K_AVG %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  } | '@' 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(%token K_SQRT %token K_TAN %token K_DTR %token K_RTD %token K_MAX %token K_MIN %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 NUMBER NUMBER { fwidth[$2] = $3; FullUpdate++; modflg++; precision[$2] = $4; } | 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_MAX '(' e ',' e ')' { $$ = new(MAX, $4, $6); } | '@' K_MIN '(' e ',' e ')' { $$ = new(MIN, $4, $6); } | '(' 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/* 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 #include #ifdef BSD42 #include #else #ifndef SYSIII #include #endif #endif #include #include "sc.h" #define DEFCOLDELIM ':' char *malloc(); #define PI (double)3.14159265358979323846 '+' 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 #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 , new ('>', $1, $4)); } | e '!' '=' e { $$ = new ('~', (struct enode *)0, new ('=', $1, $4)); } | e '>' '=' e { $$ = new ('~', (struct enode *)0, new ('<', $1, $4)); } ; var: COL NUMBER { $$ = lookat($2 , $1); }; num: NUMBER { $$ = (double) $1; } | FNUMBER { $$ = $1; } | '-' num { $$ = -$2; } | '+' num { $$ = $2; } ; ken 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 = 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); } CV  CW interp.cbond "- ʀ ʔ ʜ-- ʘZd ʘ  Cc"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': retu MIN: { double left, right; left = eval(e->e.o.left); right = eval(e->e.o.right); return (left < right ? left : right); } case MAX: { double left, right; left = eval(e->e.o.left); right = eval(e->e.o.right); return (left > right ? left : right); } } return((double) 0.0); /* safety net */ } #define MAXPROP 7 EvalAll () { int repct = 0; while (RealEvalAll() && (repct++ <= MAXPROP)); } int RealEvalAll () { regisrn (e->e.v->v); case O_REDUCE('+'): case O_REDUCE('*'): case O_REDUCE('a'): { 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, ter 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 *) malloc ((unsigned)sizeof (struct enode)); p->op = op; p->e.o.left = a1; p->e.o.right = a2; returminc, maxr, maxc); case O_REDUCE('*'): return doprod(minr, minc, maxr, maxc); case O_REDUCE('a'): return doavg(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))); casen p; } struct enode *new_var(op, a1) struct ent *a1; { register struct enode *p = (struct enode *) malloc ((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 *) malloc ((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; registe FLOOR: return (floor(eval(e->e.o.right))); case HYPOT: return (hypot(eval(e->e.o.left), eval(e->e.o.right))); case LOG: return (log(eval(e->e.o.right))); case LOG10: return (log10(eval(e->e.o.right))); 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))); caser 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 = malloc ((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); } moveto(v) struct.left); efree (e->e.o.right); } free ((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) free(v->label); if (s && s[0]) { v->label = malloc ((unsign 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; ed)(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; { if (v) sprintf (line+linelim, "%s%d", coltoa(v->col), v->row); else sprintf (line+linelim,"VAR?"); linelim += strlen (line+linelim); } char * coltoa(col) int col; { static char rname[3]; register char *p = rname; if (col > 25) { *p++ = col/26 + 'A' -  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;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; ca 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.ose '^': mypriority = 12; break; } if (mypriorityop) { 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('a'): s = "@avg("; /* fall though to more; */ more: for (; line[linelim++] = *s++;); linelim--; 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 = "@c lookat (row, col); sprintf (line, "%sstring %s%d = \"", ((p->flags&is_leftflush) ? "left" : "right"), coltoa(col), row); linelim = strlen(line); if (p->label) { sprintf (line+linelim, "%s", p->label); linelim += strlen (line+linelim); } } printfile (fname) char *fname; { FILE *f = fopen(fname, "w"); char pline[1000]; int plinelim; register row, col; register struct ent **p; if (f==0) { error ("Can't create %s", fname); return; } for (eil("; 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 MIN: srow=0;row<=maxrow; row++) { register c = 0; plinelim = 0; for (p = &tbl[row][col=0]; col<=maxcol; col++, p++) { if (*p) { char *s; while (plinelimflags&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+pline = "@min("; goto more2; case MAX: s = "@max("; goto more2; 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 (myprioritylim) pline[plinelim++] = ' '; if (dplinelim) plinelim = d-pline; } } c += fwidth [col]; } fprintf (f,"%.*s\n",plinelim,pline); } fclose (f); } tblprintfile (fname) char *fname; { FILE *f = fopen(fname, "w"); char pline[1000]; register row, col; register struct ent **p; char coldelim = DEFCOLDELIM; if (f==0) { error ("Can't create %s", fname); return; } for (row=0;row<=maxrow; rov); linelim += strlen (line+linelim); } } edits (row, col) { register struct ent *p =w++) { 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); } fclose (f); } struct enode *copye (e, Rdelta, Cdelta) register struct enode *e; { register struct enode *ret; if (e==0) ret = 0; else { ret = (struct enode *) malloc ((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'): 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 if (r2 > MAXROWS-2) { error("You can't hide the last row"); return; } FullUpdate++; while (r1 <= r2) hidden_row[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) hidden_col[c1++] = 1; } showrow(r1, r2) { if (r1 < 0 || r1 > r2) { error("Inv = (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 * inalid Range"); return; } if (r2 > MAXROWS-1) { r2 = MAXROWS-1; } FullUpdate++; while (r1 <= r2) hidden_row[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) hidden_col[c1++] = 0; } e+plinelim); } if (s = (*p)->label) { register char *d; d = pline+((*p)->flags&is_leftflush ? c : c-strlen(s)+fwidth[col]); while (d>pline+pline tbl. Thus the free_ent, fix_ent calls in sc.c */ sync_refs () { register i,j; register struct ent *p; 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'): e->e.o.right = (struct enode *) looka$X $Y lex.cbond "- ʀ ʔ ʜ-- ʘZd ʘ  Cc"t ( ((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; } /* SC A Spreadsheet Calculator * Lexical analyser * * original by James Gosling, September 1982 * modifications by Mark Weiser and Bruce Israel, * University of Maryland * * More mods Robert Bond, 12/86 * */ #if defined(BSD42) || defined(BSD43) #include #endif #include #include #include #include "sc.h" #include #ifdef BSD42 #include #else #ifndef SYSIII #include #endif #endif #include "y.tab.h"  char *strtof(); char *malloc(); jmp_buf wakeup; struct key { char *key; int val; }; struct key experres[] = { #include "experres.h" 0, 0}; struct key statres[] = { #include "statres.h" 0, 0}; #define ctl(x) ('x'&037) yylex () { register char *p = line+linelim; int ret; while (isspace(*p)) p++; if (*p==0) ret = -1; else if (isalpha(*p)) { char *tokenst = p; register tokenl; register struct key *tbl; while (isalpha(*p)) p++; if ((tokenl = p-tokenst) <= 2) { tr-p)); yylval.sval = ptr; p += 1; while (*p && *p!='"') *ptr++ = *p++; *ptr = 0; if (*p) p += 1; ret = STRING; } else if (*p=='[') { while (*p && *p!=']') p++; if (*p) p++; linelim = p-line; return yylex(); } else ret = *p++; linelim = p-line; return ret; } #ifdef SIMPLE initkbd() {} resetkbd() {} nmgetch() { return (getchar() & 0x7f); } #else /*SIMPLE*/ #if defined(BSD42) || defined (SYSIII) || defined(BSD43) #define N_KEY 4 struct key_map { char *k_str; char  register col; /* a COL is 1 or 2 char alpha (and not pi or ln!) */ if (tokenl == 2 && tokenst[0] == 'p' && tokenst[1] == 'i') { ret = K_PI; } else if (tokenl == 2 && tokenst[0] == 'l' && tokenst[1] == 'n') { ret = K_LN; } else { ret = COL; col = ((tokenst[0] & 0137) - 'A'); if (p == tokenst+2) col = (col + 1)*26 + ((tokenst[1] & 0137) - 'A'); yylval.ival = col; } } else { ret = WORD; tokenl = p-tokenst; for (tbl = linelim ? experres : statres; tbl->kk_val; char k_index; }; struct key_map km[N_KEY]; char keyarea[N_KEY*10]; char *tgetstr(); char *getenv(); #ifdef TIOCSLTC struct ltchars old_chars, new_chars; #endif char dont_use[] = { ctl(z), ctl(r), ctl(l), ctl(b), ctl(c), ctl(f), ctl(g), ctl([), ctl(h), ctl(m), ctl(j), ctl(n), ctl(p), ctl(q), ctl(s), ctl(t), ctl(u), ctl(v), ctl(e), ctl(a), 0, }; initkbd() { register struct key_map *kp; register i,j; char *ks; char *p = keyarea; static char buf[1024]; /* Why doey; tbl++) if (((tbl->key[0]^tokenst[0])&0137)==0 && tbl->key[tokenl]==0) { register i = 1; while (ikey[i])&0137)==0) i++; if (i>=tokenl) { ret = tbl->val; break; } } if (ret==WORD) { linelim = p-line; yyerror ("Unintelligible word"); } } } else if ((*p == '.') || isdigit(*p)) { register long v = 0; char *nstart = p; if (*p != '.') { do v = v*10 + (*p-'0'); while (isdigit(*++p)); } if (*p=='.' I have to do this again? */ if (tgetent(buf, getenv("TERM")) <= 0) return; km[0].k_str = tgetstr("kl", &p); km[0].k_val = ctl(b); km[1].k_str = tgetstr("kr", &p); km[1].k_val = ctl(f); km[2].k_str = tgetstr("ku", &p); km[2].k_val = ctl(p); km[3].k_str = tgetstr("kd", &p); km[3].k_val = ctl(n); ks = tgetstr("ks",&p); if (ks) printf("%s",ks); /* Unmap arrow keys which conflict with our ctl keys */ /* Ignore unset, longer than length 1, and 1-1 mapped keys */ f || *p == 'e' || *p == 'E') { ret = FNUMBER; p = strtof(nstart, &yylval.fval); } else { if((int)v != v) { ret = FNUMBER; yylval.fval = v; } else { ret = NUMBER; yylval.ival = v; } } } else if (*p=='"') { /* This storage is never freed. Oh well. -MDW */ char *ptr; ptr = p+1; while(*ptr && *ptr++ != '"'); ptr = malloc((unsigned)(por (i = 0; i < N_KEY; i++) { kp = &km[i]; if (kp->k_str && (kp->k_str[1] == 0) && (kp->k_str[0] != kp->k_val)) for (j = 0; dont_use[j] != 0; j++) if (kp->k_str[0] == dont_use[j]) { kp->k_str = (char *)0; break; } } #ifdef TIOCSLTC ioctl(fileno(stdin), TIOCGLTC, (char *)&old_chars); new_chars = old_chars; if (old_chars.t_lnextc == ctl(v)) new_chars.t_lnextc = -1; if (old_chars.t_rprntc == ctl(r)) new_chars.t_rprntc = -1; ioctl(fileno(stdin), TIOCSLTC, (char *)&new_chars); #endif } resetkbd() { #ifdef TIOCSLTC ioctl(fileno(stdin), TIOCSLTC, (char *)&old_chars); #endif } nmgetch() { register int c; register struct key_map *kp; register struct key_map *biggest; register int i; int almost; int maybe; static char dumpbuf[10]; static char *dumpindex; int timeout(); if (dumpindex && *dumpindex) return (*dumpindex++); c = getchar() & 0x7f; biggest = 0; almost = 0; for (kp = &km[0]; kp < and e is E or e. * to floating point. * p is advanced. */ char * strtof(p, res) register char *p; double *res; { double acc; int sign; double fpos; int exp; int exps; acc = 0.0; sign = 1; exp = 0; exps = 1; if (*p == '+') p++; else if (*p == '-') { p++; sign = -1; } while (isdigit(*p)) { acc = acc * 10.0 + (double)(*p - '0'); p++; } if (*p == 'e' || *p == 'E') { p++; if (*p == '+') p++&km[N_KEY]; kp++) { if (!kp->k_str) continue; if (c == kp->k_str[kp->k_index]) { almost = 1; kp->k_index++; if (kp->k_str[kp->k_index] == 0) { c = kp->k_val; for (kp = &km[0]; kp < &km[N_KEY]; kp++) kp->k_index = 0; return(c); } } if (!biggest && kp->k_index) biggest = kp; else if (kp->k_index && biggest->k_index < kp->k_index) biggest = kp; } if (almost) { signal(SIGALRM, timeout); alarm(1); ; else if (*p == '-') { p++; exps = -1; } while(isdigit(*p)) { exp = exp * 10 + (*p - '0'); p++; } } if (*p == '.') { fpos = 1.0/10.0; p++; while(isdigit(*p)) { acc += (*p - '0') * fpos; fpos *= 1.0/10.0; p++; } } if (*p == 'e' || *p == 'E') { exp = 0; exps = 1; p++; if (*p == '+') p++; else if (*p == '-') { p++; exps = -1; } while(isdigit(*p)) { exp = exp * 10 + (*p - '0'); p++; } if (setjmp(wakeup) == 0) { maybe = nmgetch(); alarm(0); return(maybe); } } if (biggest) { for (i = 0; ik_index; i++) dumpbuf[i] = biggest->k_str[i]; dumpbuf[i++] = c; dumpbuf[i] = 0; dumpindex = &dumpbuf[1]; for (kp = &km[0]; kp < &km[N_KEY]; kp++) kp->k_index = 0; return (dumpbuf[0]); } return(c); } #endif #ifdef SYSV initkbd() { keypad(stdscr, TRUE); } resetkbd() {} nmgetch() { register int c; c = getch(); swit } if (exp) { if (exps > 0) while (exp--) acc *= 10.0; else while (exp--) acc *= 1.0/10.0; } if (sign > 0) *res = acc; else *res = -acc; return(p); } help () { move(2,0); clrtobot(); dbline = 0; debug ("Cursor: ^n j next row ^p k prev. row ESC ^g erase cmd"); debug (" ^f l fwd col ^b h back col ^l ^r redraw screen"); debug (" 0 col A $ last col g goto "); debug (" ch (c) { case KEY_LEFT: c = ctl(b); break; case KEY_RIGHT: c = ctl(f); break; case KEY_UP: c = ctl(p); break; case KEY_DOWN: c = ctl(n); break; default: c = c & 0x7f; } return (c); } #endif /* SYSV */ #endif /* SIMPLE */ timeout() { longjmp(wakeup, -1); } int dbline; /*VARARGS*/ void debug (str) char *str; { mvprintw (2+(dbline++%22),80-70,str); clrtoeol(); } /* * This converts a floating point number of the form * [s]ddd[.d*][esd*] where s can be a + or -  ^ row 0 # last row"); debug ("Cell: \" < > enter label = enter value x clear cell"); debug (" c copy cell m mark cell ^t line 1 on/off"); debug (" ^a type value ^e type expr. ^v type vbl name"); debug ("Row, Col: ar ac dup ir ic insert sr sc show"); debug (" dr dc delete zr zc hide pr pc pull"); debug (" vr vc value only f format"); debug ("Region: /c copy /x clear /f fill"); debug ("File: G get database M merge database T write tbl fmt"); debug (" P put database W write listing"); debug ("Misc: Q q quit pm pull (merge)"); debug ("Expr: +-*/^ arithmetic ?e:e conditional & | booleans"); debug (" < = > relations <= >= relations != relations"); debug (" @sum(v1:v2) @avg(v1:v2) @S= -O -DBSD43 LIB=-lm -lcurses -ltermcap #Use this for system III (XENIX) #CFLAGS= -O -DSYSIII #LIB=-lm -lcurses -ltermcap #Use this for separate I and D space #ID=-i ID= $(name): sc.o lex.o gram.o interp.o cmds.o cc ${CFLAGS} ${ID} sc.o lex.o gram.o interp.o cmds.o ${LIB} -o $(name) diff_to_sc: diff_to_sc.c cc ${CFLAGS} -o dtv diff_to_sc.c lex.o: sc.h y.tab.h gram.o cc ${CFLAGS} ${SIMPLE} -c lex.c interp.o: sc.h sc.o: sc.h gram.o: sc.h y.tab.h cmds.o: cmds.c sc.h y.tab.h: gram.y gram.o: sc.h prod(v1:v2)"); debug (" @func(e) - lots of other math functions"); } almost = 1; kp->k_index++; if (kp->k_str[kp->k_index] == 0) { c = kp->k_val; for (kp = &km[0]; kp < &km[N_KEY]; kp++) kp->k_index = 0; return(c); } } if (!biggest && kp->k_index) biggest = kp; else if (kp->k_index && biggest->k_index < kp->k_index) biggest = kp; } if (almost) { signal(SIGALRM, timeout); alarm(1); y.tab.h gram.c cc ${CFLAGS} -c gram.c sedexperres.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: ${SRC1} ${SRC2} ${DOCS} shar -v -c ${DOCS} ${SRC2} > sc.shar.1 shar -v -c ${SRC1} > sc.shar.2 lint: sc.h sc.c lex.c gram.c interp.c cmds.c lint ${CFLAGS} ${SIMPLE } sc.c lex.c gram.c interp.c cmds.c -lcurses -lm $(name).1: sc.doc sed -e s/pname/$(name)/g sc.doc > $(name).1 4 5 makefilebond "- ʀ ʔ ʜ-- ʘZd ʘ  Ce" $(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) kp->k_index = 0; return (dumpbuf[0]); } return(c); } #endif #ifdef SYSV initkbd() { keypad(stdscr, TRUE); } resetkbd() {} nmgetch() { register int c; c = getch(); swit # Specify the name of the program. # All documentation and installation keys on this value. # name=sc EXDIR=/a/rgb/bin MANDIR=/usr/man/man1 SRC1=sc.h sc.c lex.c gram.y interp.c SRC2=cmds.c eres.sed sres.sed makefile cvt.sed DOCS=README $(name).man $(name).doc #Set SIMPLE for lex.c if you don't want arrow keys or lex.c blows up #SIMPLE=-DSIMPLE #Use this for system V.2 #CFLAGS= -O -DSYSV #LIB=-lm -lcurses #Use this for BSD 4.2 #CFLAGS= -O -DBSD42 #LIB=-lm -lcurses -ltermcap #Use this for BSD 4.3 CFLAG45 5  -makefile.oldbond "- ʀ ʔ ʜ-- ʘZd ʘ  Cd" # Specify the name of the program. # All documentation and installation keys on this value. # name=sc EXDIR=/a/rgb/bin MANDIR=/usr/man/man1 SRC1=sc.h sc.c lex.c gram.y interp.c SRC2=cmds.c eres.sed sres.sed makefile cvt.sed DOCS=README $(name).man $(name).doc #Set SIMPLE for lex.c if you don't want arrow keys or lex.c blows up #SIMPLE=-DSIMPLE #Use this for system V.2 #CFLAGS= -O -DSYSV #LIB=-lm -lcurses #Use this for BSD 4.2 #CFLAGS= -O -DBSD42 #LIB=-lm -lcurses -ltermcap #Use this for BSD 4.3 CFLAGn n  scbond "- ʀ ʔ ʜ-- ʘZd ʘ  Cc"S= -O -DBSD43 LIB=-lm -lcurses -ltermcap #Use this for system III (XENIX) #CFLAGS= -O -DSYSIII #LIB=-lm -lcurses -ltermcap #Use this for separate I and D space #ID=-i ID= $(name): sc.o lex.o gram.o interp.o cmds.o cc ${CFLAGS} ${ID} sc.o lex.o gram.o interp.o cmds.o ${LIB} -o $(name) diff_to_sc: diff_to_sc.c cc ${CFLAGS} -o dtv diff_to_sc.c lex.o: sc.h y.tab.h gram.o cc ${CFLAGS} ${SIMPLE} -c lex.c interp.o: sc.h sc.o: sc.h gram.o: sc.h y.tab.h cmds.o: cmds.c sc.h y.tab.h: gram.y gram.o: sc.h From tektronix!uw-beaver!cornell!rochester!seismo!lll-lcc!mordor!styx!ames!ucbcad!ucbvax!decvax!decwrl!cookie.dec.com!wecker Mon Jan 19 13:38:38 PST 1987 Article 4245 of net.sources: Path: tekcrl!tektronix!uw-beaver!cornell!rochester!seismo!lll-lcc!mordor!styx!ames!ucbcad!ucbvax!decvax!decwrl!cookie.dec.com!wecker >From: wecker@cookie.dec.com (DAVE CUM GRANO SALIS WECKER) Newsgroups: net.sources Subject: Trimmed down spread sheet program for U**X/VMS/AMIGA, happy taxes! Message-ID: <7639@decwrl.DEC.COM> Dy.tab.h gram.c cc ${CFLAGS} -c gram.c sedexperres.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: ${SRC1} ${SRC2} ${DOCS} shar -v -c ${DOCS} ${SRC2} > sc.shar.1 shar -v -c ${SRC1} > sc.shar.2 lint: sc.h sc.c lex.c gram.c interp.c cmds.c lint ${CFLAGS} ${SIMPLE } sc.c lex.c gram.c interp.c cmds.c -lcurses -lm $(name).1: sc.doc sed -e s/pname/$(name)/g sc.doc > $(name).1 ate: 18 Jan 87 00:01:14 GMT Sender: daemon@decwrl.DEC.COM Organization: Digital Equipment Corporation Lines: 3712 This is an updated version of the public domain spreadsheet released recently by Bob Bond (called at the time: vc (don't flame at me :-)). This version is designed for people with varying systems: 1) FIXES A **MAJOR** bug. If you use numbers in the 10000 - 99999 range and save the table, then get back in and restore it (P,G) numbers will be rounded to 1 place accuracy (e.g., 12345.67 $(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) kp->k_index = 0; return (dumpbuf[0]); } return(c); } #endif #ifdef SYSV initkbd() { keypad(stdscr, TRUE); } resetkbd() {} nmgetch() { register int c; c = getch(); swit becomes 12345.7 (not too good for taxes!!!)). Simple fix: replace the two occurances of "%g" in interp.c with "%.8g" 2) uses no TERMCAP file or facilities (expects a VT100 class terminal) 3) uses no system CURSES package (has its own (sort of) built in) 4) Runs on any U**X, VMS or AMIGA system (plus probably lots more) (define either VMS, U__X, or MCH_AMIGA to your compiler) 5) Does not require YACC (output already pre-built) 6) Does not require nroff (compiled man page provided) Enjoy!! dave (decwrl.dec.com!cookie.dec.com!wecker) # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # README # vc.man # makefile.amiga # sc.c # lex.c # gram.c # interp.c # cmds.c # curses.c # experres.h # sc.h # statres.h # y.tab.h # This archive created: Sat Jan 17 16:31:12 1987 echo shar: extrnd columns of cells. Each cell may have a label XX string associated with it and an expression. The expression XX may be a constant or it may compute something based on other XX entries. XX XX When _v_c is running, the screen is divided into four regions: XX the top line is for entering commands, the second line is XX for messages from _v_c, the third line and the first four XX columns show the row and column numbers, and the rest of the Xacting README sed 's/^XX//' << \SHAR_EOF > README XXThis is a much modified version of the public domain spread sheet vc, XXposted a year or two ago by Mark Weiser, orginally by James Gosling XX XXI have completely reworked the user interface. The save file format is XXdifferent so I have included a sed script, cvt.sed, which will convert to XXthe new file formats. I have also added lots of new features and fixed XXlots of bugs. Any bugs you find at this point are probably mine. XXI would love to hear frX screen forms a window looking at the table. _v_c has two XX cursors: a cell cursor (indicated by a '<' on the screen) XX and a character cursor (indicated by the terminals hardware XX cursor). The cell and character cursors are often the same. XX They will differ when a long command is being typed on the XX top line. XX XX Commands which use the terminal's control key will work when XX either a long command is being typed or in "nom you if you have any problems. XX XXThe code has been tested against a Vax running 4.2 and a National ICM-3216 XXwith system V.2. The ICM has a National Semi 32016. Just check the makefile XXfor the system flags. XX XXGood luck with the tax man. XX XX Bob Bond XX XX Robert Bond ihnp4!nsc!nscpdc!rgb XX National Semiconductor tektronix!nscpdc!rgb SHAR_EOF if test 790 -ne "`wc -c README`" then echo shar: error transmitting README '(should have been 790 characters)' fi echo shar: extracting vormal" mode. XX XX The cursor control commands and the row, column commands can XX be prefixed by a numeric argument indicating how many times XX the command is to be executed. "^U" can be used before the XX number if the cursor movement is to take place while a XX command is being typed into the command line. XX XX Cursor control commands: XX XX XX ^N Move the cell cursor to the next row. XX XX XX ^P Move the cell cursor to the prc.man sed 's/^XX//' << \SHAR_EOF > vc.man XX XX XX XX VC(1) UNIX 3.0 VC(1) XX XX XX XX NAME XX vc - spread sheet calculator ("visicalc-like") XX XX SYNOPSIS XX vc [ _f_i_l_e ] XX XX XX DESCRIPTION XX _V_c is a calculator that is based on rectangular tables, in XX much the same style as Visicalc or Lotus 123. When it is XX invoked it presents you with an empty table organised as XX rows aevious row. XX XX XX ^F Move the cell cursor forward one column. XX XX XX ^B Move the cell cursor backward one column. XX XX XX ^H Backspace one character. XX XX XX XX Page 1 (printed 1/5/87) XX XX XX XX XX XX XX VC(1) UNIX 3.0 VC(1) XX XX XX XX h, j, k, l XX Alternate cursor controls (left, down, up, right). XX XX XX 0 Move the cell cursor to column 0 of the current row. XX XX XX $ Move the cell cursor to the last valid column in the XX current row. XX XX XX Cell entry and editing commands: XX XX XX = Prompts for an expression which will be evaluated XX dynamically to produce a value for the cell pointed at XX by the cell cursor. This may be used in conjunction XX with ^V to make one entries value be dependent on XX anothers. XX XX XX " from a file. XX XX XX P Put the current database into a file. XX XX XX W Write a listing of the current database in a form that XX matches its appearance on the screen. This differs XX from the "put" command in that "put"s files are XX intended to be reloaded with "get", while "write" XX produces a file for people to look at. XX XX XX T Write a listing of the current database to a file, but XX put ":"s Enter a label for the current cell. XX XX XX < Enter a label that will be flushed left against the XX left edge of the cell. XX XX XX > Enter a label that will be flushed right against the XX right edge of the cell. XX XX XX x Clears the current cell. XX XX XX e Edit the value associated with the current cell. This XX is identical to '=' except that the command line starts XX out containing the old va between each field. This is useful for XX tables that will be further formatted by the _t_b_l XX preprocessor of _n_r_o_f_f. XX XX XX M Merges the database from the named file into the XX current database. Values, expressions and names XX defined in the named file are written into the current XX file, overwriting the existing entries at those XX locations. XX XX XX Row and Column operations. lue or expression associated XX with the cell. XX XX XX E Edit the string associated with the current cell. This XX is the same as either "leftstring", "rightstring", or XX "label", with the additional fact that the command line XX starts out with the old string. XX XX XX m Mark a cell to be used as the source for the copy XX command. XX XX XX c Copy the last marked cell to the current cell, updating X Members of this class of XX commands can be used on either rows or columns. The second XX letter of the command is either a column designator (one of XX the characters c, j, k, ^N, ^p) or a row designator (one of XX r, l, h, ^B, ^F). Commands which move or copy cells also XX modify the variable references in affected cell expressions. XX Variable references may be frozen by using the "fixed" XX operator. XX XX XX ar, ac XX X XX XX XX Page 2 (printed 1/5/87) XX XX XX XX XX XX XX VC(1) UNIX 3.0 VC(1) XX XX XX XX the row and column references. XX XX XX ^T Toggle cell display. The current cell's contents are XX displayed in line one when no command being entered or XX edited. ^T turns the display on or off. XX XX XX File operations XX XX XX G Get a new database  Creates a new row (column) immediately following the XX current row (column). It is initialized to be a copy XX of the current one. XX XX XX XX XX Page 3 (printed 1/5/87) XX XX XX XX XX XX XX VC(1) UNIX 3.0 VC(1) XX XX XX XX dr, dc XX Delete this row (column). XX XX XX pr, pc, pm XX Pull deleted rows (columns) back into the spread sheet. XX The last deleted set of cells is put back into the XX spread sheet at the current location. _P_r inserts XX enough rows to hold the data. _P_c inserts enough XX columns to hold the data. _P_m (merge) does not insert XX rows or columns, but overwrites the cells beginning at XX the current cursor location. XX XX XX ir, ic XX Insert a new row (column) by moving the row (column) XX 0 VC(1) XX XX XX XX q Alternate exit command. XX XX XX ? Types a brief helpful message. XX XX XX / Copy a region to the area specified by the current XX cell. XX XX XX ^G or ESC XX Abort the current long command. XX XX XX ^R Redraw the screen. XX XX XX ^V Types, in the long command line, the name of the cell XX being pointed at by the cell cursor. This is used when XX  containing the cell cursor, and all following, down XX (right) one. The new position will be empty. XX XX XX zr, zc XX Hide ("zap") the current row (column). This keeps a XX row or column from being displayed but keeps it in the XX data base. XX XX XX vr, vc XX Removes expressions from the affected rows (columns), XX leaving only the values which were in the cells before XX the command w typing in expressions to refer to entries in the table. XX XX XX ^E Types, in the long command line, the expression of the XX cell being pointed at by the cell cursor. XX XX XX ^A Types, in the long command line, the value of the cell XX being pointed at by the cell cursor. XX XX XX Expressions that are used with the '=' and 'e' commands have XX a fairly conventional syntax. Terms may be variable names XX (from the ^V commanas executed. XX XX XX sr, sc XX Show hidden rows (columns). Type in a range of rows or XX columns to be revealed. The command default is the XX first range of rows or columns currently hidden. XX XX XX f Sets the output format to be used for printing the XX numbers in each cell in the current column. Type in XX two numbers which will be the width in characters of a XX column and the number of digits wd), parenthesised expressions, negated XX terms, and constants. Rectangular regions of the screen may XX be operated upon with '@' functions such as sum (@sum), XX average (@avg) and product (@prod). Terms may be combined XX using many binary operators. Their precedences (from XX highest to lowest) are: *,/; +,-; <,=,>,<=,>=; &; |; ?. XX XX XX e+e Addition. XX XX XX e-e Subtraction. XX XX XX e*e Multiphich will follow the XX decimal point. Note that this command has only a XX column version and does have a second letter. XX XX XX Miscellaneous commands: XX XX XX ^C Exit from _v_c. If you were editing a named file, and XX you modified it, then it will ask about saving before XX exiting. XX XX XX XX Page 4 (printed 1/5/87) XX XX XX XX XX XX XX VC(1) UNIX 3.lication. XX XX XX e/e Division. XX XX XX XX XX XX Page 5 (printed 1/5/87) XX XX XX XX XX XX XX VC(1) UNIX 3.0 VC(1) XX XX XX XX @sum(v:v) Sum all valid (nonblank) entries in the XX region whose two corners are defined by the XX two variable (cell) names given. XX XX XX @avg(v:v) Average all valid (nonblank) entries in the XX region whose two corners are defined by the XX two variable (cell) names given. XX XX XX @prod(v:v) Multiply together all valid (nonblank) XX entries in the region whose two corners are XX defined by the two variable (cell) names XX given. XX XX XX e?e:e Conditional: If the first expression is true XX then the value of the seconh XXDOCS = README vc.man XX XXvc : $(OBJS) XX ln -v -o vc $(OBJS) df0:lib/m.lib df0:lib/c.lib XX XXlex.o : lex.c $(INCL) XX cc lex.c XX XXinterp.o : interp.c $(INCL) XX cc interp.c XX XXsc.o : sc.c $(INCL) XX cc sc.c XX XXcmds.o : cmds.c $(INCL) XX cc cmds.c XX XXcurses.o : curses.c $(INCL) XX cc curses.c XX XXgram.o : gram.c $(INCL) XX cc gram.c XX SHAR_EOF if test 614 -ne "`wc -c makefile.amiga`" then echo shar: error transmitting makefile.amiga '(should have been 614 characters)' fi echo shar: extractingd is returned, XX otherwise the value of the third is. XX XX XX <,=,>,<=,>= Relationals: true iff the indicated relation XX holds. XX XX XX &,| Boolean connectives. XX XX XX fixed To make a variable not change automatically XX when a cell moves, put the word fixed in XX front of the reference. I.e. B1*fixed C3 XX XX XX XX SEE ALSO XX bc(1), dc(1) XX sc.c sed 's/^XX//' << \SHAR_EOF > sc.c XX/* SC A Spreadsheet Calculator XX * Main driver XX * XX * original by James Gosling, September 1982 XX * modifications by Mark Weiser and Bruce Israel, XX * University of Maryland XX * XX * More mods Robert Bond, 12/86 XX * Major mods to run on VMS and AMIGA, 1/17/87 XX * XX */ XX XX#include "sc.h" XX XXextern char *malloc(); XX XX/* default column width */ XX XX#define DEFWIDTH 10 XX#define DEFPREC 2 XX XX#define RESCOL 4 /* columns reserved f XX XX BUGS XX Expression reevaluation is done in the same top-to-bottom, XX left-to-right manner as is done in other spread sheet XX calculators. This is silly. A proper following of the XX dependency graph with (perhaps) recourse to relaxation XX should be implemented. XX XX At most 200 rows and 40 columns. XX XX XX XX XX XX XX XX XX XX Page 6 (printed 1/5/87) XX XX XX SHAR_EOF if test 11422 -ne "`wc or row numbers */ XX#define RESROW 3 /* rows reserved for prompt, error, and column numbers */ XX XXchar curfile[1024]; XX XXint showme = 1; /* 1 to display the current cell in the top line */ XXint batch = 0; XX XXerror (fmt,a,b,c,d,e) { XX if (batch) fprintf(stderr,fmt,a,b,c,d,e); XX else { XX move (1,0); XX clrtoeol (); XX printw (fmt,a,b,c,d,e); XX } XX} XX XXint seenerr; XX XXyyerror (err) XXchar *err; { XX if (seenerr) return; XX seenerr++; XX move (1,0); XX clrtoeol (); XX p-c vc.man`" then echo shar: error transmitting vc.man '(should have been 11422 characters)' fi echo shar: extracting makefile.amiga sed 's/^XX//' << \SHAR_EOF > makefile.amiga XX# Make file for AMIAG version of DBW_VC XX# XX# v1.0 870117 DBW XX# XX XX# On U**X systems, compile with: XX# % cc -c -DU__X -O file.c XX# XX# On VMS system, compile with: XX# $ cc/define=VMS file.c XX# also.... rename y.tab.h to y_tab.h XX XXOBJS = sc.o lex.o gram.o interp.o cmds.o curses.o XXINCL = experres.h sc.h statres.h y.tab.rintw ("%s: %.*s <= %s",err,linelim,line,line+linelim); XX} XX XXstruct ent * XXlookat(row,col){ XX register struct ent **p; XX if (row < 0) XX row = 0; XX else if (row > MAXROWS-1) XX row = MAXROWS-1; XX if (col < 0) XX col = 0; XX else if (col > MAXCOLS-1) XX col = MAXCOLS-1; XX p = &tbl[row][col]; XX if (*p==0) { XX *p = (struct ent *) malloc (sizeof (struct ent)); XX if (row>maxrow) maxrow = row; XX if (col>maxcol) maxcol = col; XX (*p)->label = 0; XX (*p)->flags = 0; XX (*p)->row  = row; XX (*p)->col = col; XX (*p)->expr = 0; XX (*p)->v = (double) 0.0; XX } else if ((*p)->flags & is_deleted) XX debug("But %s%d has been deleted!", coltoa(col), row); XX return *p; XX} XX XX/* XX * This structure is used to keep ent structs around before they XX * are deleted to allow the sync_refs routine a chance to fix the XX * variable references. XX * We also use it as a last-deleted buffer for the 'p' command. XX */ XX XXfree_ent(p) XXregister struct ent *p; XX{ XX p->next = to_fix; XX clrtobot (); XX standout(); XX for (row=RESROW, i=strow; i <= maxrow; i++) { XX if (hidden_row[i]) XX continue; XX move(row,0); XX printw("%-*d", RESCOL, i); XX row++; XX } XX move (2,0); XX printw("%*s", RESCOL, " "); XX for (col=RESCOL, i = stcol; i <= maxcol; i++) { XX if (hidden_col[i]) XX continue; XX move(2, col); XX printw("%*s", fwidth[i], coltoa(i)); XX col += fwidth[i]; XX } XX standend(); XX } XX for (row = strow, r = RESROW; row <= maxrow; row++) { XX reg to_fix = p; XX p->flags |= is_deleted; XX} XX XXflush_saved() XX{ XX register struct ent *p; XX register struct ent *q; XX XX if (!(p = to_fix)) XX return; XX while (p) { XX clearent(p); XX q = p->next; XX free(p); XX p = q; XX } XX to_fix = 0; XX} XX XXupdate () { XX register row, XX col; XX register struct ent **p; XX static lastmx, XX lastmy; XX static char *under_cursor = " "; XX int maxcol; XX int maxrow; XX int rowister c = RESCOL; XX if (hidden_row[row]) XX continue; XX for (p = &tbl[row][col = stcol]; col <= maxcol; col++, p++) { XX if (hidden_col[col]) XX continue; XX if (*p && ((*p) -> flags & is_changed || FullUpdate)) { XX char *s; XX move (r, c); XX (*p) -> flags &= ~is_changed; XX if ((*p) -> flags & is_valid) XX printw ("%*.*f", fwidth[col], precision[col], (*p) -> v); XX if (s = (*p) -> label) { XX char field[1024]; XX XX strncpy(field,s,fwidth[col]); XX field[fwids; XX int cols; XX register r; XX XX while (hidden_row[currow]) /* You can't hide the last row or col */ XX currow++; XX while (hidden_col[curcol]) XX curcol++; XX if (curcol < stcol) XX stcol = curcol, FullUpdate++; XX if (currow < strow) XX strow = currow, FullUpdate++; XX while (1) { XX register i; XX for (i = stcol, cols = 0, col = RESCOL; XX (col + fwidth[i]) < COLS-1 && i < MAXCOLS; i++) { XX cols++; XX if (hidden_col[i]) XX continue; XX col += fwidth[i]th[col]] = 0; XX move (r,(*p) -> flags & is_leftflush XX ? c : c - strlen (field) + fwidth[col]); XX addstr(field); XX } XX } XX c += fwidth[col]; XX } XX r++; XX } XX XX move(lastmy, lastmx); XX if (inch() == '<') XX addstr (under_cursor); XX lastmy = RESROW; XX for (row = strow; row < currow; row++) XX if (!hidden_row[row]) XX lastmy += 1; XX lastmx = RESCOL; XX for (col = stcol; col <= curcol; col++) XX if (!hidden_col[col]) XX lastmx += fwidth[; XX } XX if (curcol >= stcol + cols) XX stcol++, FullUpdate++; XX else XX break; XX } XX while (1) { XX register i; XX for (i = strow, rows = 0, row = RESROW; XX row < ROWS && i < MAXROWS; i++) { XX rows++; XX if (hidden_row[i]) XX continue; XX row++; XX } XX if (currow >= strow + rows) XX strow++, FullUpdate++; XX else XX break; XX } XX maxcol = stcol + cols - 1; XX maxrow = strow + rows - 1; XX if (FullUpdate) { XX register int i; XX move (2, 0); XX col]; XX move(lastmy, lastmx); XX *under_cursor = inch(); XX addstr ("<"); XX move (0, 0); XX clrtoeol (); XX if (linelim >= 0) { XX addstr (">> "); XX addstr (line); XX } else { XX if (showme) { XX register struct ent *p; XX p = tbl[currow][curcol]; XX if (p && ((p->flags & is_valid) || p->label)) { XX if (p->expr || !p->label) { XX linelim = 0; XX editexp(currow, curcol); XX } else { XX sprintf(line, "%s", p->label); XX } XX addstr("["); XX addstr (line ); XX addstr("]"); XX linelim = -1; XX } else { XX addstr("[]"); XX } XX } XX move (lastmy, lastmx); XX } XX FullUpdate = 0; XX} XX XXvoid XXquit() XX{ XX endwin (); XX exit(); XX} XX XXmain (argc, argv) XXchar **argv; { XX int inloop = 1; XX register int c; XX int edistate = -1; XX int arg = 1; XX int narg; XX int nedistate = -1; XX int running = 1; XX { XX register i; XX for (i = 0; i < MAXCOLS; i++) { XX fwidth[i] = DEFWIDTHak; XX case ctl (g): XX case ctl ([): XX linelim = -1; XX move (1, 0); XX clrtoeol (); XX break; XX case 0177: XX case ctl (h): XX while (--arg>=0) if (linelim > 0) XX line[--linelim] = 0; XX break; XX case ctl (l): XX FullUpdate++; XX break; XX case ctl (m): XX if (linelim < 0) XX line[linelim = 0] = 0; XX else { XX linelim = 0; XX yyparse (); XX linelim = -1; XX } XX break; XX case ctl (n): XX while (--arg>=0) { XX if (cur; XX precision[i] = DEFPREC; XX } XX } XX linelim = -1; XX curfile[0]=0; XX running = 1; XX XX if (argc > 1 && (! strcmp(argv[1],"-b"))) { XX argc--, argv++; XX batch = 1; XX } XX XX if (! batch) { XX initscr (); XX } XX initkbd(); XX if (argc > 1) { XX strcpy(curfile,argv[1]); XX readfile (argv[1],0); XX } XX modflg = 0; XX if (batch) exit(0); XX error ("VC 2.1 Type '?' for help."); XX FullUpdate++; XX while (inloop) { running = 1; XX while (running) row < MAXROWS - 1) XX currow++; XX else XX error ("The table can't be any longer"); XX while (hidden_row[currow] && (currow < MAXROWS - 1)) XX currow++; XX } XX break; XX case ctl (p): XX while (--arg>=0) { XX if (currow) XX currow--; XX else XX error ("At row zero"); XX while (hidden_row[currow] && currow) XX currow--; XX } XX break; XX case ctl (q): XX break; /* ignore flow control */ XX case ctl (s): XX break; /* ignore f{ XX nedistate = -1; XX narg = 1; XX if (edistate < 0 && linelim < 0 && (changed || FullUpdate)) XX EvalAll (), changed = 0; XX update (); XX refresh (); XX move (1, 0); XX clrtoeol (); XX fflush (stdout); XX seenerr = 0; XX if (((c = nmgetch ()) < ' ') || ( c == 0177 )) XX switch (c) { XX case ctl (z): XX quit(); XX break; XX case ctl (r): XX FullUpdate++; XX touchwin(); XX clear(); XX break; XX default: XX error ("No such command (^%c)", c + 0100); XX brlow control */ XX case ctl (t): XX showme ^= 1; XX break; XX case ctl (u): XX narg = arg * 4; XX nedistate = 1; XX break; XX case ctl (v): /* insert variable name */ XX if (linelim > 0) { XX sprintf (line+linelim,"%s%d", coltoa(curcol), currow); XX linelim = strlen (line); XX } XX break; XX case ctl (e): /* insert variable expression */ XX if (linelim > 0) editexp(currow,curcol); XX break; XX case ctl (a): /* insert variable value */ XX if (lineak; XX case ctl (b): XX while (--arg>=0) { XX if (curcol) XX curcol--; XX else XX error ("At column A"); XX while(hidden_col[curcol] && curcol) XX curcol--; XX } XX break; XX case ctl (c): XX running = 0; XX break; XX case ctl (f): XX while (--arg>=0) { XX if (curcol < MAXCOLS - 1) XX curcol++; XX else XX error ("The table can't be any wider"); XX while(hidden_col[curcol]&&(curcol 0) { XX struct ent *p = tbl[currow][curcol]; XX XX if (p && p -> flags & is_valid) { XX sprintf (line + linelim, "%.*f", XX precision[curcol],p -> v); XX linelim = strlen (line); XX } XX } XX break; XX } XX else XX if ('0' <= c && c <= '9' && (linelim < 0 || edistate >= 0)) { XX if (edistate != 0) { XX if (c == '0') /* just a '0' goes to left col */ XX curcol = 0; XX else { XX nedistate = 0; XX narg = c - '0'; XX } XX } el se { XX nedistate = 0; XX narg = arg * 10 + (c - '0'); XX } XX } XX else XX if (linelim >= 0) { XX line[linelim++] = c; XX line[linelim] = 0; XX } XX else XX switch (c) { XX case '.': XX nedistate = 1; XX break; XX case ':': XX break; /* Be nice to vi users */ XX case '=': XX sprintf(line,"let %s%d = ",coltoa(curcol),currow); XX linelim = strlen (line); XX break; XX case '/': XX sprintf(line,"copy [to] %s%d [from] ", XX  break; XX case 'W': XX sprintf (line, "write [listing to] \""); XX linelim = strlen (line); XX break; XX case 'T': /* tbl output */ XX sprintf (line, "tbl [listing to] \""); XX linelim = strlen (line); XX break; XX case 'i': XX switch (get_qual()) { XX case 'r': XX insertrow(arg); XX break; XX case 'c': XX insertcol(arg); XX break; XX default: XX break; XX } XX break; XX case 'd': XX switch (get_qual( coltoa(curcol), currow); XX linelim = strlen (line); XX break; XX case '$': XX curcol = MAXCOLS - 1; XX while (!tbl[currow][curcol] && curcol > 0) XX curcol--; XX break; XX case '?': XX help (); XX break; XX case '"': XX sprintf (line, "label %s%d = \"", XX coltoa(curcol), currow); XX linelim = strlen (line); XX break; XX case '<': XX sprintf (line, "leftstring %s%d = \"", XX coltoa(curcol), currow); XX l)) { XX case 'r': XX deleterow(arg); XX break; XX case 'c': XX deletecol(arg); XX break; XX default: XX break; XX } XX break; XX case 'v': XX switch (get_qual()) { XX case 'r': XX valueizerow(arg); XX break; XX case 'c': XX valueizecol(arg); XX break; XX default: XX break; XX } XX break; XX case 'p': XX { XX register qual; XX qual = get_qual(); XX while (arg--) XX pullcells(qinelim = strlen (line); XX break; XX case '>': XX sprintf (line, "rightstring %s%d = \"", XX coltoa(curcol), currow); XX linelim = strlen (line); XX break; XX case 'e': XX editv (currow, curcol); XX break; XX case 'E': XX edits (currow, curcol); XX break; XX case 'f': XX sprintf (line, "format [for column] %s [is] ", XX coltoa(curcol)); XX error("Current format is %d %d", XX fwidth[curcol],precision[curcol]); XX linelimual); XX break; XX } XX case 'x': XX { XX register struct ent **p; XX register int c; XX flush_saved(); XX for (c = curcol; arg-- && c < MAXCOLS; c++) { XX p = &tbl[currow][c]; XX if (*p) { XX free_ent(*p); XX *p = 0; XX } XX } XX sync_refs(); XX FullUpdate++; XX } XX break; XX case 'Q': XX case 'q': XX running = 0; XX break; XX case 'h': XX while (--arg>=0) { XX if (curc = strlen (line); XX break; XX case 'P': XX sprintf (line, "put [database into] \""); XX if (*curfile) XX error("default file is '%s'",curfile); XX linelim = strlen (line); XX break; XX case 'M': XX sprintf (line, "merge [database from] \""); XX linelim = strlen (line); XX break; XX case 'G': XX sprintf (line, "get [database from] \""); XX if (*curfile) XX error("default file is '%s'",curfile); XX linelim = strlen (line); XXol) XX curcol--; XX else XX error ("At column A"); XX while(hidden_col[curcol] && curcol) XX curcol--; XX } XX break; XX case 'j': XX while (--arg>=0) { XX if (currow < MAXROWS - 1) XX currow++; XX else XX error ("The table can't be any longer"); XX while (hidden_row[currow]&&(currow=0) { XX if (currow) XX currow--; XX else XX   error ("At row zero"); XX while (hidden_row[currow] && currow) XX currow--; XX } XX break; XX case 'l': XX while (--arg>=0) { XX if (curcol < MAXCOLS - 1) XX curcol++; XX else XX error ("The table can't be any wider"); XX while(hidden_col[curcol]&&(curcol flags = p -> flags; XX n -> v = p -> v; XX n -> expr = copye(p->expr, XX currow - savedrow, XX c - savedcol); XX n -> label = 0; XX if (p -> label) { XX n -> label = (char *) XX malloc(strlen(p->label)+1); X register struct ent **p; XX register r, c; XX char save[1024]; XX XX if (*fname == 0) fname = &curfile[0]; XX XX strcpy(save,fname); XX XX f = fopen (fname, "w"); XX if (f==0) { XX error ("Can't create %s", fname); XX return; XX } XX XX fprintf (f, "# This data file was generated by the Spreadsheet "); XX fprintf (f, "Calculator.\n"); XX fprintf (f, "# You almost certainly shouldn't edit it.\n\n"); XX for (c=0; c label, p -> label); XX } XX } XX break; XX } XX case 'z': XX switch (get_qual()) { XX case 'r': XX hiderow(arg); XX break; XX case 'c': XX hidecol(arg); XX break; XX default: XX break; XX } XX break; XX case 's': XX switch (get_qual()) { XX case 'r': XX showrow_op(); XX break; XX case 'c': XX showcol_op(); XX break; XX default: XX break; XX } XX break; XX case 'a': X= DEFPREC) XX fprintf (f, "format %s %d %d\n",coltoa(c),fwidth[c],precision[c]); XX for (r=0; r<=maxrow; r++) { XX p = &tbl[r][0]; XX for (c=0; c<=maxcol; c++, p++) XX if (*p) { XX if ((*p)->label) XX fprintf (f, "%sstring %s%d = \"%s\"\n", XX (*p)->flags&is_leftflush ? "left" : "right", XX coltoa(c),r,(*p)->label); XX if ((*p)->flags&is_valid) { XX editv (r, c); XX fprintf (f, "%s\n",line); XX } XX } XX } XX fclose (f); XX strcpy(curfile,save); XX XX modflX switch (get_qual()) { XX case 'r': XX while (arg--) XX duprow(); XX break; XX case 'c': XX while (arg--) XX dupcol(); XX break; XX default: XX break; XX } XX break; XX default: XX if ((c & 0177) != c) XX error("Weird character, decimal '%d'.\n", XX (int) c); XX else error ("No such command (%c)", c); XX break; XX } XX edistate = nedistate; XX arg = narg; XX } /* while (running) */ XX inloop = modchecg = 0; XX error("File '%s' written.",curfile); XX} XX XXreadfile (fname,eraseflg) XXchar *fname; int eraseflg; { XX register FILE *f; XX char save[1024]; XX XX if (*fname == 0) fname = &curfile[0]; XX strcpy(save,fname); XX XX if (eraseflg && strcmp(fname,curfile) && modcheck(" first")) return; XX XX f = fopen (save, "r"); XX if (f==0) { XX error ("Can't read %s", save); XX return; XX } XX XX if (eraseflg) erasedb (); XX XX while (fgets(line,sizeof line,f)) { XX linelim = 0;  XX if (line[0] != '#') yyparse (); XX } XX fclose (f); XX linelim = -1; XX modflg++; XX if (eraseflg) { XX strcpy(curfile,save); XX modflg = 0; XX } XX EvalAll(); XX} XX XXerasedb () { XX register r, c; XX for (c = 0; c<=maxcol; c++) { XX fwidth[c] = DEFWIDTH; XX precision[c] = DEFPREC; XX } XX XX for (r = 0; r<=maxrow; r++) { XX register struct ent **p = &tbl[r][0]; XX for (c=0; c++<=maxcol; p++) XX if (*p) { XX if ((*p)->expr) efree ((*p) -> expr); XX if ((*p)->labe ret = WORD; XX tokenl = p-tokenst; XX for (tbl = linelim ? experres : statres; tbl->key; tbl++) XX if (((tbl->key[0]^tokenst[0])&0137)==0 XX && tbl->key[tokenl]==0) { XX register i = 1; XX while (ikey[i])&0137)==0) XX i++; XX if (i>=tokenl) { XX ret = tbl->val; XX break; XX } XX } XX if (ret==WORD) { XX linelim = p-line; XX yyerror ("Unintelligible word"); XX } XX } XX } else if ((*p == '.') || isdigit(*p)) { XX rel) free ((*p) -> label); XX free (*p); XX *p = 0; XX } XX } XX maxrow = 0; XX maxcol = 0; XX FullUpdate++; XX} XX SHAR_EOF if test 16896 -ne "`wc -c sc.c`" then echo shar: error transmitting sc.c '(should have been 16896 characters)' fi echo shar: extracting lex.c sed 's/^XX//' << \SHAR_EOF > lex.c XX/* SC A Spreadsheet Calculator XX * Lexical analyser XX * XX * original by James Gosling, September 1982 XX * modifications by Mark Weiser and Bruce Israel, XX * University of Maryland XXgister long v = 0; XX char *nstart = p; XX if (*p != '.') { XX do v = v*10 + (*p-'0'); XX while (isdigit(*++p)); XX } XX if (*p=='.' || *p == 'e' || *p == 'E') { XX ret = FNUMBER; XX p = strtof(nstart, &yylval.fval); XX } else { XX if((int)v != v) XX { XX ret = FNUMBER; XX yylval.fval = v; XX } XX else XX { XX XX ret = NUMBER; XX yylval.ival = v; XX } XX } XX } el * XX * More mods Robert Bond, 12/86 XX * Major mods to run on VMS and AMIGA, 1/17/87 XX * XX */ XX XX XX XX#include "sc.h" XX#include XX#ifdef VMS XX#include "y_tab.h" XX#else XX#include "y.tab.h" XX#endif XX XXextern char *malloc(); XXchar *strtof(); XX XXstruct key { XX char *key; XX int val; XX}; XX XXstruct key experres[] = { XX#include "experres.h" XX 0, 0}; XX XXstruct key statres[] = { XX#include "statres.h" XX 0, 0}; XX XX#define ctl(x) ('x'&037) XX XXyylex () { se if (*p=='"') { XX /* This storage is never freed. Oh well. -MDW */ XX char *ptr; XX ptr = p+1; XX while(*ptr && *ptr++ != '"'); XX ptr = (char *)malloc((unsigned)(ptr-p)); XX yylval.sval = ptr; XX p += 1; XX while (*p && *p!='"') *ptr++ = *p++; XX *ptr = 0; XX if (*p) p += 1; XX ret = STRING; XX } else if (*p=='[') { XX while (*p && *p!=']') p++; XX if (*p) p++; XX linelim = p-line; XX return yylex(); XX } else ret = *p++; XX linelim = p-line; XX return ret; XX} XX XX#dXX register char *p = line+linelim; XX int ret = -1; XX while (isspace(*p)) p++; XX if (*p==0) ret = -1; XX else if (isalpha(*p)) { XX char *tokenst = p; XX register tokenl; XX register struct key *tbl; XX while (isalpha(*p)) p++; XX if (p-tokenst <= 2) { /* a COL is 1 or 2 char alpha */ XX register col; XX ret = COL; XX col = ((tokenst[0] & 0137) - 'A'); XX if (p == tokenst+2) XX col = (col + 1)*26 + ((tokenst[1] & 0137) - 'A'); XX yylval.ival = col; XX } else { XX efine N_KEY 26 XX XXstruct key_map { XX char *k_str; XX char k_val; XX char k_index; XX}; XX XXstruct key_map km[N_KEY]; XX XXinitkbd() XX{ XX int i; XX XX /* cursor set mode */ XX km[0].k_str = "\033OD"; km[0].k_val = ctl(b); XX km[1].k_str = "\033OC"; km[1].k_val = ctl(f); XX km[2].k_str = "\033OA"; km[2].k_val = ctl(p); XX km[3].k_str = "\033OB"; km[3].k_val = ctl(n); XX /* cursor reset mode */ XX km[4].k_str = "\033[D"; km[4].k_val = ctl(b); XX km[5].k_str   = "\033[C"; km[5].k_val = ctl(f); XX km[6].k_str = "\033[A"; km[6].k_val = ctl(p); XX km[7].k_str = "\033[B"; km[7].k_val = ctl(n); XX /* CSI arrows */ XX km[8].k_str = "\233D"; km[8].k_val = ctl(b); XX km[9].k_str = "\233C"; km[9].k_val = ctl(f); XX km[10].k_str = "\233A"; km[10].k_val = ctl(p); XX km[11].k_str = "\233B"; km[11].k_val = ctl(n); XX /* application keypad mode */ XX km[12].k_str = "\033Op"; km[12].k_val = '0'; XX km[13].k_str = "\033Oq"; km[13].k_va if (almost) return(nmgetch()); XX XX if (biggest) { XX for (i = 0; ik_index; i++) XX dumpbuf[i] = biggest->k_str[i]; XX dumpbuf[i++] = c; XX dumpbuf[i] = 0; XX dumpindex = &dumpbuf[1]; XX for (kp = &km[0]; kp < &km[N_KEY]; kp++) XX kp->k_index = 0; XX return (dumpbuf[0]); XX } XX XX return(c); XX} XX XX XXint dbline; XX XXdebug (fmt, a, b, c) { XX move(2+(dbline++%22),80-60); XX printw(fmt,a,b,c); XX clrtoeol(); XX} XX XX/* XX * This converts a floating point number ofl = '1'; XX km[14].k_str = "\033Or"; km[14].k_val = '2'; XX km[15].k_str = "\033Os"; km[15].k_val = '3'; XX km[16].k_str = "\033Ot"; km[16].k_val = '4'; XX km[17].k_str = "\033Ou"; km[17].k_val = '5'; XX km[18].k_str = "\033Ov"; km[18].k_val = '6'; XX km[19].k_str = "\033Ow"; km[19].k_val = '7'; XX km[20].k_str = "\033Ox"; km[20].k_val = '8'; XX km[21].k_str = "\033Oy"; km[21].k_val = '9'; XX km[22].k_str = "\033Om"; km[22].k_val = '-'; XX km[23].k_str = "\033Ol"; km[23].k_val  the form XX * [s]ddd[.d*][esd*] where s can be a + or - and e is E or e. XX * to floating point. XX * p is advanced. XX */ XX XXchar * XXstrtof(p, res) XXregister char *p; XXdouble *res; XX{ XX double acc; XX int sign; XX double fpos; XX int exp; XX int exps; XX XX acc = 0.0; XX sign = 1; XX exp = 0; XX exps = 1; XX if (*p == '+') XX p++; XX else if (*p == '-') { XX p++; XX sign = -1; XX } XX while (isdigit(*p)) { XX acc = acc * 10.0 + (d= ','; XX km[24].k_str = "\033On"; km[24].k_val = '.'; XX km[25].k_str = "\033OM"; km[25].k_val = ctl(m); XX} XX XXnmgetch() XX{ XX register int c; XX register struct key_map *kp; XX register struct key_map *biggest; XX register int i; XX int almost; XX int maybe; XX XX static char dumpbuf[10]; XX static char *dumpindex; XX XX void timeout(); XX XX if (dumpindex && *dumpindex) XX return (*dumpindex++); XX XX c = ttgetc(); XX biggest = 0; XX almost = 0; XX XXouble)(*p - '0'); XX p++; XX } XX if (*p == 'e' || *p == 'E') { XX p++; XX if (*p == '+') XX p++; XX else if (*p == '-') { XX p++; XX exps = -1; XX } XX while(isdigit(*p)) { XX exp = exp * 10 + (*p - '0'); XX p++; XX } XX } XX if (*p == '.') { XX fpos = 1.0/10.0; XX p++; XX while(isdigit(*p)) { XX acc += (*p - '0') * fpos; XX fpos *= 1.0/10.0; XX p++; XX } XX } XX if (*p == 'e' || *p == 'E') { XX exp = 0; XX exps for (kp = &km[0]; kp < &km[N_KEY]; kp++) { XX if (!kp->k_str) XX continue; XX if (c == (kp->k_str[kp->k_index] & 0xFF)) { XX almost = 1; XX kp->k_index++; XX if (kp->k_str[kp->k_index] == 0) { XX c = kp->k_val; XX for (kp = &km[0]; kp < &km[N_KEY]; kp++) XX kp->k_index = 0; XX return(c); XX } XX } XX if (!biggest && kp->k_index) XX biggest = kp; XX else if (kp->k_index && biggest->k_index < kp->k_index) XX biggest = kp; XX } XX XX = 1; XX p++; XX if (*p == '+') XX p++; XX else if (*p == '-') { XX p++; XX exps = -1; XX } XX while(isdigit(*p)) { XX exp = exp * 10 + (*p - '0'); XX p++; XX } XX } XX if (exp) { XX if (exps > 0) XX while (exp--) XX acc *= 10.0; XX else XX while (exp--) XX acc *= 1.0/10.0; XX } XX if (sign > 0) XX *res = acc; XX else XX *res = -acc; XX XX return(p); XX} XX XXhelp () { XX move(2,0); XX clrtobot(); XX dbline = 0; XX debug ("   Cursor cmds:"); XX debug (" ^n j next row ^p k prev. row ^g erase cmd"); XX debug (" ^f l fwd col ^b h back col ^r redraw screen"); XX debug (" 0 $ first, end col"); XX debug (" Cell cmds:"); XX debug (" \" < > enter label = enter value x clear cell"); XX debug (" c copy cell m mark cell ^t line 1 on/off"); XX debug (" ^a type value ^e type expr. ^v type vbl name"); XX debug (" 2 XX# define S_COPY 273 XX# define S_SHOW 274 XX# define K_FIXED 275 XX# define K_SUM 276 XX# define K_PROD 277 XX# define K_AVE 278 XX#define yyclearin yychar = -1 XX#define yyerrok yyerrflag = 0 XXextern int yychar; XXextern short yyerrflag; XX#ifndef YYMAXDEPTH XX#define YYMAXDEPTH 150 XX#endif XXYYSTYPE yylval, yyval; XX# define YYERRCODE 256 XXshort yyexca[] ={ XX-1, 1, XX 0, -1, XX -2, 0, XX-1, 83, XX 60, 0, XX 61, 0, XX 62, 0, XX -2, 34, XX-1, 85, XX 60, 0, XX 61, 0, XX 62, 0, XX -2, 35, XX-1, 86, XX Row, Column cmds:"); XX debug (" ar ac dup ir ic insert sr sc show"); XX debug (" dr dc delete zr zc hide pr pc pull"); XX debug (" vr vc value only f format"); XX debug (" File cmds:"); XX debug (" G get database M merge database T write tbl fmt"); XX debug (" P put database W write listing"); XX debug (" Misc. cmds:"); XX debug (" ^c, q quit / copy region pm pull (merge)"); XX  60, 0, XX 61, 0, XX 62, 0, XX -2, 36, XX-1, 96, XX 60, 0, XX 61, 0, XX 62, 0, XX -2, 39, XX-1, 97, XX 60, 0, XX 61, 0, XX 62, 0, XX -2, 41, XX-1, 98, XX 60, 0, XX 61, 0, XX 62, 0, XX -2, 40, XX }; XX# define YYNPROD 43 XX# define YYLAST 267 XXshort yyact[]={ XX XX 14, 69, 70, 71, 16, 55, 6, 3, 4, 5, XX 7, 9, 8, 2, 10, 11, 49, 13, 12, 27, XX 49, 54, 26, 43, 49, 20, 44, 43, 45, 53, XX 44, 43, 45, 34, 44, 30, 45, 52, 51, 50, XX 25, 24, 23, 22, 87, 21, 90, debug (" Expression Operators"); XX debug (" +-*/ arithmetic ?e:e conditional & | booleans"); XX debug (" < = > relations <= >= relations != relations"); XX debug (" @sum(v1:v2) @avg(v1:v2) @prod(v1:v2)"); XX} SHAR_EOF if test 7972 -ne "`wc -c lex.c`" then echo shar: error transmitting lex.c '(should have been 7972 characters)' fi echo shar: extracting gram.c sed 's/^XX//' << \SHAR_EOF > gram.c XX XX# line 15 "gram.y" XX#include "sc.h" XX XX# lin 42, 84, 67, XX 33, 42, 105, 32, 65, 42, 31, 67, 59, 57, XX 29, 58, 65, 60, 104, 94, 59, 57, 103, 58, XX 56, 60, 36, 35, 95, 111, 62, 63, 64, 61, XX 110, 109, 93, 67, 62, 63, 64, 61, 65, 39, XX 67, 67, 59, 57, 92, 58, 65, 60, 38, 59, XX 59, 57, 91, 58, 60, 60, 67, 1, 0, 48, XX 62, 63, 64, 48, 0, 0, 0, 48, 62, 63, XX 64, 61, 40, 0, 0, 15, 17, 18, 19, 0, XX 0, 68, 0, 0, 73, 74, 28, 0, 75, 76, XX 66, 0, 72, e 18 "gram.y" XXtypedef union { XX int ival; XX double fval; XX struct ent *ent; XX struct enode *enode; XX char *sval; XX} YYSTYPE; XX# define STRING 257 XX# define NUMBER 258 XX# define FNUMBER 259 XX# define WORD 260 XX# define COL 261 XX# define S_FORMAT 262 XX# define S_LABEL 263 XX# define S_LEFTSTRING 264 XX# define S_RIGHTSTRING 265 XX# define S_GET 266 XX# define S_PUT 267 XX# define S_MERGE 268 XX# define S_LET 269 XX# define S_WRITE 270 XX# define S_TBL 271 XX# define S_PROGLET 27 0, 0, 0, 0, 0, 66, 0, XX 0, 37, 0, 0, 0, 0, 78, 79, 80, 81, XX 82, 83, 85, 86, 88, 89, 67, 0, 0, 0, XX 0, 0, 0, 0, 66, 59, 57, 0, 58, 77, XX 60, 0, 66, 96, 0, 0, 97, 0, 0, 98, XX 67, 0, 0, 0, 102, 65, 67, 0, 0, 59, XX 57, 0, 58, 0, 60, 59, 57, 0, 58, 0, XX 60, 0, 0, 0, 99, 100, 101, 62, 63, 64, XX 0, 0, 0, 62, 63, 64, 106, 107, 108, 0, XX 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, X X 0, 46, 47, 0, 16, 46, 47, 0, 16, 46, XX 47, 0, 16, 0, 0, 0, 0, 0, 41, 0, XX 0, 0, 41, 0, 0, 0, 41 }; XXshort yypact[]={ XX XX-256,-1000,-257,-257,-257,-257,-236,-212,-214,-215, XX-216,-217,-239,-257,-1000, -1,-223, -5, -8, -11, XX-225,-1000,-1000,-1000,-1000,-1000, 15, 14,-257, -9, XX-1000,-218,-219,-220,-229,-240,-253, 12, 58,-1000, XX-1000, -9,-275, -9, -9, -9,-1000,-1000, -9, -9, XX-1000,-1000,-1000,-1000,-1000,-1000,-257, -9, -9, -9, XX -9, , 0, 0, 0, 15, 0, 0, 0, 0, 0, XX 0, 6, 7, 8, 9, 10, 0, 0, 0, 0, XX 42, 0, 0, 0, 0, 0, 0, 0, 1, 32, XX 16, 0, 0, 0, 0, 0, 24, 25, 0, 0, XX 2, 3, 4, 5, 11, 12, 0, 0, 0, 0, XX 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, XX 0, 0, 0, 22, 23, 26, 27, 13, 28, 29, XX 30, 31, 0, -2, 0, -2, -2, 0, 37, 38, XX 0, 0, 0, 0, 21, 0, -2, -2, -2, 0, XX 0, 0, 33, 0, 0, 0, 0, 0-9, -13, -9, -17, -9, -9, -15,-1000, 62, XX 54, 42, 24,-1000,-1000,-1000,-1000,-1000, 57, 57, XX 73, 73, 16, 133, -9, 133, 133, -9, 163, 157, XX -9,-257,-257,-257,-1000, -9, 133, 133, 133, 10, XX 6, -6, 50,-257,-257,-257, 40, 39, 34,-1000, XX-1000,-1000 }; XXshort yypgo[]={ XX XX 0, 122, 98, 89, 107 }; XXshort yyr1[]={ XX XX 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, XX 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, XX 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, X, 0, 18, XX 19, 20 }; XX#ifndef lint XXstatic char yaccpar_sccsid[] = "@(#)yaccpar 4.1 (Berkeley) 2/11/83"; XX#endif not lint XX XX# XX# define YYFLAG -1000 XX# define YYERROR goto yyerrlab XX# define YYACCEPT return(0) XX# define YYABORT return(1) XX XX/* parser for yacc output */ XX XX#ifdef YYDEBUG XXint yydebug = 0; /* 1 for debugging */ XX#endif XXYYSTYPE yyv[YYMAXDEPTH]; /* where the values are stored */ XXint yychar = -1; /* current input token number */ XXint yynerrs = 0; /* number of errors *X 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, XX 2, 2, 1 }; XXshort yyr2[]={ XX XX 0, 4, 4, 4, 4, 4, 2, 2, 2, 2, XX 2, 4, 4, 5, 0, 1, 1, 2, 7, 7, XX 7, 3, 2, 2, 1, 1, 2, 2, 3, 3, XX 3, 3, 1, 5, 3, 3, 3, 3, 3, 4, XX 4, 4, 2 }; XXshort yychk[]={ XX XX-1000, -4, 269, 263, 264, 265, 262, 266, 268, 267, XX 270, 271, 274, 273, 256, -1, 261, -1, -1, -1, XX 261, 257, 257, 257, 257, 257, 261, 258, -1, 61, XX 258,/ XXshort yyerrflag = 0; /* error recovery flag */ XX XXyyparse() { XX XX short yys[YYMAXDEPTH]; XX short yyj, yym; XX register YYSTYPE *yypvt; XX register short yystate, *yyps, yyn; XX register YYSTYPE *yypv; XX register short *yyxi; XX XX yystate = 0; XX yychar = -1; XX yynerrs = 0; XX yyerrflag = 0; XX yyps= &yys[-1]; XX yypv= &yyv[-1]; XX XX yystack: /* put a state and value onto the stack */ XX XX#ifdef YYDEBUG XX if( yydebug ) printf( "state %d, char 0%o\n", yystate, yychar ); XX#endif XX if( ++ 61, 61, 61, 258, 58, 58, -1, -2, -3, XX -1, 275, 64, 40, 43, 45, 258, 259, 126, 33, XX 257, 257, 257, 258, 261, 258, 58, 43, 45, 42, XX 47, 63, 60, 61, 62, 38, 124, 33, -3, 276, XX 277, 278, -2, -3, -3, -3, -3, -1, -2, -2, XX -2, -2, -2, -2, 61, -2, -2, 61, -2, -2, XX 61, 40, 40, 40, 41, 58, -2, -2, -2, -1, XX -1, -1, -2, 58, 58, 58, -1, -1, -1, 41, XX 41, 41 }; XXshort yydef[]={ XX XX 14, -2, 0, 0, 0, 0, 0, 0, 0, 0, XX 0yyps> &yys[YYMAXDEPTH] ) { yyerror( "yacc stack overflow" ); return(1); } XX *yyps = yystate; XX ++yypv; XX *yypv = yyval; XX XX yynewstate: XX XX yyn = yypact[yystate]; XX XX if( yyn<= YYFLAG ) goto yydefault; /* simple state */ XX XX if( yychar<0 ) if( (yychar=yylex())<0 ) yychar=0; XX if( (yyn += yychar)<0 || yyn >= YYLAST ) goto yydefault; XX XX if( yychk[ yyn=yyact[ yyn ] ] == yychar ){ /* valid shift */ XX yychar = -1; XX yyval = yylval; XX yystate = yyn; XX if( yyerrflag > 0 ) --yyerrflag; XX   goto yystack; XX } XX XX yydefault: XX /* default state action */ XX XX if( (yyn=yydef[yystate]) == -2 ) { XX if( yychar<0 ) if( (yychar=yylex())<0 ) yychar = 0; XX /* look through exception table */ XX XX for( yyxi=yyexca; (*yyxi!= (-1)) || (yyxi[1]!=yystate) ; yyxi += 2 ) ; /* VOID */ XX XX while( *(yyxi+=2) >= 0 ){ XX if( *yyxi == yychar ) break; XX } XX if( (yyn = yyxi[1]) < 0 ) return(0); /* accept */ XX } XX XX if( yyn == 0 ){ /* error */ XX /* error ... attempt to resume parsing */ XX ypgo[yyn] + *yyps + 1; XX if( yyj>=YYLAST || yychk[ yystate = yyact[yyj] ] != -yyn ) yystate = yyact[yypgo[yyn]]; XX switch(yym){ XX XXcase 1: XX# line 59 "gram.y" XX{ let (yypvt[-2].ent, yypvt[-0].enode); } break; XXcase 2: XX# line 61 "gram.y" XX{ label (yypvt[-2].ent, yypvt[-0].sval, 0); } break; XXcase 3: XX# line 63 "gram.y" XX{ label (yypvt[-2].ent, yypvt[-0].sval, -1); } break; XXcase 4: XX# line 65 "gram.y" XX{ label (yypvt[-2].ent, yypvt[-0].sval, 1); } break; XXcase 5: XX# line 67 "gram.y" XXXX switch( yyerrflag ){ XX XX case 0: /* brand new error */ XX XX yyerror( "syntax error" ); XX yyerrlab: XX ++yynerrs; XX XX case 1: XX case 2: /* incompletely recovered error ... try again */ XX XX yyerrflag = 3; XX XX /* find a state where "error" is a legal shift action */ XX XX while ( yyps >= yys ) { XX yyn = yypact[*yyps] + YYERRCODE; XX if( yyn>= 0 && yyn < YYLAST && yychk[yyact[yyn]] == YYERRCODE ){ XX yystate = yyact[yyn]; /* simulate a shift of "error" */ XX { fwidth[yypvt[-2].ival] = yypvt[-1].ival; XX FullUpdate++; XX modflg++; XX precision[yypvt[-2].ival] = yypvt[-0].ival; } break; XXcase 6: XX# line 71 "gram.y" XX{ readfile (yypvt[-0].sval,1); } break; XXcase 7: XX# line 72 "gram.y" XX{ readfile (yypvt[-0].sval,0); } break; XXcase 8: XX# line 73 "gram.y" XX{ writefile (yypvt[-0].sval); } break; XXcase 9: XX# line 74 "gram.y" XX{ printfile (yypvt[-0].sval); } break; XXcase 10: XX# line 75 "gram.y" XX{ tblprintfile (yypvt[-0].sval); } break; XX goto yystack; XX } XX yyn = yypact[*yyps]; XX XX /* the current yyps has no shift onn "error", pop stack */ XX XX#ifdef YYDEBUG XX if( yydebug ) printf( "error recovery pops state %d, uncovers %d\n", *yyps, yyps[-1] ); XX#endif XX --yyps; XX --yypv; XX } XX XX /* there is no state on the stack with an error shift ... abort */ XX XX yyabort: XX return(1); XX XX XX case 3: /* no shift yet; clobber input char */ XX XX#ifdef YYDEBUG XX if( yydebug ) printf( "ecase 11: XX# line 76 "gram.y" XX{ showcol( yypvt[-2].ival, yypvt[-0].ival); } break; XXcase 12: XX# line 77 "gram.y" XX{ showrow( yypvt[-2].ival, yypvt[-0].ival); } break; XXcase 13: XX# line 79 "gram.y" XX{ copy(yypvt[-3].ent, yypvt[-2].ent, yypvt[-0].ent); } break; XXcase 16: XX# line 83 "gram.y" XX{ yyval.enode = new ('v', yypvt[-0].ent); } break; XXcase 17: XX# line 84 "gram.y" XX{ yyval.enode = new ('f', 0L, yypvt[-0].enode); } break; XXcase 18: XX# line 86 "gram.y" XX{ yyval.enode = new (O_REDUCE('+')rror recovery discards char %d\n", yychar ); XX#endif XX XX if( yychar == 0 ) goto yyabort; /* don't discard EOF, quit */ XX yychar = -1; XX goto yynewstate; /* try again in the same state */ XX XX } XX XX } XX XX /* reduction by production yyn */ XX XX#ifdef YYDEBUG XX if( yydebug ) printf("reduce %d\n",yyn); XX#endif XX yyps -= yyr2[yyn]; XX yypvt = yypv; XX yypv -= yyr2[yyn]; XX yyval = yypv[1]; XX yym=yyn; XX /* consult goto table to find next state */ XX yyn = yyr1[yyn]; XX yyj = y, yypvt[-3].ent, yypvt[-1].ent); } break; XXcase 19: XX# line 88 "gram.y" XX{ yyval.enode = new (O_REDUCE('*'), yypvt[-3].ent, yypvt[-1].ent); } break; XXcase 20: XX# line 90 "gram.y" XX{ yyval.enode = new (O_REDUCE('a'), yypvt[-3].ent, yypvt[-1].ent); } break; XXcase 21: XX# line 91 "gram.y" XX{ yyval.enode = yypvt[-1].enode; } break; XXcase 22: XX# line 92 "gram.y" XX{ yyval.enode = yypvt[-0].enode; } break; XXcase 23: XX# line 93 "gram.y" XX{ yyval.enode = new ('m', 0L, yypvt[-0].enode); } break; XXcase  24: XX# line 94 "gram.y" XX{ yyval.enode = new ('k', (double) yypvt[-0].ival); } break; XXcase 25: XX# line 95 "gram.y" XX{ yyval.enode = new ('k', yypvt[-0].fval); } break; XXcase 26: XX# line 96 "gram.y" XX{ yyval.enode = new ('~', 0L, yypvt[-0].enode); } break; XXcase 27: XX# line 97 "gram.y" XX{ yyval.enode = new ('~', 0L, yypvt[-0].enode); } break; XXcase 28: XX# line 100 "gram.y" XX{ yyval.enode = new ('+', yypvt[-2].enode, yypvt[-0].enode); } break; XXcase 29: XX# line 101 "gram.y" XX{ yyval.enode = ould have been 11880 characters)' fi echo shar: extracting interp.c sed 's/^XX//' << \SHAR_EOF > interp.c XX/* SC A Spreadsheet Calculator XX * Expression interpreter and assorted support routines. XX * XX * original by James Gosling, September 1982 XX * modified by Mark Weiser and Bruce Israel, XX * University of Maryland XX * XX * More mods Robert Bond, 12/86 XX * Major mods to run on VMS and AMIGA, 1/17/87 XX */ XX XX#include "sc.h" XX#define DEFCOLDELIM ':' XX XXchar *malloc(); XX XXnew ('-', yypvt[-2].enode, yypvt[-0].enode); } break; XXcase 30: XX# line 102 "gram.y" XX{ yyval.enode = new ('*', yypvt[-2].enode, yypvt[-0].enode); } break; XXcase 31: XX# line 103 "gram.y" XX{ yyval.enode = new ('/', yypvt[-2].enode, yypvt[-0].enode); } break; XXcase 33: XX# line 105 "gram.y" XX{ yyval.enode = new ('?', yypvt[-4].enode, new(':', yypvt[-2].enode, yypvt[-0].enode)); } break; XXcase 34: XX# line 106 "gram.y" XX{ yyval.enode = new ('<', yypvt[-2].enode, yypvt[-0].enode); } break; XXcase 35: double dosum(minr, minc, maxr, maxc) XXint minr, minc, maxr, maxc; XX{ XX double v; XX register r,c; XX register struct ent *p; XX XX v = 0; XX for (r = minr; r<=maxr; r++) XX for (c = minc; c<=maxc; c++) XX if ((p = tbl[r][c]) && p->flags&is_valid) XX v += p->v; XX return v; XX} XX XXdouble doprod(minr, minc, maxr, maxc) XXint minr, minc, maxr, maxc; XX{ XX double v; XX register r,c; XX register struct ent *p; XX XX v = 1; XX for (r = minr; r<=maxr; r++) XX for (c = miXX# line 107 "gram.y" XX{ yyval.enode = new ('=', yypvt[-2].enode, yypvt[-0].enode); } break; XXcase 36: XX# line 108 "gram.y" XX{ yyval.enode = new ('>', yypvt[-2].enode, yypvt[-0].enode); } break; XXcase 37: XX# line 109 "gram.y" XX{ yyval.enode = new ('&', yypvt[-2].enode, yypvt[-0].enode); } break; XXcase 38: XX# line 110 "gram.y" XX{ yyval.enode = new ('|', yypvt[-2].enode, yypvt[-0].enode); } break; XXcase 39: XX# line 111 "gram.y" XX{ yyval.enode = new ('~', 0L, new ('>', yypvt[-3].enode, yypvt[-0].enc; c<=maxc; c++) XX if ((p = tbl[r][c]) && p->flags&is_valid) XX v *= p->v; XX return v; XX} XX XXdouble doavg(minr, minc, maxr, maxc) XXint minr, minc, maxr, maxc; XX{ XX double v; XX register r,c,count; XX register struct ent *p; XX XX v = 0; XX count = 0; XX for (r = minr; r<=maxr; r++) XX for (c = minc; c<=maxc; c++) XX if ((p = tbl[r][c]) && p->flags&is_valid) { XX v += p->v; XX count++; XX } XX XX return (v / (double)count); XX} XX XXdouble eval(e) XXregister stnode)); } break; XXcase 40: XX# line 112 "gram.y" XX{ yyval.enode = new ('~', 0L, new ('=', yypvt[-3].enode, yypvt[-0].enode)); } break; XXcase 41: XX# line 113 "gram.y" XX{ yyval.enode = new ('~', 0L, new ('<', yypvt[-3].enode, yypvt[-0].enode)); } break; XXcase 42: XX# line 116 "gram.y" XX{ yyval.ent = lookat(yypvt[-0].ival , yypvt[-1].ival); } break; XX } XX goto yystack; /* stack new state and value */ XX XX } SHAR_EOF if test 11880 -ne "`wc -c gram.c`" then echo shar: error transmitting gram.c '(shruct enode *e; { XX if (e==0) return 0; XX switch (e->op) { XX case '+': return (eval(e->e.o.left) + eval(e->e.o.right)); XX case '-': return (eval(e->e.o.left) - eval(e->e.o.right)); XX case '*': return (eval(e->e.o.left) * eval(e->e.o.right)); XX case '/': { double denom = eval (e->e.o.right); XX return denom ? eval(e->e.o.left) / denom : 0; } XX case '<': return (eval(e->e.o.left) < eval(e->e.o.right)); XX case '=': return (eval(e->e.o.left) == eval(e->e.o.right)); XX case '>': return (eval(e->e.o.left) > eval(e->e.o.right)); XX case '&': return (eval(e->e.o.left) != 0.0 && XX eval(e->e.o.right) != 0.0) ? 1.0 : 0.0; XX case '|': return (eval(e->e.o.left) != 0.0 || XX eval(e->e.o.right) != 0.0) ? 1.0 : 0.0; XX case '?': return eval(e->e.o.left) ? eval(e->e.o.right->e.o.left) XX : eval(e->e.o.right->e.o.right); XX case 'm': return (-eval(e->e.o.right)); XX case 'f': return (eval(e->e.o.right)); XX case '~': return (!eval(e->e.o.right)); XX case 'k': return (e->e.k); XX cas&a1; break; XX default: p->e.o.left = a1; p->e.o.right = a2; XX } XX return p; XX} XX XXcopy (dv, v1, v2) XXstruct ent *dv, *v1, *v2; XX{ XX register r,c; XX register struct ent *p; XX register struct ent *n; XX register deltar, deltac; XX int maxr, maxc; XX int minr, minc; XX int dr, dc; XX XX dr = dv->row; XX dc = dv->col; XX maxr = v2->row; XX maxc = v2->col; XX minr = v1->row; XX minc = v1->col; XX if (minr>maxr) r = maxr, maxr = minr, minr = r; XX ie 'v': return (e->e.v->v); XX case O_REDUCE('+'): XX case O_REDUCE('*'): XX case O_REDUCE('a'): XX { register r,c; XX register maxr, maxc; XX register minr, minc; XX maxr = ((struct ent *) e->e.o.right) -> row; XX maxc = ((struct ent *) e->e.o.right) -> col; XX minr = ((struct ent *) e->e.o.left) -> row; XX minc = ((struct ent *) e->e.o.left) -> col; XX if (minr>maxr) r = maxr, maxr = minr, minr = r; XX if (minc>maxc) c = maxc, maxc = minc, minc = c; XX switch (e->op) { XX f (minc>maxc) c = maxc, maxc = minc, minc = c; XX if (dr+maxr-minr >= MAXROWS || XX dc+maxc-minc >= MAXCOLS) { XX error ("The table can't be any bigger"); XX return; XX } XX deltar = dr-minr; XX deltac = dc-minc; XX FullUpdate++; XX for (r = minr; r<=maxr; r++) XX for (c = minc; c<=maxc; c++) { XX n = lookat (r+deltar, c+deltac); XX clearent(n); XX if (p = tbl[r][c]) { XX n -> v = p -> v; XX n -> flags = p -> flags; XX n -> expr = copye(p->expr, deltar, deltac); case O_REDUCE('+'): return dosum(minr, minc, maxr, maxc); XX case O_REDUCE('*'): return doprod(minr, minc, maxr, maxc); XX case O_REDUCE('a'): return doavg(minr, minc, maxr, maxc); XX } XX } XX } XX} XX XX#define MAXPROP 7 XX XXEvalAll () { XX int lastct,repct = 0; XX XX while ((lastct = RealEvalAll()) && (repct++ <= MAXPROP)); XX XX repct--; XX} XX XXint RealEvalAll () { XX register i,j; XX int chgct = 0; XX register struct ent *p; XX for (i=0; i<=maxrXX n -> label = 0; XX if (p -> label) { XX n -> label = (char *) XX malloc (strlen (p -> label) + 1); XX strcpy (n -> label, p -> label); XX } XX } XX } XX} XX XXlet (v, e) XXstruct ent *v; XXstruct enode *e; { XX efree (v->expr); XX if (constant(e)) { XX v->v = eval(e); XX v->expr = 0; XX efree(e); XX } else XX v->expr = e; XX v->flags |= (is_changed|is_valid); XX changed++; XX modflg++; XX} XX XXclearent (v) XXstruct ent *v; { XX if (!v) XX return; XX label(v,"ow; i++) XX for (j=0; j<=maxcol; j++) XX if ((p=tbl[i][j]) && p->expr) { XX double v = eval (p->expr); XX if (v != p->v) { XX p->v = v; chgct++; XX p->flags |= (is_changed|is_valid); XX } XX } XX return(chgct); XX} XX XXstruct enode *new(op,a1,a2) XXstruct enode *a1, *a2; { XX register struct enode *p = (struct enode *) malloc (sizeof (struct enode)); XX p->op = op; XX switch (op) { XX case O_VAR: p->e.v = (struct ent *) a1; break; XX case O_CONST: p->e.k = *(double *)",-1); XX v->v = 0; XX if (v->expr) XX efree(v->expr); XX v->expr = 0; XX v->flags |= (is_changed); XX v->flags &= ~(is_valid); XX changed++; XX modflg++; XX} XX XXconstant(e) XXregister struct enode *e; { XX return e==0 || e->op == O_CONST XX || (e->op != O_VAR XX && (e->op&~0177) != O_REDUCE(0) XX && constant (e->e.o.left) XX && constant(e->e.o.right)); XX} XX XXefree (e) XXregister struct enode *e; { XX if (e) { XX if (e->op != O_VAR && e->op !=O_CONST && (e->op&~0177) != O_REDUCE(0)) { XX efree (e->e.o.left); XX efree (e->e.o.right); XX } XX free (e); XX } XX} XX XXlabel (v, s, flushdir) XXregister struct ent *v; XXregister char *s; { XX if (v) { XX if (flushdir==0 && v->flags&is_valid) { XX register struct ent *tv; XX if (v->col>0 && ((tv=lookat(v->row,v->col-1))->flags&is_valid)==0) XX v = tv, flushdir = 1; XX else if (((tv=lookat (v->row,v->col+1))->flags&is_valid)==0) XX v = tv, flushdir = -1; XX else flushdir = -1; XX } XX if (v->label) f (e->e.o.right, 30); XX break; XX case '~': line[linelim++] = '~'; XX decompile (e->e.o.right, 30); XX break; XX case 'v': decodev (e->e.v); XX break; XX case 'k': sprintf (line+linelim,"%.8g",e->e.k); XX linelim += strlen (line+linelim); XX break; XX case O_REDUCE('+'): XX for (s="@sum("; line[linelim++] = *s++;); XX goto more; XX case O_REDUCE('*'): XX for (s="@prod("; line[linelim++] = *s++;); XX goto more; XX case O_REDUCE('a'): XX for (s="@avg("; line[linelim++] = *s++;); XX more:ree(v->label); XX if (s && s[0]) { XX v->label = (char *) malloc (strlen(s)+1); XX strcpy (v->label, s); XX } else v->label = 0; XX v->flags |= is_lchanged; XX if (flushdir<0) v->flags |= is_leftflush; XX else v->flags &= ~is_leftflush; XX FullUpdate++; XX modflg++; XX } XX} XX XXdecodev (v) XXregister struct ent *v; { XX if (v) sprintf (line+linelim, "%s%d", coltoa(v->col), v->row); XX else sprintf (line+linelim,"VAR?"); XX linelim += strlen (line+linelim); XX} XX XXchar * XXcoltoa(col) XXint co linelim--; XX decodev (e->e.o.left); XX line[linelim++] = ':'; XX decodev (e->e.o.right); XX line[linelim++] = ')'; XX break; XX XX default: decompile (e->e.o.left, mypriority); XX line[linelim++] = e->op; XX decompile (e->e.o.right, mypriority+1); XX break; XX } XX if (mypriority 25) { XX *p++ = col/26 + 'A' - 1; XX col %= 26; XX } XX *p++ = col+'A'; XX *p = 0; XX return(rname); XX} XX XXdecompile(e, priority) XXregister struct enode *e; { XX register char *s; XX if (e) { XX int mypriority; XX switch (e->op) { XX default: mypriority = 99; break; XX case '?': mypriority = 1; break; XX case ':': mypriori XXeditexp(row,col) { XX register struct ent *p; XX p = lookat (row, col); XX if (p->flags&is_valid) XX if (p->expr) { XX decompile (p->expr); XX line[linelim] = 0; XX } else { XX sprintf (line+linelim, "%.8g", p->v); XX linelim += strlen (line+linelim); XX } XX} XX XXedits (row, col) { XX register struct ent *p = lookat (row, col); XX sprintf (line, "%sstring %s%d = \"", XX ((p->flags&is_leftflush) ? "left" : "right"), XX coltoa(col), row); XX linelim = strlen(line); Xty = 2; break; XX case '|': mypriority = 3; break; XX case '&': mypriority = 4; break; XX case '<': case '=': case '>': mypriority = 6; break; XX case '+': case '-': mypriority = 8; break; XX case '*': case '/': mypriority = 10; break; XX } XX if (mypriorityop) { XX case 'f': { XX for (s="fixed "; line[linelim++] = *s++;); XX linelim--; XX decompile (e->e.o.right, 30); XX break; XX } XX case 'm': line[linelim++] = '-'; XX decompileX sprintf (line+linelim, "%s", p->label); XX linelim += strlen (line+linelim); XX} XX XXprintfile (fname) { XX FILE *f = fopen(fname, "w"); XX char pline[1000]; XX int plinelim; XX register row, col; XX register struct ent **p; XX if (f==0) { XX error ("Can't create %s", fname); XX return; XX } XX for (row=0;row<=maxrow; row++) { XX register c = 0; XX plinelim = 0; XX for (p = &tbl[row][col=0]; col<=maxcol; col++, p++) { XX if (*p) { XX char *s; XX while (plinelimflags&is_valid) { XX sprintf (pline+plinelim,"%*.*f",fwidth[col],precision[col], XX (*p)->v); XX plinelim += strlen (pline+plinelim); XX } XX if (s = (*p)->label) { XX register char *d; XX d = pline+((*p)->flags&is_leftflush XX ? c : c-strlen(s)+fwidth[col]); XX while (d>pline+plinelim) pline[plinelim++] = ' '; XX if (dplinelim) plinelim = d-pline;  ); XX ret->e.o.left = (struct enode *) lookat ( XX ((struct ent *)e->e.o.left)->row+Rdelta, XX ((struct ent *)e->e.o.left)->col+Cdelta XX ); XX break; XX default: XX ret->e.o.right = copye (e->e.o.right,Rdelta,Cdelta); XX ret->e.o.left = copye (e->e.o.left,Rdelta,Cdelta); XX break; XX } XX } XX return ret; XX} XX XX/* XX * sync_refs and sync_ref are used to remove references to XX * deleted struct ents. Note that the deleted structure must still XX * be hanging aXX } XX } XX c += fwidth [col]; XX } XX fprintf (f,"%.*s\n",plinelim,pline); XX } XX fclose (f); XX} XX XXtblprintfile (fname) { XX FILE *f = fopen(fname, "w"); XX char pline[1000]; XX int plinelim; XX register row, col; XX register struct ent **p; XX char coldelim = DEFCOLDELIM; XX XX if (f==0) { XX error ("Can't create %s", fname); XX return; XX } XX for (row=0;row<=maxrow; row++) { XX register c = 0; XX plinelim = 0; XX for (p = &tbl[row][col=0]; col<=maxcol; colround before the call, but not referenced by an entry XX * in tbl. Thus the free_ent, fix_ent calls in sc.c XX */ XX XXsync_refs () { XX register i,j; XX register struct ent *p; XX for (i=0; i<=maxrow; i++) XX for (j=0; j<=maxcol; j++) XX if ((p=tbl[i][j]) && p->expr) XX sync_ref(p->expr); XX} XX XX XXsync_ref(e) XXregister struct enode *e; XX{ XX if (e==0) XX return; XX else { XX switch (e->op) { XX case 'v': XX e->e.v = lookat(e->e.v->row, e->e.v->col); XX break; XX case 'k': XX br++, p++) { XX if (*p) { XX char *s; XX if ((*p)->flags&is_valid) { XX fprintf (f,"%.*f",precision[col], XX (*p)->v); XX } XX if (s = (*p)->label) { XX fprintf (f,"%s",s); XX } XX } XX fprintf(f,"%c",coldelim); XX } XX fprintf (f,"\n",pline); XX } XX fclose (f); XX} XX XXstruct enode *copye (e, Rdelta, Cdelta) XXregister struct enode *e; { XX register struct enode *ret; XX if (e==0) ret = 0; XX else { XX ret = (struct enode *) malloc (sizeof (struct enode))eak; XX case O_REDUCE('+'): XX case O_REDUCE('*'): XX case O_REDUCE('a'): XX e->e.o.right = (struct enode *) lookat ( XX ((struct ent *)e->e.o.right)->row, XX ((struct ent *)e->e.o.right)->col XX ); XX e->e.o.left = (struct enode *) lookat ( XX ((struct ent *)e->e.o.left)->row, XX ((struct ent *)e->e.o.left)->col XX ); XX break; XX default: XX sync_ref(e->e.o.right); XX sync_ref(e->e.o.left); XX break; XX } XX } XX} XX XXhiderow(arg) XX; XX ret->op = e->op; XX switch (ret->op) { XX case 'v': XX ret->e.v = lookat (e->e.v->row+Rdelta, e->e.v->col+Cdelta); XX break; XX case 'k': XX ret->e.k = e->e.k; XX break; XX case 'f': XX ret->e.o.right = copye (e->e.o.right,0,0); XX ret->e.o.left = 0; XX break; XX case O_REDUCE('+'): XX case O_REDUCE('*'): XX case O_REDUCE('a'): XX ret->e.o.right = (struct enode *) lookat ( XX ((struct ent *)e->e.o.right)->row+Rdelta, XX ((struct ent *)e->e.o.right)->col+Cdelta XX { XX register int r1; XX register int r2; XX XX r1 = currow; XX r2 = r1 + arg - 1; XX if (r1 < 0 || r1 > r2) { XX error("Invalid Range"); XX return; XX } XX if (r2 > MAXROWS-2) { XX error("You can't hide the last row"); XX return; XX } XX FullUpdate++; XX while (r1 <= r2) XX hidden_row[r1++] = 1; XX} XX XXhidecol(arg) XX{ XX register int c1; XX register int c2; XX XX c1 = curcol; XX c2 = c1 + arg - 1; XX if (c1 < 0 || c1 > c2) { XX error("Invalid Range"); XX return; XX } XX if (c2 > MAXCOLS-2) { XX error("You can't hide the last col"); XX return; XX } XX FullUpdate++; XX while (c1 <= c2) XX hidden_col[c1++] = 1; XX} XX XXshowrow(r1, r2) XX{ XX if (r1 < 0 || r1 > r2) { XX error("Invalid Range"); XX return; XX } XX if (r2 > MAXROWS-1) { XX r2 = MAXROWS-1; XX } XX FullUpdate++; XX while (r1 <= r2) XX hidden_row[r1++] = 0; XX} XX XXshowcol(c1, c2) XX{ XX if (c1 < 0 || c1 > c2) { XX error("Invalid Range"); XX return; XX } XX if 0; XX} XX XXdupcol() XX{ XX if (curcol >= MAXCOLS - 1 || maxcol >= MAXCOLS - 1) { XX error ("The table can't be any wider"); XX return; XX } XX modflg++; XX curcol++; XX opencol (curcol); XX for (currow = 0; currow <= maxrow; currow++) { XX register struct ent *p = tbl[currow][curcol - 1]; XX if (p) { XX register struct ent *n; XX n = lookat (currow, curcol); XX n -> v = p -> v; XX n -> flags = p -> flags; XX n -> expr = copye (p -> expr, 0, 1); XX n -> label = 0; (c2 > MAXCOLS-1) { XX c2 = MAXCOLS-1; XX } XX FullUpdate++; XX while (c1 <= c2) XX hidden_col[c1++] = 0; XX} SHAR_EOF if test 13644 -ne "`wc -c interp.c`" then echo shar: error transmitting interp.c '(should have been 13644 characters)' fi echo shar: extracting cmds.c sed 's/^XX//' << \SHAR_EOF > cmds.c XX/* SC A Spreadsheet Calculator XX * Main driver XX * XX * original by James Gosling, September 1982 XX * modifications by Mark Weiser and Bruce Israel, XX * University of Maryland XX * XX * XX if (p -> label) { XX n -> label = (char *) XX malloc (strlen (p -> label) + 1); XX strcpy (n -> label, p -> label); XX } XX } XX } XX for (currow = 0; currow <= maxrow; currow++) { XX register struct ent *p = tbl[currow][curcol]; XX if (p && (p -> flags & is_valid) && !p -> expr) XX break; XX } XX if (currow > maxrow) XX currow = 0; XX} XX XXinsertrow(arg) XX{ XX while (--arg>=0) openrow (currow); XX} XX XXdeleterow(arg) XX{ XX flush_saved(); XX erase_area(currow More mods Robert Bond, 12/86 XX * Major mods to run on VMS and AMIGA, 1/17/87 XX * XX */ XX XX#include "sc.h" XX XXextern char *malloc(); XX XXduprow() XX{ XX if (currow >= MAXROWS - 1 || maxrow >= MAXROWS - 1) { XX error ("The table can't be any bigger"); XX return; XX } XX modflg++; XX currow++; XX openrow (currow); XX for (curcol = 0; curcol <= maxcol; curcol++) { XX register struct ent *p = tbl[currow - 1][curcol]; XX if (p) { XX register struct ent *n; XX n = look, 0, currow + arg - 1, maxcol); XX currow += arg; XX while (--arg>=0) closerow (--currow); XX sync_refs(); XX} XX XXinsertcol(arg) XX{ XX while (--arg>=0) opencol(curcol); XX} XX XXdeletecol(arg) XX{ XX flush_saved(); XX erase_area(0, curcol, maxrow, curcol + arg - 1); XX curcol += arg; XX while (--arg>=0) closecol (--curcol); XX sync_refs(); XX} XX XXvalueizerow(arg) XX{ XX valueize_area(currow, 0, currow + arg - 1, maxcol); XX} XX XXvalueizecol(arg) XX{ XX valueize_area(0,at (currow, curcol); XX n -> v = p -> v; XX n -> flags = p -> flags; XX n -> expr = copye (p -> expr, 1, 0); XX n -> label = 0; XX if (p -> label) { XX n -> label = (char *) XX malloc (strlen (p -> label) + 1); XX strcpy (n -> label, p -> label); XX } XX } XX } XX for (curcol = 0; curcol <= maxcol; curcol++) { XX register struct ent *p = tbl[currow][curcol]; XX if (p && (p -> flags & is_valid) && !p -> expr) XX break; XX } XX if (curcol > maxcol) XX curcol =  curcol, maxrow, curcol + arg - 1); XX} XX XXerase_area(sr, sc, er, ec) XXint sr, sc, er, ec; XX{ XX register int r, c; XX register struct ent **p; XX XX if (sr > er) { XX r = sr; sr = er; er= r; XX } XX XX if (sc > ec) { XX c = sc; sc = ec; ec= c; XX } XX XX if (sr < 0) XX sr = 0; XX if (sc < 0) XX sc = 0; XX if (er >= MAXROWS) XX er = MAXROWS-1; XX if (ec >= MAXCOLS) XX ec = MAXCOLS-1; XX XX for (r = sr; r <= er; r++) { XX for (c = sc; c <= ec; c++) { XX p = &tbl[r][c]; XX if (*p) { XX free_ent(*p); XX *p = 0; XX } XX } XX } XX XX} XX XXvalueize_area(sr, sc, er, ec) XXint sr, sc, er, ec; XX{ XX register int r, c; XX register struct ent *p; XX XX if (sr > er) { XX r = sr; sr = er; er= r; XX } XX XX if (sc > ec) { XX c = sc; sc = ec; ec= c; XX } XX XX if (sr < 0) XX sr = 0; XX if (sc < 0) XX sc = 0; XX if (er >= MAXROWS) XX er = MAXROWS-1; XX if (ec >= MAXCOLS) XX ec = MAXCOLS-1; XX XX for (r = sr; r <= er; r++) { XX for  XX{ XX register int i,j; XX for (i=0; iexpr) { XX efree(p->expr); XX p->expr = 0; XX } XX } XX } XX XX} XX XXpullcells(to_insert) XX{ XX register struct ent *p, *n; XX register int deltar, deltac; XX int minrow, mincol; XX int maxrow, maxcol; XX int numrows, numcols; XX XX if (!to_fix) XX return; XX XX switch (to_insert) { XX case 'm': XX case 'r': XX case 'c': XX break; XX default: XX return; XX } XX XX minrow = MAXROWS; XX minc XX } XX j--; XX if (inext) { XX if (p->row < minrow) XX minrow = p->row; XX if (p->row > maxrow) XX maxrow = p->row; XX if (p->col < mincol) XX mincol = p->col; XX if (p->col > maxcol) XX maxcol = p->col; XX } XX XX numrows = maxrow - minrow + 1; XX numcols = maxcol - mincol + 1; XX deltar = currow - minrow; XX deltac = curcol - mincol; XX XX if (to_insert == 'r') { XX insertrow(numrows); XX deltac = 0; XX  register r; XX register struct ent **p; XX register c; XX register i; XX XX if (rs > maxrow) maxrow = rs; XX if (maxrow >= MAXROWS - 1 || rs > MAXROWS - 1) { XX error ("The table can't be any longer"); XX return; XX } XX for (i = maxrow+1; i > rs; i--) { XX hidden_row[i] = hidden_row[i-1]; XX } XX for (r = ++maxrow; r > rs; r--) XX for (c = maxcol + 1, p = &tbl[r][0]; --c >= 0; p++) XX if (p[0] = p[-MAXCOLS]) XX p[0] -> row++; XX p = &tbl[rs][0]; XX for (c = max} else if (to_insert == 'c') { XX insertcol(numcols); XX deltar = 0; XX } XX XX FullUpdate++; XX modflg++; XX XX for (p = to_fix; p; p = p->next) { XX n = lookat (p->row + deltar, p->col + deltac); XX clearent(n); XX n -> flags = p -> flags & ~is_deleted; XX n -> v = p -> v; XX n -> expr = copye(p->expr, deltar, deltac); XX n -> label = 0; XX if (p -> label) { XX n -> label = (char *) XX malloc(strlen(p->label)+1); XX strcpy (n -> label, p -> label); XX } XX } XX} XX XXshowcol_op()col + 1; --c >= 0;) XX *p++ = 0; XX FullUpdate++; XX modflg++; XX} XX XXcloserow (r) XXregister r; { XX register struct ent **p; XX register c; XX register int i; XX XX if (r > maxrow) return; XX XX p = &tbl[r][0]; XX for (c=maxcol+1; --c>=0; ) { XX if (*p) XX free_ent(*p); XX *p++ = 0; XX } XX XX for (i = r; i < MAXROWS - 1; i++) { XX hidden_row[i] = hidden_row[i+1]; XX } XX XX while (r=0; p++) XX if (p[0] = p[MAXCOLS]) XX p[0]->row--; XX r++; XX } XX XX p = &tbl[maxrow][0]; XX for (c=maxcol+1; --c>=0; ) *p++ = 0; XX maxrow--; XX FullUpdate++; XX modflg++; XX} XX XXopencol (cs) { XX register r; XX register struct ent **p; XX register c; XX register lim = maxcol-cs+1; XX int i; XX XX if (cs > maxcol) maxcol = cs; XX if (maxcol >= MAXCOLS - 1 || cs > MAXCOLS - 1) { XX error ("The table can't be any wider"); XX return; XX } XX for (i = maxcol+1; i > cs; i--) { XX fwidth[sdef.h> XX#include XX#include XX#include XX XX#define NIBUF 128 /* Input buffer size */ XX#define NOBUF 1024 /* MM says bug buffers win! */ XX#define EFN 0 /* Event flag */ XX XXchar obuf[NOBUF]; /* Output buffer */ XXint nobuf; /* # of bytes in above */ XXchar ibuf[NIBUF]; /* Input buffer */ XXint nibuf; /* # of bytes in above */ XXint ibufi; /* Read index */ XXint oldmode[2]; /* Old TTY mode bits */ XXint newmode[2]; /* New TTY mode bits */ XXshort ioi] = fwidth[i-1]; XX precision[i] = precision[i-1]; XX hidden_col[i] = hidden_col[i-1]; XX } XX /* fwidth[cs] = DEFWIDTH; XX precision[i] = DEFPREC; */ XX XX for (r=0; r<=maxrow; r++) { XX p = &tbl[r][maxcol+1]; XX for (c=lim; --c>=0; p--) XX if (p[0] = p[-1]) XX p[0]->col++; XX p[0] = 0; XX } XX maxcol++; XX FullUpdate++; XX modflg++; XX} XX XXclosecol (cs) { XX register r; XX register struct ent **p; XX register struct ent *q; XX register c; XX register lim = chan; /* TTY I/O channel */ XXstruct dsc$descriptor idsc; XXstruct dsc$descriptor odsc; XXchar oname[40]; XXint iosb[2]; XXint term[2]; XXint status; XX#endif XX XX#ifdef MCH_AMIGA XXextern char *Open(); XXextern long Read(),Write(); XXextern void Close(); XX#define NEW 1006L XX#define AMG_MAXBUF 1024 XXstatic char *terminal = 0L; XXstatic char scrn_tmp[AMG_MAXBUF+1]; XXstatic long scrn_tmp_p = 0L; XX#endif XX XX#ifdef U__X XX#include XX#include XX#include XXstrumaxcol-cs; XX int i; XX XX if (lim < 0) return; XX XX for (r=0; r<=maxrow; r++) XX if (q = tbl[r][cs]) { XX free_ent(q); XX } XX XX for (r=0; r<=maxrow; r++) { XX p = &tbl[r][cs]; XX for (c=lim; --c>=0; p++) XX if (p[0] = p[1]) XX p[0]->col--; XX p[0] = 0; XX } XX XX for (i = cs; i < MAXCOLS - 1; i++) { XX fwidth[i] = fwidth[i+1]; XX precision[i] = precision[i+1]; XX hidden_col[i] = hidden_col[i+1]; XX } XX XX maxcol--; XX FullUpdate++; XX modflg++; XX} XX SHAR_EOF if ct sgttyb old_tty,new_tty; XX#endif XX XX#ifdef MCH_AMIGA XX#define COLS 79 XX#define ROWS 23 XX#else XX#define COLS 80 XX#define ROWS 24 XX#endif XX XX#define NORMAL 0x00 XX#define BOLD 0x80 XX XXchar nscrn[ROWS][COLS], XX cscrn[ROWS][COLS], XX row, XX col, XX mode; XXchar str[256]; XX XXmove(y,x) XXint y,x; XX { XX row = y; XX col = x; XX } XX XXclrtoeol() { XX int i; XX XX for (i = col; i < COLS; i++) nscrn[row][i] = ' ' | mode; XX } XX XXprintw(fmt,a1,a2,a3,a4,a5) XXchar *fmt,*a1,*atest 8004 -ne "`wc -c cmds.c`" then echo shar: error transmitting cmds.c '(should have been 8004 characters)' fi echo shar: extracting curses.c sed 's/^XX//' << \SHAR_EOF > curses.c XX/********************************************************************** XX * XX * Tiny pseudo "curses" package (runs on U__X, VMS, or MCH_AMIGA) XX * XX * v1.0 870117 DBW - D. Wecker, initial hack XX * XX **********************************************************************/ XX XX#ifdef VMS XX#include XX#include = nibuf) { XX ibufi = 0; XX term[0] = 0; XX term[1] = 0; XX status = SYS$QIOW(EFN, iochan, IO$_READLBLK|IO$M_TIMED, XX iosb, 0, 0, ibuf, NIBUF, 0, term, 0, 0); XX if (status != SS$_NORMAL) exit(status); XX status = iosb[0] & 0xFFFF; XX if (status!=SS$_NORMAL && status!=SS$_TIMEOUT) exit(status); XX nibuf = (iosb[0]>>16) + (iosb[1]>>16); XX if (nibuf == 0) { XX status = SYS$QIOW(EFN, iochan, IO$_READLBLK, XX iosb, 0, 0, ibuf, 1, 0, term, 0, 0); XX if (status != SS$_NORMAL || (status = (iosb[0]&0xFFFF)) != SS$_NORMAL) XX exit(status); XX nibuf = (iosb[0]>>16) + (iosb[1]>>16); XX } XX } XX return (ibuf[ibufi++] & 0x7F); XX#endif XX XX#ifdef U__X XX return(getchar() & 0x7F); XX#endif XX } XX XXttputc(c) XX#ifdef MCH_AMIGA XXchar c; XX#endif XX { XX#ifdef MCH_AMIGA XX scrn_tmp[scrn_tmp_p++] = c; XX if(scrn_tmp_p>=AMG_MAXBUF) amg_flush(); XX#endif XX XX#ifdef VMS XX if ndif XX XX#define MAXROWS 200 XX#define MAXCOLS 40 XX XXstruct ent { XX double v; XX char *label; XX struct enode *expr; XX short flags; XX short row, col; XX struct ent *next; XX}; XX XX XXstruct enode { XX int op; XX union { XX double k; XX struct ent *v; XX struct { XX struct enode *left, *right; XX } o; XX } e; XX}; XX XX/* op values */ XX#define O_VAR 'v' XX#define O_CONST 'k' XX#define O_REDUCE(c) (c+0200) XX XX/* flag values */ XX#define is_valid 0001 XX#define is_c(nobuf >= NOBUF) ttflush(); XX obuf[nobuf++] = c; XX#endif XX XX#ifdef U__X XX fputc(c, stdout); XX#endif XX } XX XX#ifdef MCH_AMIGA XXamg_flush() XX { XX if(scrn_tmp_p) Write(terminal,scrn_tmp,(long)scrn_tmp_p); XX scrn_tmp_p = 0; XX } XX#endif XX XXttputs(s) XXchar *s; XX { XX while (*s) ttputc(*s++); XX } XX XXttflush() XX { XX#ifdef MCH_AMIGA XX amg_flush(); XX#endif XX XX#ifdef VMS XX status = SS$_NORMAL; XX if (nobuf != 0) { XX status = SYS$QIOW(EFN, iochan, Ihanged 0002 XX#define is_lchanged 0004 XX#define is_leftflush 0010 XX#define is_deleted 0020 XX XX#define ctl(c) ('c'&037) XX XXstruct ent *tbl[MAXROWS][MAXCOLS]; XX XXint strow, stcol; XXint currow, curcol; XXint savedrow, savedcol; XXint FullUpdate; XXint maxrow, maxcol; XXint fwidth[MAXCOLS]; XXint precision[MAXCOLS]; XXchar hidden_col[MAXCOLS]; XXchar hidden_row[MAXROWS]; XXchar line[1000]; XXint linelim; XXint changed; XXstruct ent *to_fix; XXstruct enode *new(); XXstruct ent *lookat(); XXstruct eO$_WRITELBLK|IO$M_NOFORMAT, XX iosb, 0, 0, obuf, nobuf, 0, 0, 0, 0); XX if (status == SS$_NORMAL) status = iosb[0] & 0xFFFF; XX nobuf = 0; XX } XX return (status); XX#endif XX XX#ifdef U__X XX fflush(stdout); XX#endif XX } XX SHAR_EOF if test 7037 -ne "`wc -c curses.c`" then echo shar: error transmitting curses.c '(should have been 7037 characters)' fi echo shar: extracting experres.h sed 's/^XX//' << \SHAR_EOF > experres.h XX "FIXED", K_FIXED, XX "SUM", K_SUM, XX "PROD", K_PROD, XX "AVE", K_AVE, Snode *copye(); XXchar *coltoa(); XX XXint modflg; SHAR_EOF if test 1241 -ne "`wc -c sc.h`" then echo shar: error transmitting sc.h '(should have been 1241 characters)' fi echo shar: extracting statres.h sed 's/^XX//' << \SHAR_EOF > statres.h XX "FORMAT", S_FORMAT, XX "LABEL", S_LABEL, XX "LEFTSTRING", S_LEFTSTRING, XX "RIGHTSTRING", S_RIGHTSTRING, XX "GET", S_GET, XX "PUT", S_PUT, XX "MERGE", S_MERGE, XX "LET", S_LET, XX "WRITE", S_WRITE, XX "TBL", S_TBL, XX "PROGLET", S_PROGLET, XX "COPY", S_COPY, XX "SHOWHAR_EOF if test 66 -ne "`wc -c experres.h`" then echo shar: error transmitting experres.h '(should have been 66 characters)' fi echo shar: extracting sc.h sed 's/^XX//' << \SHAR_EOF > sc.h XX/* VC A Table Calculator XX * Common definitions XX * XX * original by James Gosling, September 1982 XX * modified by Mark Weiser and Bruce Israel, XX * University of Maryland XX * XX */ XX XX#include XX XX#ifdef MCH_AMIGA XX#define ROWS 23 XX#define COLS 79 XX#else XX#define ROWS 24 XX#define COLS 80 XX#e", S_SHOW, SHAR_EOF if test 255 -ne "`wc -c statres.h`" then echo shar: error transmitting statres.h '(should have been 255 characters)' fi echo shar: extracting y.tab.h sed 's/^XX//' << \SHAR_EOF > y.tab.h XX XXtypedef union { XX int ival; XX double fval; XX struct ent *ent; XX struct enode *enode; XX char *sval; XX} YYSTYPE; XXextern YYSTYPE yylval; XX# define STRING 257 XX# define NUMBER 258 XX# define FNUMBER 259 XX# define WORD 260 XX# define COL 261 XX# define S_FORMAT 262 XX# define S_LABEL 263 XX# define S_LEFTSTRING 264 XX# define S_RIGHTSTRING 265 XX# define S_GET 266 XX# define S_PUT 267 XX# define S_MERGE 268 XX# define S_LET 269 XX# define S_WRITE 270 XX# define S_TBL 271 XX# define S_PROGLET 272 XX# define S_COPY 273 XX# define S_SHOW 274 XX# define K_FIXED 275 XX# define K_SUM 276 XX# define K_PROD 277 XX# define K_AVE 278 SHAR_EOF if test 597 -ne "`wc -c y.tab.h`" then echo shar: error transmitting y.tab.h '(should have been 597 characters)' fi # End of shell archive exit 0 Ff Software Innovations. Sc is not a product it is free... (You get the picture.) -- Robert Bond ihnp4!nsc!nscpdc!rgb National Semiconductor tektronix!nscpdc!rgb struct ent *next; XX}; XX XX XXstruct enode { XX int op; XX union { XX double k; XX struct ent *v; XX struct { XX struct enode *left, *right; XX } o; XX } e; XX}; XX XX/* op values */ XX#define O_VAR 'v' XX#define O_CONST 'k' XX#define O_REDUCE(c) (c+0200) XX XX/* flag values */ XX#define is_valid 0001 XX#define is_crom tektronix!reed!nscpdc!rgb Mon Jan 19 13:40:30 PST 1987 Article 4251 of net.sources: Path: tekcrl!tektronix!reed!nscpdc!rgb >From: rgb@nscpdc.NSC.COM (Robert Bond) Newsgroups: net.sources Subject: Forthcoming sc (was vc) update Message-ID: <818@nscpdc.NSC.COM> Date: 18 Jan 87 23:51:59 GMT Reply-To: rgb@nscpdc.UUCP (Robert Bond) Organization: NSC Portland, Oregon Lines: 35 I will refer to the program posted as vc as sc from now on. I have received lots of mail from helpful folks who had fixes and prob   sc.1bond "- ʀ ʔ ʜ-- ʘZd ʘ  C1"lems and I intend to post a better version as soon as I get back from Uniform next week. Corrections include: 1) Much linting for those who reported coredumps. This version should be more portable. 2) The @avg bug is fixed. 3) I added a "^" command to go to row 0 4) Trig and other math functions added. 5) Assorted bug fixes and cleanup. 6) Use crmode() instead of raw() for BSD. 7) Better precision is maintained in the save files. I have also changed the makefile so it defaults to sc, but will make an#!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # README # sc.man # sc.doc # cmds.c # eres.sed # sres.sed # makefile # cvt.sed # This archive created: Mon Jan 26 19:36:29 1987 # By: Robert Bond (NSC Portland, Oregon) echo shar: extracting README '(2477 characters)' cat << \SHAR_EOF > README This is a much modified version of the public domain spread sheet vc, posted a year or two ago by Mark Weiser, orginally by James Gosling. Changes since my last version: 1) Much lintind install under any name you want. I have heard of at least five different names, so I thought I would make it easy. Please hold off on posting new versions and bug fixes till you see this one. If you send them to me I will try to include worthwhile mods. If you are at Uniform and want to talk about sc, please come find me. The folks at the National Semiconductor booth will know how to get in touch with me. Bob Bond Disclamer: Sc is not a product of National Semiconductor. Sc is not a product og for those who reported coredumps. This version should be more portable. On our 4.3 system, lint only complains about some functions whose values are always ignored. On the 5.2 system it also complains about some hidden variables. This is normal. Yacc will complain about 14 shift reduce conflicts. This is also normal. 2) The @avg bugs are fixed. 3) I added a "^" command to go to row 0 4) Trig and other math functions added. 5) Assorted bug fixes and cleanup. 6) Use crmode() instead of raw() for BSD 7) A couple of new region commands (erase and fill) 8) More cursor movement commands (goto and #) 9) All function names are unique within the first 7 characters. 10) More precision is retained in the saved files. Due to some trademark name problems, I have changed the name back to Gosling's original, sc. I have modified the makefile to make it easy for you to call it what you want (I saw at least five different names in correspondence and on the net). Just change "name=sc" to "name=myfavoritenSC(1) NAME sc - spread sheet calculator SYNOPSIS sc [ _f_i_l_e ] DESCRIPTION The spread sheet calculator _s_c is based on rectangular tables, in much the same style as Visicalc or Lotus 123. When it is invoked it presents you with an empty table organized as rows and columns of cells. Each cell may have a label string associated with it and an expression. The expression may be a constant or it may coame" and try "make myfavoritename". Similarly, you can make the documentation with "make myfavoritename.man". "make install" will make and install the code in EXDIR. The installation steps and documentation all key off of the name. The makefile even changes the name in the nroffable man page. If you don't have nroff, you will have to change sc.man yourself. The code has been tested against a Vax running 4.2 and 4.3 and a National ICM-3216 with system V.2. The ICM has a National Semi 32016. Just checkmpute something based on other entries. When _s_c is running, the screen is divided into four regions. The top line is for entering commands. The second line is for messages from _s_c. The third line and the first four columns show the row and column numbers. The rest of the screen forms a window looking at the table. The screen has two cursors: a cell cursor (indicated by a '<' on the screen) and a character cursor (ind the makefile for the system flags. I have heard reports of lots of other machines which work. I have added ifdefs for system III and for Berkely 4.3. If you have problems with lex.c, and don't care about arrow keys, define SIMPLE (-DSIMPLE in the makefile). SIMPLE causes the arrow keys to not be used. Many thanks to all of the kind souls who wrote with fixes and bug reports. In particular, my "beta" testers, Kim Rochat and Dave Shanks, and to Eric Goldman for the floating point stuff. Disclaimer: Sicated by the terminal's hardware cursor). The cell and character cursors are often the same. They will differ when a command is being typed on the top line. Commands which use the terminal's control key such as ^N will work both when a command is being typed and when in normal mode. The cursor control commands and the row, column commands can be prefixed by a numeric argument indicating how many times the command c is not a product of National Semiconductor. It is supplied as is with no warrenty, express or implied, as a service to Usenet readers. Bob Bond Robert Bond ihnp4!nsc!nscpdc!rgb National Semiconductor tektronix!nscpdc!rgb SHAR_EOF if test 2477 -ne "`wc -c README`" then echo shar: error transmitting README '(should have been 2477 characters)' fi echo shar: extracting sc.man '(15996 characters)' cat << \SHAR_EOF > sc.man SC(1) UNIX 3.0 is to be executed. "^U" can be used before the number if the number is to be entered while a command is being typed into the command line. Cursor control commands: ^N Move the cell cursor to the next row. ^P Move the cell cursor to the previous row. ^F Move the cell cursor forward one column. ^B Move the cell cursor backward one column. Page 1 (printed 1/26/87)  SC(1) UNIX 3.0 SC(1) ^H Backspace one character. h, j, k, l Alternate cursor controls (left, down, up, right). Arrow Keys The terminal's arrow keys provide another alternate set of cell cursor controls if they exist and are supported in the _t_e_r_m_c_a_p entry. Some terminals have arrow keys which conflict with other control key codes. Foris command with a count of the number of cells on the current row to clear. Cells cleared with this command may be recalled with any of the variations of the pull command. e Edit the value associated with the current cell. This is identical to '=' except that the command line starts out containing the old value or expression associated with the cell. E Edit the string asso example, a terminal could send ^H when the back arrow key is depressed. In these cases, the conflicting arrow key performs the same function as the key combination it mimics. 0 Move the cell cursor to column 0 of the current row. $ Move the cell cursor to the last valid column in the current row. ^ Move the cell cursor to row 0 of the current column. # Move the cell cursorciated with the current cell. This is the same as either "leftstring", "rightstring", or "label", with the additional fact that the command line starts out with the old string. m Mark a cell to be used as the source for the copy command. c Copy the last marked cell to the current cell, updating the row and column references. ^T Toggle cell display. The current cell's contents are  to the last valid row in the current column. g Go to a cell. The program will prompt for the name of a cell. Enter a cell number such as "a0" or "ae122". Cell entry and editing commands: = Prompts for an expression which will be evaluated dynamically to produce a value for the cell pointed at by the cell cursor. This may be used in conjunction with ^V to make one entries value be dependen displayed in line one when no command being entered or edited. ^T turns the display on or off. File operations G Get a new database from a file. P Put the current database into a file. W Write a listing of the current database in a form that matches its appearance on the screen. This differs from the "put" command in that "put"s files are intended to be reloaded with "get", while "wrt on anothers. " Enter a label for the current cell. < Enter a label that will be flushed left against the left edge of the cell. Page 2 (printed 1/26/87) SC(1) UNIX 3.0 SC(1) > Enter a label that will be flushed right against the right edge of the cell. x Clears the current cell. You may prefix thite" produces a file for people to look at. Page 3 (printed 1/26/87) SC(1) UNIX 3.0 SC(1) T Write a listing of the current database to a file, but put ":"s between each field. This is useful for tables that will be further formatted by the _t_b_l preprocessor of _n_r_o_f_f. M Merges the database from the named file into the current database. Values, expressions and names defined in the named file are written into the current file, overwriting the existing entries at those locations. Row and Column operations. Members of this class of commands can be used on either rows or columns. The second letter of the command is either a column designator (one of the characters c, j, k, ^N, ^p) or a row designator  Removes expressions from the affected rows (columns), leaving only the values which were in the cells before the command was executed. sr, sc Show hidden rows (columns). Type in a range of rows or columns to be revealed. The command default is the first range of rows or columns currently hidden. f Sets the output format to be used for printing the numbers in each cell in the(one of r, l, h, ^B, ^F). Commands which move or copy cells also modify the variable references in affected cell expressions. Variable references may be frozen by using the "fixed" operator. ar, ac Creates a new row (column) immediately following the current row (column). It is initialized to be a copy of the current one. dr, dc Delete this row (column). pr, pc, pm  current column. Type in two numbers which will be the width in characters of a column and the number of digits which will follow the decimal point. Note that this command has only a column version and does have a second letter. Region Operations: Region commands affect a rectangular region on the screen. All of the commands in this class start with a slash; the second letter of the command indicates whic Pull deleted rows (columns) back into the spread sheet. The last deleted set of cells is put back into the spread sheet at the current location. _P_r inserts enough rows to hold the data. _P_c inserts enough columns to hold the data. _P_m (merge) does not insert rows or columns. It overwrites the cells beginning at the current cursor location. ir, ic Insert a new row (columnh command to do. The program will prompt for needed paramters. Phrases surrounded by square brackets in the prompt are informational only and may be erased with the backspace key. /x Clear a region. Cells cleared with this command may be recalled via any of the pull row or column commands. /c Copy a region to the area starting at the current cell. /f Fill a region with constant values. The start and inc) by moving the row (column) containing the cell cursor, and all following, down (right) one. The new position will be empty. zr, zc Hide ("zap") the current row (column). This keeps a row or column from being displayed but keeps it in the Page 4 (printed 1/26/87) SC(1) UNIX 3.0 SC(1) data base. vr, vcrement numbers may be positive or negative. Miscellaneous commands: q Exit from _s_c. If you were editing a file, and you modified it, then _s_c will ask about saving before exiting. If you aren't editing a file and haven't saved the data you entered, you will get a chance to save the data before you exit. Page 5 (printed 1/26/87) SC(1)  UNIX 3.0 SC(1) ^C Alternate exit command. ? Types a brief helpful message. ^G or ESC Abort entry of the current command. ^R or ^L Redraw the screen. ^V Types, in the command line, the name of the cell referenced by the cell cursor. This is used when typing in expressions which refer to entries in the table. ^E Types, in the comll valid (nonblank) entries in the region whose two corners are defined by the two variable (cell) names given. e?e:e Conditional: If the first expression is true then the value of the second is returned, otherwise the value of the third is. <,=,>,<=,>= Relationals: true iff the indicated relation holds. &,| mand line, the expression of the cell referenced by the cell cursor. ^A Types, in the command line, the value of the cell referenced by the cell cursor. Expressions that are used with the '=' and 'e' commands have a fairly conventional syntax. Terms may be variable names (from the ^V command), parenthesised expressions, negated terms, and constants. Rectangular regions of the screen may be operated upon with '@' Boolean connectives. fixed To make a variable not change automatically when a cell moves, put the word fixed in front of the reference. I.e. B1*fixed C3 Assorted math functions. Most of these are standard system functions more fully described in _m_a_t_h(_3). All of them operate on floating point numbers (doubles); the trig functions operate with angles in radians. @exp functions such as sum (@sum), average (@avg) and product (@prod). Terms may be combined using many binary operators. Their precedences (from highest to lowest) are: ^; *,/; +,-; <,=,>,<=,>=; &; |; ?. e+e Addition. e-e Subtraction. e*e Multiplication. e/e Division. e^e Exponentiation. Page 6 (printed 1/26/87) (expr) Returns exponential function of . @ln(expr) Returns the natural logarithm of . @log(expr) Returns the base 10 logarithm of . @pow(expr1,expr2) Returns raised to the power of . Page 7 (printed 1/26/87) SC(1) UNIX 3.0 SC(1) @floor(expr) Returns returns t SC(1) UNIX 3.0 SC(1) @sum(v:v) Sum all valid (nonblank) entries in the region whose two corners are defined by the two variable (cell) names given. @avg(v:v) Average all valid (nonblank) entries in the region whose two corners are defined by the two variable (cell) names given. @prod(v:v) Multiply together ahe largest integer not greater than . @ceil(expr) Returns the smallest integer not less than . @hypot(x,y) Returns SQRT(x*x+y*y), taking precautions against unwarranted overflows. @fabs(expr) Returns the absolute value |expr|. @sin(expr), @cos(expr), @tan(expr) Return trigonometric functions of radian arguments. The magnitude of the arguments are not checked to assure meaningful results. @asin(expr) Returns the arc sin in the range -pi/2 to pi/2 @acos(expr) Returns the arc cosine in the range 0 to pi. @atan(expr) Returns the arc tangent of in the range -pi/2 to pi/2. @dtr(expr) Converts in degrees to radians. @rtd(expr) Converts in radians to degreeou with an empty table organized as rows and columns of cells. Each cell may have a label string associated with it and an expression. The expression may be a constant or it may compute something based on other entries. When \fIpname\fR is running, the screen is divided into four regions. The top line is for entering commands. The second line is for messages from \fIpname\fR. The third line and the first four columns show the row and column numbers. The rest of the screen forms a window looking at the tas. pi A constant quite close to pi. @max(expr1,expr2) Returns the largest value of the two expressions. @min(expr1,expr2) Returns the smallest value of the two expressions. @gamma(expr1) Returns the natural log of the gamma Page 8 (printed 1/26/87) SC(1) UNIX 3.0 ble. The screen has two cursors: a cell cursor (indicated by a '<' on the screen) and a character cursor (indicated by the terminal's hardware cursor). The cell and character cursors are often the same. They will differ when a command is being typed on the top line. Commands which use the terminal's control key such as ^N will work both when a command is being typed and when in normal mode. The cursor control commands and the row, column commands can be prefixed by a numeric argument indicating how man SC(1) function. SEE ALSO bc(1), dc(1) BUGS Expression reevaluation is done in the same top-to-bottom, left-to-right manner as is done in other spread sheet calculators. This is silly. A proper following of the dependency graph with (perhaps) recourse to relaxation should be implemented. At most 200 rows and 40 columns. Page 9 y times the command is to be executed. "^U" can be used before the number if the number is to be entered while a command is being typed into the command line. Cursor control commands: .IP ^N Move the cell cursor to the next row. .IP ^P Move the cell cursor to the previous row. .IP ^F Move the cell cursor forward one column. .IP ^B Move the cell cursor backward one column. .IP ^H Backspace one character. .IP "h, j, k, l" Alternate cursor controls (left, down, up, right). .IP "Arrow Keys" The termina (printed 1/26/87) SHAR_EOF if test 15996 -ne "`wc -c sc.man`" then echo shar: error transmitting sc.man '(should have been 15996 characters)' fi echo shar: extracting sc.doc '(11360 characters)' cat << \SHAR_EOF > sc.doc .TH SC 1 .SH NAME pname \- spread sheet calculator .SH SYNOPSIS .B pname [ .I file ] .SH DESCRIPTION The spread sheet calculator .I pname is based on rectangular tables, in much the same style as Visicalc or Lotus 123. When it is invoked it presents yl's arrow keys provide another alternate set of cell cursor controls if they exist and are supported in the .I termcap entry. Some terminals have arrow keys which conflict with other control key codes. For example, a terminal could send ^H when the back arrow key is depressed. In these cases, the conflicting arrow key performs the same function as the key combination it mimics. .IP 0 Move the cell cursor to column 0 of the current row. .IP $ Move the cell cursor to the last valid column in the current row. .IP ^ Move the cell cursor to row 0 of the current column. .IP # Move the cell cursor to the last valid row in the current column. .IP g Go to a cell. The program will prompt for the name of a cell. Enter a cell number such as "a0" or "ae122". .PP Cell entry and editing commands: .IP = Prompts for an expression which will be evaluated dynamically to produce a value for the cell pointed at by the cell cursor. This may be used in conjunction with ^V to make one entries value be dependent on anotheurrent database to a file, but put ":"s between each field. This is useful for tables that will be further formatted by the .I tbl preprocessor of .I nroff. .IP M Merges the database from the named file into the current database. Values, expressions and names defined in the named file are written into the current file, overwriting the existing entries at those locations. .PP Row and Column operations. Members of this class of commands can be used on either rows or columns. The second letter of the cors. .IP """ Enter a label for the current cell. .IP < Enter a label that will be flushed left against the left edge of the cell. .IP > Enter a label that will be flushed right against the right edge of the cell. .IP x Clears the current cell. You may prefix this command with a count of the number of cells on the current row to clear. Cells cleared with this command may be recalled with any of the variations of the pull command. .IP e Edit the value associated with the current cell. This is identicalmmand is either a column designator (one of the characters c, j, k, ^N, ^p) or a row designator (one of r, l, h, ^B, ^F). Commands which move or copy cells also modify the variable references in affected cell expressions. Variable references may be frozen by using the "fixed" operator. .IP "ar, ac" Creates a new row (column) immediately following the current row (column). It is initialized to be a copy of the current one. .IP "dr, dc" Delete this row (column). .IP "pr, pc, pm" Pull deleted rows (column to '=' except that the command line starts out containing the old value or expression associated with the cell. .IP E Edit the string associated with the current cell. This is the same as either "leftstring", "rightstring", or "label", with the additional fact that the command line starts out with the old string. .IP m Mark a cell to be used as the source for the copy command. .IP c Copy the last marked cell to the current cell, updating the row and column references. .IP ^T Toggle cell display. Thes) back into the spread sheet. The last deleted set of cells is put back into the spread sheet at the current location. .I Pr inserts enough rows to hold the data. .I Pc inserts enough columns to hold the data. .I Pm (merge) does not insert rows or columns. It overwrites the cells beginning at the current cursor location. .IP "ir, ic" Insert a new row (column) by moving the row (column) containing the cell cursor, and all following, down (right) one. The new position will be empty. .IP "zr, zc" Hide ("z current cell's contents are displayed in line one when no command being entered or edited. ^T turns the display on or off. .PP File operations .IP G Get a new database from a file. .IP P Put the current database into a file. .IP W Write a listing of the current database in a form that matches its appearance on the screen. This differs from the "put" command in that "put"s files are intended to be reloaded with "get", while "write" produces a file for people to look at. .IP T Write a listing of the cap") the current row (column). This keeps a row or column from being displayed but keeps it in the data base. .IP "vr, vc" Removes expressions from the affected rows (columns), leaving only the values which were in the cells before the command was executed. .IP "sr, sc" Show hidden rows (columns). Type in a range of rows or columns to be revealed. The command default is the first range of rows or columns currently hidden. .IP f Sets the output format to be used for printing the numbers in each cell in the current column. Type in two numbers which will be the width in characters of a column and the number of digits which will follow the decimal point. Note that this command has only a column version and does have a second letter. .PP Region Operations: Region commands affect a rectangular region on the screen. All of the commands in this class start with a slash; the second letter of the command indicates which command to do. The program will prompt for needed paramters. Phrases surrounded by squared using many binary operators. Their precedences (from highest to lowest) are: ^; *,/; +,-; <,=,>,<=,>=; &; |; ?. .TP 15 e+e Addition. .TP 15 e-e Subtraction. .TP 15 e*e Multiplication. .TP 15 e/e Division. .TP 15 e^e Exponentiation. .TP 15 @sum(v:v) Sum all valid (nonblank) entries in the region whose two corners are defined by the two variable (cell) names given. .TP 15 @avg(v:v) Average all valid (nonblank) entries in the region whose two corners are defined by the two variable (cell) names givee brackets in the prompt are informational only and may be erased with the backspace key. .IP "/x" Clear a region. Cells cleared with this command may be recalled via any of the pull row or column commands. .IP "/c" Copy a region to the area starting at the current cell. .IP "/f" Fill a region with constant values. The start and increment numbers may be positive or negative. .PP Miscellaneous commands: .IP q Exit from \fIpname\fR. If you were editing a file, and you modified it, then \fIpname\fR win. .TP 15 @prod(v:v) Multiply together all valid (nonblank) entries in the region whose two corners are defined by the two variable (cell) names given. .TP 15 e?e:e Conditional: If the first expression is true then the value of the second is returned, otherwise the value of the third is. .TP 15 <,=,>,<=,>= Relationals: true iff the indicated relation holds. .TP 15 &,| Boolean connectives. .TP 15 fixed To make a variable not change automatically when a cell moves, put the word \*(lqfixed\*(rq in front oll ask about saving before exiting. If you aren't editing a file and haven't saved the data you entered, you will get a chance to save the data before you exit. .IP ^C Alternate exit command. .IP ? Types a brief helpful message. .IP "^G or ESC" Abort entry of the current command. .IP "^R or ^L" Redraw the screen. .IP ^V Types, in the command line, the name of the cell referenced by the cell cursor. This is used when typing in expressions which refer to entries in the table. .IP ^E Types, in the commf the reference. I.e. B1*fixed C3 .PP Assorted math functions. Most of these are standard system functions more fully described in .I math(3). All of them operate on floating point numbers (doubles); the trig functions operate with angles in radians. .TP 15 @exp(expr) Returns exponential function of . .TP 15 @ln(expr) Returns the natural logarithm of . .TP 15 @log(expr) Returns the base 10 logarithm of . .TP 15 @pow(expr1,expr2) Returns raised to the power of . .TP 1and line, the expression of the cell referenced by the cell cursor. .IP ^A Types, in the command line, the value of the cell referenced by the cell cursor. .PP Expressions that are used with the '=' and 'e' commands have a fairly conventional syntax. Terms may be variable names (from the ^V command), parenthesised expressions, negated terms, and constants. Rectangular regions of the screen may be operated upon with '@' functions such as sum (@sum), average (@avg) and product (@prod). Terms may be combin5 @floor(expr) Returns returns the largest integer not greater than . .TP 15 @ceil(expr) Returns the smallest integer not less than . .TP 15 @hypot(x,y) Returns SQRT(x*x+y*y), taking precautions against unwarranted overflows. .TP 15 @fabs(expr) Returns the absolute value |expr|. .TP 15 @sin(expr), @cos(expr), @tan(expr) Return trigonometric functions of radian arguments. The magnitude of the arguments are not checked to assure meaningful results. .TP 15 @asin(expr) Returns the arc sin in the range -pi/2 to pi/2 .TP 15 @acos(expr) Returns the arc cosine in the range 0 to pi. .TP 15 @atan(expr) Returns the arc tangent of in the range -pi/2 to pi/2. .TP 15 @dtr(expr) Converts in degrees to radians. .TP 15 @rtd(expr) Converts in radians to degrees. .TP 15 pi A constant quite close to pi. .TP 15 @max(expr1,expr2) Returns the largest value of the two expressions. .TP 15 @min(expr1,expr2) Returns the smallest value of the two expressions. .TP 15 @gamma(expr1) Returns the 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  natural log of the gamma function. .SH SEE ALSO bc(1), dc(1) .SH BUGS Expression reevaluation is done in the same top-to-bottom, left-to-right manner as is done in other spread sheet calculators. This is silly. A proper following of the dependency graph with (perhaps) recourse to relaxation should be implemented. At most 200 rows and 40 columns. SHAR_EOF if test 11360 -ne "`wc -c sc.doc`" then echo shar: error transmitting sc.doc '(should have been 11360 characters)' fi echo shar: extracting cmds.c '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 = malloc ((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)(8071 characters)' cat << \SHAR_EOF > cmds.c /* 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 #include "sc.h" #ifdef BSD42 #include #else #ifndef SYSIII #include #endif #endif char *malloc(); duprow() { if (currow >= MAXROWS - 1 || maxrow >= MAXROWS - 1) { error ("The table can' { 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, maxt 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 = malloc ((unsigned)(strlen (p -> label) + 1)); strcpy (n -> label, p -> label); } } } col); } 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) { efres:", coltoa(i)); sprintf(line + strlen(line),"%s",coltoa(j)); linelim = strlen (line); } } rowshow_op() { register int i,j; for (i=0; iexpr); 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) l(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--) { hidden_row[i] = hidden_row[i-1]; } for (r = ++maxrow; r > r 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 = lookas; 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++) { hidden_row[i] = hidden_row[i+1]; } t (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 = malloc((unsigned)(strlen(p->label)+1)); strcpy (n -> label, p -> label); } } } colshow_op() { register int i,j; for (i=0; i=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]; hidden_col[i] = hidden_col[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-cSV #LIB=-lm -lcurses #Use this for BSD 4.2 #CFLAGS= -O -DBSD42 #LIB=-lm -lcurses -ltermcap #Use this for BSD 4.3 CFLAGS= -O -DBSD43 LIB=-lm -lcurses -ltermcap #Use this for system III (XENIX) #CFLAGS= -O -DSYSIII #LIB=-lm -lcurses -ltermcap #Use this for separate I and D space #ID=-i ID= $(name): sc.o lex.o gram.o interp.o cmds.o cc ${CFLAGS} ${ID} sc.o lex.o gram.o interp.o cmds.o ${LIB} -o $(name) diff_to_sc: diff_to_sc.c cc ${CFLAGS} -o dtv diff_to_sc.c lex.o: sc.h y.tab.h gram.o cc ${CFLAGS} $s; 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]; hidden_col[i] = hidden_col[i+1]; } maxcol--; FullUpdate++; modflg++; } SHAR_EOF if test 8071 -ne "`wc -c cmds.c`" then echo shar: error transmittin{SIMPLE} -c lex.c interp.o: sc.h sc.o: sc.h gram.o: sc.h y.tab.h cmds.o: cmds.c sc.h y.tab.h: gram.y gram.o: sc.h y.tab.h gram.c cc ${CFLAGS} -c gram.c sedexperres.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: ${SRC1} ${SRC2} ${DOCS} shar -v -c ${DOCS} ${SRC2} > sc.shar.1 shar -v -c ${SRC1} > sc.shar.2 lint: sc.h sc.c lex.c gram.c interp.c cmds.c lint ${CFLAGS} ${Sg cmds.c '(should have been 8071 characters)' fi echo shar: extracting eres.sed '(50 characters)' cat << \SHAR_EOF > eres.sed /%token.*K_/!d /%token.*K_\(.*\)/s// "\1", K_\1,/ SHAR_EOF if test 50 -ne "`wc -c eres.sed`" then echo shar: error transmitting eres.sed '(should have been 50 characters)' fi echo shar: extracting sres.sed '(50 characters)' cat << \SHAR_EOF > sres.sed /%token.*S_/!d /%token.*S_\(.*\)/s// "\1", S_\1,/ SHAR_EOF if test 50 -ne "`wc -c sres.sed`" then echo shar: error transmitting sres.sIMPLE } sc.c lex.c gram.c interp.c cmds.c -lcurses -lm $(name).1: sc.doc sed -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 if test 1845 -ne "`wc -c makefile`" then echo shar: error transmitting maked '(should have been 50 characters)' fi echo shar: extracting makefile '(1845 characters)' cat << \SHAR_EOF > makefile # Specify the name of the program. # All documentation and installation keys on this value. # name=sc EXDIR=/a/rgb/bin MANDIR=/usr/man/man1 SRC1=sc.h sc.c lex.c gram.y interp.c SRC2=cmds.c eres.sed sres.sed makefile cvt.sed DOCS=README $(name).man $(name).doc #Set SIMPLE for lex.c if you don't want arrow keys or lex.c blows up #SIMPLE=-DSIMPLE #Use this for system V.2 #CFLAGS= -O -DSYefile '(should have been 1845 characters)' fi echo shar: extracting cvt.sed '(1420 characters)' cat << \SHAR_EOF > cvt.sed 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/f#!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # sc.h # sc.c # lex.c # gram.y # interp.c # This archive created: Mon Jan 26 19:36:31 1987 # By: Robert Bond (NSC Portland, Oregon) echo shar: extracting sc.h '(1515 characters)' cat << \SHAR_EOF > sc.h /* VC A Table Calculator * Common definitions * * original by James Gosling, September 1982 * modified by Mark Weiser and Bruce Israel, * University of Maryland * */ #define MAXROWS 200 #define MAXCOLS 40 #defineormat 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/form error move(1,0), clrtoeol(), printw struct ent { double v; char *label; struct enode *expr; short flags; short row, col; struct ent *next; }; struct enode { int op; union { double k; struct ent *v; struct { struct enode *left, *right; } o; } e; }; /* op values */ #define O_VAR 'v' #define O_CONST 'k' #define O_REDUCE(c) (c+0200) #define ACOS 0 #define ASIN 1 #define ATAN 2 #define CEIL 3 #define COS 4 #define EXP 5 #define FABS 6 #define FLOOR 7 #define Hat j/g SHAR_EOF if test 1420 -ne "`wc -c cvt.sed`" then echo shar: error transmitting cvt.sed '(should have been 1420 characters)' fi # End of shell archive exit 0 -- Robert Bond ihnp4!nsc!nscpdc!rgb National Semiconductor tektronix!nscpdc!rgb sed '(should have been 50 characters)' fi echo shar: extracting sres.sed '(50 characters)' cat << \SHAR_EOF > sres.sed /%token.*S_/!d /%token.*S_\(.*\)/s// "\1", S_\1,/ SHAR_EOF if test 50 -ne "`wc -c sres.sed`" then echo shar: error transmitting sres.sYPOT 8 #define LOG 9 #define LOG10 10 #define POW 11 #define SIN 12 #define SQRT 13 #define TAN 14 #define DTR 15 #define RTD 16 #define MIN 17 #define MAX 18 /* flag values */ #define is_valid 0001 #define is_changed 0002 #define is_lchanged 0004 #define is_leftflush 0010 #define is_deleted 0020 #define ctl(c) ('c'&037) struct ent *tbl[MAXROWS][MAXCOLS]; int strow, stcol; int currow, curcol; int savedrow, savedcol; int FullUpdate; int maxrow, maxcol; int fwidth[MAXCOLS]; int precision[MAXCOLS]Q R sc.2bond "- ʀ ʔ ʜ-- ʘZd ʘ  C2"; char hidden_col[MAXCOLS]; char hidden_row[MAXROWS]; char line[1000]; int linelim; int changed; struct ent *to_fix; struct enode *new(); struct enode *new_const(); struct enode *new_var(); struct ent *lookat(); struct enode *copye(); char *coltoa(); int modflg; SHAR_EOF if test 1515 -ne "`wc -c sc.h`" then echo shar: error transmitting sc.h '(should have been 1515 characters)' fi echo shar: extracting sc.c '(18976 characters)' cat << \SHAR_EOF > sc.c /* 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 #include #ifdef BSD42 #include #else #ifndef SYSIII #include #endif #endif #include #include "sc.h" #if BSD42 || SYSIII #define cbreak crmode #define nocbreak nocrmode #endif char *malloc(); /* default column width */ #define DEFWIDTH 10 #define DEFPREC 2 #defi col; register struct ent **p; static lastmx, lastmy; static char *under_cursor = " "; int maxcol; int maxrow; int rows; int cols; register r; while (hidden_row[currow]) /* You can't hide the last row or col */ currow++; while (hidden_col[curcol]) curcol++; if (curcol < stcol) stcol = curcol, FullUpdate++; if (currow < strow) strow = currow, FullUpdate++; while (1) { register i; for (i = stcol, cols = 0, colne RESCOL 4 /* columns reserved for row numbers */ #define RESROW 3 /* rows reserved for prompt, error, and column numbers */ char curfile[1024]; int linelim = -1; int showme = 1; /* 1 to display the current cell in the top line */ char *rev = "$Revision: 3.1 $"; int seenerr; yyerror (err) char *err; { if (seenerr) return; seenerr++; move (1,0); clrtoeol (); printw ("%s: %.*s<=%s",err,linelim,line,line+linelim); } struct ent * lookat(row,col){ register struct ent **p; if  = RESCOL; (col + fwidth[i]) < COLS-1 && i < MAXCOLS; i++) { cols++; if (hidden_col[i]) continue; col += fwidth[i]; } if (curcol >= stcol + cols) stcol++, FullUpdate++; else break; } while (1) { register i; for (i = strow, rows = 0, row = RESROW; row < LINES && i < MAXROWS; i++) { rows++; if (hidden_row[i]) continue; row++; } if (currow >= strow + rows) strow++, FullUpdate++; else break; } maxcol = stcol + cols - 1;(row < 0) row = 0; else if (row > MAXROWS-1) row = MAXROWS-1; if (col < 0) col = 0; else if (col > MAXCOLS-1) col = MAXCOLS-1; p = &tbl[row][col]; if (*p==0) { *p = (struct ent *) malloc ((unsigned) sizeof (struct ent)); if (row>maxrow) maxrow = row; if (col>maxcol) maxcol = col; (*p)->label = 0; (*p)->flags = 0; (*p)->row = row; (*p)->col = col; (*p)->expr = 0; (*p)->v = (double) 0.0; } return *p; } /* * This structure is used to keep ent structs around before t maxrow = strow + rows - 1; if (FullUpdate) { register int i; move (2, 0); clrtobot (); standout(); for (row=RESROW, i=strow; i <= maxrow; i++) { if (hidden_row[i]) continue; move(row,0); printw("%-*d", RESCOL, i); row++; } move (2,0); printw("%*s", RESCOL, " "); for (col=RESCOL, i = stcol; i <= maxcol; i++) { if (hidden_col[i]) continue; move(2, col); printw("%*s", fwidth[i], coltoa(i)); col += fwidth[i]; } standend(); } for (row = strhey * are deleted to allow the sync_refs routine a chance to fix the * variable references. * We also use it as a last-deleted buffer for the 'p' command. */ free_ent(p) register struct ent *p; { p->next = to_fix; to_fix = p; p->flags |= is_deleted; } flush_saved() { register struct ent *p; register struct ent *q; if (!(p = to_fix)) return; while (p) { clearent(p); q = p->next; free ((char *)p); p = q; } to_fix = 0; } update () { register row, ow, r = RESROW; row <= maxrow; row++) { register c = RESCOL; if (hidden_row[row]) continue; for (p = &tbl[row][col = stcol]; col <= maxcol; col++, p++) { if (hidden_col[col]) continue; if (*p && ((*p) -> flags & is_changed || FullUpdate)) { char *s; move (r, c); (*p) -> flags &= ~is_changed; if ((*p) -> flags & is_valid) printw ("%*.*f", fwidth[col], precision[col], (*p) -> v); if (s = (*p) -> label) { char field[1024]; strncpy(field,s,fwidth[col]);  field[fwidth[col]] = 0; mvaddstr (r, (*p) -> flags & is_leftflush ? c : c - strlen (field) + fwidth[col], field); } } c += fwidth[col]; } r++; } move(lastmy, lastmx); if (inch() == '<') addstr (under_cursor); lastmy = RESROW; for (row = strow; row < currow; row++) if (!hidden_row[row]) lastmy += 1; lastmx = RESCOL; for (col = stcol; col <= curcol; col++) if (!hidden_col[col]) lastmx += fwidth[col]; move(lastmy, la changed = 0; update (); refresh (); move (1, 0); clrtoeol (); fflush (stdout); seenerr = 0; if (((c = nmgetch ()) < ' ') || ( c == 0177 )) switch (c) { #if defined(BSD42) || defined (BSD43) case ctl (z): nocrmode (); nl (); echo (); kill(getpid(),SIGTSTP); /* the pc stops here */ crmode (); nonl (); noecho (); break; #endif case ctl (r): case ctl (l): FullUpdate++; clearok(stdscr,1); break; default: error ("stmx); *under_cursor = inch(); addstr ("<"); move (0, 0); clrtoeol (); if (linelim >= 0) { addstr (">> "); addstr (line); } else { if (showme) { register struct ent *p; p = tbl[currow][curcol]; if (p && ((p->flags & is_valid) || p->label)) { if (p->expr || !p->label) { linelim = 0; editexp(currow, curcol); } else { sprintf(line, "%s", p->label); } addstr("["); addstr (line); addstr("]"); linelim = -1; } else { addstr("[]"); No such command (^%c)", c + 0100); break; case ctl (b): while (--arg>=0) { if (curcol) curcol--; else error ("At column A"); while(hidden_col[curcol] && curcol) curcol--; } break; case ctl (c): running = 0; break; case ctl (f): while (--arg>=0) { if (curcol < MAXCOLS - 1) curcol++; else error ("The table can't be any wider"); while(hidden_col[curcol]&&(curcol=0) if (linelim > 0) line[--linelim] = 0; break; case ctl (m): case ctl (j): if (linelim < 0) line[linelim = 0] = 0; else { linelim = 0; yyparse (); linelim = -1; } break; case ctl (n): while (--arg>=0) { if (currow < MAXROWS - 1) currow++; else error ("The table can't be any longenonl(); noecho (); initkbd(); if (argc > 1) { strcpy(curfile,argv[1]); readfile (argv[1],0); } modflg = 0; strcpy(revmsg, argv[0]); for (revi=rev; *revi++ != ':';); strcat(revmsg, revi); revi = revmsg+strlen(revmsg); *--revi = 0; strcat(revmsg,"Type '?' for help."); error (revmsg); FullUpdate++; while (inloop) { running = 1; while (running) { nedistate = -1; narg = 1; if (edistate < 0 && linelim < 0 && (changed || FullUpdate)) EvalAll (),r"); while (hidden_row[currow] && (currow < MAXROWS - 1)) currow++; } break; case ctl (p): while (--arg>=0) { if (currow) currow--; else error ("At row zero"); while (hidden_row[currow] && currow) currow--; } break; case ctl (q): break; /* ignore flow control */ case ctl (s): break; /* ignore flow control */ case ctl (t): showme ^= 1; break; case ctl (u): narg = arg * 4; nedistate = 1; break; case ctl (v): /* insert variable name */ if (linelim > 0) { sprintf (line+linelim,"%s%d", coltoa(curcol), currow); linelim = strlen (line); } break; case ctl (e): /* insert variable expression */ if (linelim > 0) editexp(currow,curcol); break; case ctl (a): /* insert variable value */ if (linelim > 0) { struct ent *p = tbl[currow][curcol]; if (p && p -> flags & is_valid) { sprintf (line + linelim, "%.*f", precision[curcol],p -> v);  coltoa(curcol), currow); linelim = strlen (line); break; case '<': sprintf (line, "leftstring %s%d = \"", coltoa(curcol), currow); linelim = strlen (line); break; case '>': sprintf (line, "rightstring %s%d = \"", coltoa(curcol), currow); linelim = strlen (line); break; case 'e': editv (currow, curcol); break; case 'E': edits (currow, curcol); break; case 'f': sprintf (line, "format [ linelim = strlen (line); } } break; } else if ('0' <= c && c <= '9' && (linelim < 0 || edistate >= 0)) { if (edistate != 0) { if (c == '0') /* just a '0' goes to left col */ curcol = 0; else { nedistate = 0; narg = c - '0'; } } else { nedistate = 0; narg = arg * 10 + (c - '0'); } } else if (linelim >= 0) { line[linelim++] = c; line[linelim] = 0; } else switch (c) { case '.': for column] %s [is] ", coltoa(curcol)); error("Current format is %d %d", fwidth[curcol],precision[curcol]); linelim = strlen (line); break; case 'g': sprintf (line, "goto [v] "); linelim = strlen (line); break; case 'P': sprintf (line, "put [database into] \""); if (*curfile) error("default file is '%s'",curfile); linelim = strlen (line); break; case 'M': sprintf (line, "merge [database from] \"");  nedistate = 1; break; case ':': break; /* Be nice to vi users */ case '=': sprintf(line,"let %s%d = ",coltoa(curcol),currow); linelim = strlen (line); break; case '/': switch (nmgetch()) { case 'c': sprintf(line,"copy [to] %s%d [from] ", coltoa(curcol), currow); linelim = strlen(line); break; case 'x': sprintf(line,"erase [v:v] "); linelim = strlen(line); break; case 'f': sprintf(line,"fill [v:v starlinelim = strlen (line); break; case 'G': sprintf (line, "get [database from] \""); if (*curfile) error("default file is '%s'",curfile); linelim = strlen (line); break; case 'W': sprintf (line, "write [listing to] \""); linelim = strlen (line); break; case 'T': /* tbl output */ sprintf (line, "tbl [listing to] \""); linelim = strlen (line); break; case 'i': switch (get_qual()) { case 'r': insertt inc] "); linelim = strlen(line); break; default: error("Invalid region operation"); } break; case '$': curcol = MAXCOLS - 1; while (!tbl[currow][curcol] && curcol > 0) curcol--; break; case '#': currow = MAXROWS - 1; while (!tbl[currow][curcol] && currow > 0) currow--; break; case '^': currow = 0; break; case '?': help (); break; case '"': sprintf (line, "label %s%d = \"", row(arg); break; case 'c': insertcol(arg); break; default: error("Invalid insert command"); break; } break; case 'd': switch (get_qual()) { case 'r': deleterow(arg); break; case 'c': deletecol(arg); break; default: error("Invalid delete command"); break; } break; case 'v': switch (get_qual()) { case 'r': rowvalueize(arg); modflg++; break; case 'c': colvalueize(arg); modflg++; break; default: error("Invalid value command"); break; } break; case 'p': { register qual; qual = get_qual(); while (arg--) pullcells(qual); break; } case 'x': { register struct ent **p; register int c; flush_saved(); for (c = curcol; arg-- && c < MAXCOLS; c++) { p = &tbl[currow][c]; if (*p) { free_ent(*p); *p = 0;  n -> label = malloc((unsigned)(strlen(p->label)+1)); strcpy (n -> label, p -> label); } } break; } case 'z': switch (get_qual()) { case 'r': hiderow(arg); break; case 'c': hidecol(arg); break; default: error("Invalid zap command"); break; } break; case 's': switch (get_qual()) { case 'r': rowshow_op(); break; case 'c': colshow_op(); break; default:  } } sync_refs(); FullUpdate++; } break; case 'Q': case 'q': running = 0; break; case 'h': while (--arg>=0) { if (curcol) curcol--; else error ("At column A"); while(hidden_col[curcol] && curcol) curcol--; } break; case 'j': while (--arg>=0) { if (currow < MAXROWS - 1) currow++; else error ("The table can't be any longer"); while (hidden_row[currow]&&(curr error("Invalid show command"); break; } break; case 'a': switch (get_qual()) { case 'r': while (arg--) duprow(); break; case 'c': while (arg--) dupcol(); break; default: error("Invalid add row/col command"); break; } break; default: if ((c & 0177) != c) error("Weird character, decimal '%d'.\n", (int) c); else error ("No such command (%c)", c); break; } edistate =ow=0) { if (currow) currow--; else error ("At row zero"); while (hidden_row[currow] && currow) currow--; } break; case 'l': while (--arg>=0) { if (curcol < MAXCOLS - 1) curcol++; else error ("The table can't be any wider"); while(hidden_col[curcol]&&(curcol flags = p -> flags; n -> v = p -> v; n -> expr = copye(p->expr, currow - savedrow, c - savedcol); n -> label = 0; if (p -> label) {  move (LINES - 1, 0); clrtoeol(); refresh(); nocbreak(); nl(); echo(); resetkbd(); endwin(); exit(1); } modcheck(endstr) char *endstr; { if (modflg && curfile[0]) { char ch, lin[100]; move (0, 0); clrtoeol (); sprintf (lin,"File '%s' is modified, save%s? ",curfile,endstr); addstr (lin); refresh(); ch = nmgetch(); if (ch != 'n' && ch != 'N') if (writefile(curfile) < 0) return (1); else if (ch == ctl (g) || ch == ctl([)) return(1); } else if (modflg) { char ch, lin[100]; move (0, 0); clrtoeol (); sprintf (lin,"Do you want a chance to save the data? "); addstr (lin); refresh(); ch = nmgetch(); if (ch == 'n' || ch == 'N') return(0); else return(1); } return(0); } writefile (fname) char *fname; { register FILE *f; register struct ent **p; register r, c; char save[1024]; if (*fname == 0) fname = &curfile[0]; strcpy(save,fname); f = fopen (fname, "w"); if (f==0) { error ("Can't create %s", fnaaxrow; r++) { register struct ent **p = &tbl[r][0]; for (c=0; c++<=maxcol; p++) if (*p) { if ((*p)->expr) efree ((*p) -> expr); if ((*p)->label) free ((*p) -> label); free ((char *)*p); *p = 0; } } maxrow = 0; maxcol = 0; FullUpdate++; } #if DEBUG debugout(g,fmt,args) FILE *g; char *fmt; { int op; if (g == 0) g = fopen("debug","a"),op = 1; if (g == 0) return; _doprnt(fmt, &args, g); fflush(g); if (op) fclose(g); } #endif SHAR_EOF if test 18976 me); 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; clabel) fprintf (f, "%sstring %s%d = \"%s\"\n-ne "`wc -c sc.c`" then echo shar: error transmitting sc.c '(should have been 18976 characters)' fi echo shar: extracting lex.c '(9305 characters)' cat << \SHAR_EOF > lex.c /* SC A Spreadsheet Calculator * Lexical analyser * * original by James Gosling, September 1982 * modifications by Mark Weiser and Bruce Israel, * University of Maryland * * More mods Robert Bond, 12/86 * */ #if defined(BSD42) || defined(BSD43) #include #endif #include #include 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); strcpy(curfile,save); modflg = 0; error("File '%s' written.",curfile); return (0); } readfile (fname,eraseflg) char *fname; int eraseflg; { register FILE *f; char save[1024]; if (*fname == 0) fname = &curfile[0]; strcpy(save,fname); if (eraseflg && strcmp(fname,curfile) && mgnal.h> #include #include "sc.h" #include #ifdef BSD42 #include #else #ifndef SYSIII #include #endif #endif #include "y.tab.h" char *strtof(); char *malloc(); jmp_buf wakeup; struct key { char *key; int val; }; struct key experres[] = { #include "experres.h" 0, 0}; struct key statres[] = { #include "statres.h" 0, 0}; #define ctl(x) ('x'&037) yylex () { register char *p = line+linelim; int ret; while (isspace(*p)) p++; if (*odcheck(" first")) return; f = fopen (save, "r"); if (f==0) { error ("Can't read %s", save); return; } if (eraseflg) erasedb (); while (fgets(line,sizeof line,f)) { linelim = 0; if (line[0] != '#') yyparse (); } fclose (f); linelim = -1; modflg++; if (eraseflg) { strcpy(curfile,save); modflg = 0; } EvalAll(); } erasedb () { register r, c; for (c = 0; c<=maxcol; c++) { fwidth[c] = DEFWIDTH; precision[c] = DEFPREC; } for (r = 0; r<=mp==0) ret = -1; else if (isalpha(*p)) { char *tokenst = p; register tokenl; register struct key *tbl; while (isalpha(*p)) p++; if ((tokenl = p-tokenst) <= 2) { register col; /* a COL is 1 or 2 char alpha (and not pi or ln!) */ if (tokenl == 2 && tokenst[0] == 'p' && tokenst[1] == 'i') { ret = K_PI; } else if (tokenl == 2 && tokenst[0] == 'l' && tokenst[1] == 'n') { ret = K_LN; } else { ret = COL; col = ((tokenst[0] & 0137) - 'A'); if (p == tokenst+2) col = (col + 1)*26 + ((tokenst[1] & 0137) - 'A'); yylval.ival = col; } } else { ret = WORD; tokenl = p-tokenst; for (tbl = linelim ? experres : statres; tbl->key; tbl++) if (((tbl->key[0]^tokenst[0])&0137)==0 && tbl->key[tokenl]==0) { register i = 1; while (ikey[i])&0137)==0) i++; if (i>=tokenl) { ret = tbl->val; break; } } if (ret==WORD) { linelim = p-line; yyerror ("Unintelligible word"); } } l(u), ctl(v), ctl(e), ctl(a), 0, }; initkbd() { register struct key_map *kp; register i,j; char *ks; char *p = keyarea; static char buf[1024]; /* Why do I have to do this again? */ if (tgetent(buf, getenv("TERM")) <= 0) return; km[0].k_str = tgetstr("kl", &p); km[0].k_val = ctl(b); km[1].k_str = tgetstr("kr", &p); km[1].k_val = ctl(f); km[2].k_str = tgetstr("ku", &p); km[2].k_val = ctl(p); km[3].k_str = tgetstr("kd", &p); km[3].k_val = ctl(n); ks = tgetstr("ks } else if ((*p == '.') || isdigit(*p)) { register long v = 0; char *nstart = p; if (*p != '.') { do v = v*10 + (*p-'0'); while (isdigit(*++p)); } if (*p=='.' || *p == 'e' || *p == 'E') { ret = FNUMBER; p = strtof(nstart, &yylval.fval); } else { if((int)v != v) { ret = FNUMBER; yylval.fval = v; } else { ret = NUMBER; yylval.ival = v; } } } e",&p); if (ks) printf("%s",ks); /* Unmap arrow keys which conflict with our ctl keys */ /* Ignore unset, longer than length 1, and 1-1 mapped keys */ for (i = 0; i < N_KEY; i++) { kp = &km[i]; if (kp->k_str && (kp->k_str[1] == 0) && (kp->k_str[0] != kp->k_val)) for (j = 0; dont_use[j] != 0; j++) if (kp->k_str[0] == dont_use[j]) { kp->k_str = (char *)0; break; } } #ifdef TIOCSLTC ioctl(fileno(stdin), TIOCGLTC, (char *)&old_chars); new_chars lse if (*p=='"') { /* This storage is never freed. Oh well. -MDW */ char *ptr; ptr = p+1; while(*ptr && *ptr++ != '"'); ptr = malloc((unsigned)(ptr-p)); yylval.sval = ptr; p += 1; while (*p && *p!='"') *ptr++ = *p++; *ptr = 0; if (*p) p += 1; ret = STRING; } else if (*p=='[') { while (*p && *p!=']') p++; if (*p) p++; linelim = p-line; return yylex(); } else ret = *p++; linelim = p-line; return ret; } #ifdef SIMPLE initkbd() {} resetkbd() {} nmgetch()= old_chars; if (old_chars.t_lnextc == ctl(v)) new_chars.t_lnextc = -1; if (old_chars.t_rprntc == ctl(r)) new_chars.t_rprntc = -1; ioctl(fileno(stdin), TIOCSLTC, (char *)&new_chars); #endif } resetkbd() { #ifdef TIOCSLTC ioctl(fileno(stdin), TIOCSLTC, (char *)&old_chars); #endif } nmgetch() { register int c; register struct key_map *kp; register struct key_map *biggest; register int i; int almost; int maybe; static char dumpbuf[10]; static char *dumpinde { return (getchar() & 0x7f); } #else /*SIMPLE*/ #if defined(BSD42) || defined (SYSIII) || defined(BSD43) #define N_KEY 4 struct key_map { char *k_str; char k_val; char k_index; }; struct key_map km[N_KEY]; char keyarea[N_KEY*10]; char *tgetstr(); char *getenv(); #ifdef TIOCSLTC struct ltchars old_chars, new_chars; #endif char dont_use[] = { ctl(z), ctl(r), ctl(l), ctl(b), ctl(c), ctl(f), ctl(g), ctl([), ctl(h), ctl(m), ctl(j), ctl(n), ctl(p), ctl(q), ctl(s), ctl(t), ctx; int timeout(); if (dumpindex && *dumpindex) return (*dumpindex++); c = getchar() & 0x7f; biggest = 0; almost = 0; for (kp = &km[0]; kp < &km[N_KEY]; kp++) { if (!kp->k_str) continue; if (c == kp->k_str[kp->k_index]) { almost = 1; kp->k_index++; if (kp->k_str[kp->k_index] == 0) { c = kp->k_val; for (kp = &km[0]; kp < &km[N_KEY]; kp++) kp->k_index = 0; return(c); } } if (!biggest && kp->k_index) biggest = kp; else if (kp->k_index && biggest->k_index < kp->k_index) biggest = kp; } if (almost) { signal(SIGALRM, timeout); alarm(1); if (setjmp(wakeup) == 0) { maybe = nmgetch(); alarm(0); return(maybe); } } if (biggest) { for (i = 0; ik_index; i++) dumpbuf[i] = biggest->k_str[i]; dumpbuf[i++] = c; dumpbuf[i] = 0; dumpindex = &dumpbuf[1]; for (kp = &km[0]; kp < &km[N_KEY]; kp++) kp->k_index = 0; return (; exps = 1; p++; if (*p == '+') p++; else if (*p == '-') { p++; exps = -1; } while(isdigit(*p)) { exp = exp * 10 + (*p - '0'); p++; } } if (exp) { if (exps > 0) while (exp--) acc *= 10.0; else while (exp--) acc *= 1.0/10.0; } if (sign > 0) *res = acc; else *res = -acc; return(p); } help () { move(2,0); clrtobot(); dbline = 0; debug ("Cursor: ^n j next row ^p k prev. row ESC ^g erase cmd"); dumpbuf[0]); } return(c); } #endif #ifdef SYSV initkbd() { keypad(stdscr, TRUE); } resetkbd() {} nmgetch() { register int c; c = getch(); switch (c) { case KEY_LEFT: c = ctl(b); break; case KEY_RIGHT: c = ctl(f); break; case KEY_UP: c = ctl(p); break; case KEY_DOWN: c = ctl(n); break; default: c = c & 0x7f; } return (c); } #endif /* SYSV */ #endif /* SIMPLE */ timeout() { longjmp(wakeup, -1); } int dbline; /*VARARGS*/ void debug (st debug (" ^f l fwd col ^b h back col ^l ^r redraw screen"); debug (" 0 col A $ last col g goto "); debug (" ^ row 0 # last row"); debug ("Cell: \" < > enter label = enter value x clear cell"); debug (" c copy cell m mark cell ^t line 1 on/off"); debug (" ^a type value ^e type expr. ^v type vbl name"); debug ("Row, Col: ar ac dup r) char *str; { mvprintw (2+(dbline++%22),80-70,str); clrtoeol(); } /* * This converts a floating point number of the form * [s]ddd[.d*][esd*] where s can be a + or - and e is E or e. * to floating point. * p is advanced. */ char * strtof(p, res) register char *p; double *res; { double acc; int sign; double fpos; int exp; int exps; acc = 0.0; sign = 1; exp = 0; exps = 1; if (*p == '+') p++; else if (*p == '-') { p++; sign = -1;  ir ic insert sr sc show"); debug (" dr dc delete zr zc hide pr pc pull"); debug (" vr vc value only f format"); debug ("Region: /c copy /x clear /f fill"); debug ("File: G get database M merge database T write tbl fmt"); debug (" P put database W write listing"); debug ("Misc: Q q quit pm pull (merge)"); debug ("Expr: +-*/^ arithmetic ?e:e condi } while (isdigit(*p)) { acc = acc * 10.0 + (double)(*p - '0'); p++; } if (*p == 'e' || *p == 'E') { p++; if (*p == '+') p++; else if (*p == '-') { p++; exps = -1; } while(isdigit(*p)) { exp = exp * 10 + (*p - '0'); p++; } } if (*p == '.') { fpos = 1.0/10.0; p++; while(isdigit(*p)) { acc += (*p - '0') * fpos; fpos *= 1.0/10.0; p++; } } if (*p == 'e' || *p == 'E') { exp = 0tional & | booleans"); debug (" < = > relations <= >= relations != relations"); debug (" @sum(v1:v2) @avg(v1:v2) @prod(v1:v2)"); debug (" @func(e) - lots of other math functions"); } SHAR_EOF if test 9305 -ne "`wc -c lex.c`" then echo shar: error transmitting lex.c '(should have been 9305 characters)' fi echo shar: extracting gram.y '(4962 characters)' cat << \SHAR_EOF > gram.y /* 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 #include "sc.h" %} %union { int ival; double fval; struct ent *ent; struct enode *enode; char *sval; } %type var %type num %type e term %token STRING %token NUMBER %token FNUMBER %token WORD %token COL %token S_FORMAT %token S_LA$$ = new ('f', (struct enode *)0, $2); } | '@' K_SUM '(' var ':' var ')' { $$ = new (O_REDUCE('+'), (struct enode *)$4, (struct enode *)$6); } | '@' K_PROD '(' var ':' var ')' { $$ = new (O_REDUCE('*'), (struct enode *)$4, (struct enode *)$6); } | '@' K_AVG '(' var ':' var ')' { $$ = new (O_REDUCE('a'), (struct enode *)$4, (struct enode *)$6); } | '@' K_ACOS '(' e ')' { $$ = new(ACOS, (struct enode *)0, $4); } | '@' K_ASIN '(' e ')' { $$ = new(ASIN, (struct BEL %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_PROGLET %token S_COPY %token S_SHOW %token S_ERASE %token S_FILL %token S_GOTO %token K_FIXED %token K_SUM %token K_PROD %token K_AVG %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_RTDenode *)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(L %token K_MAX %token K_MIN %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 NUMBER NUMBER { fwidth[$2] = $3; FullUpdate++; modflg++; precision[$2] = $4; } | S_GET STRING { readfile ($2,1); } | S_MERGE STRING OG, (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_MAX '(' e ',' e ')' { ${ 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 var ':' var { copy($2, $3, $5); } | S_ERASE var ':' var { eraser($2, $4); } | S_FILL var ':' var num num { fill($2, $4, $5, $6); } | S_GOTO var {moveto($2); } | /* nothing */ | error; term: var { $$ = new_var('v', $1); } | K_FIXED term { $ = new(MAX, $4, $6); } | '@' K_MIN '(' e ',' e ')' { $$ = new(MIN, $4, $6); } | '(' 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 { $$ = r; 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); } doublnew ('~', (struct enode *)0, new ('=', $1, $4)); } | e '>' '=' e { $$ = new ('~', (struct enode *)0, new ('<', $1, $4)); } ; var: COL NUMBER { $$ = lookat($2 , $1); }; num: NUMBER { $$ = (double) $1; } | FNUMBER { $$ = $1; } | '-' num { $$ = -$2; } | '+' num { $$ = $2; } ; SHAR_EOF if test 4962 -ne "`wc -c gram.y`" then echo shar: error transmitting gram.y '(should have been 4962 characters)' fi echo shar: extracting interp.c '(17239 characters)' cat << \SHAR_EOF > interp.c /* SCe 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 (ev 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 #include #ifdef BSD42 #include #else #ifndef SYSIII #include #endif #endif #include #include "sc.h" #define DEFCOLDELIM ':' char *malloc(); #define PI (double)3.14159265358979323846 #defal(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 (eine 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 = min->e.v->v); case O_REDUCE('+'): case O_REDUCE('*'): case O_REDUCE('a'): { 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 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 FLOO} struct enode *new_var(op, a1) struct ent *a1; { register struct enode *p = (struct enode *) malloc ((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 *) malloc ((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 delR: return (floor(eval(e->e.o.right))); case HYPOT: return (hypot(eval(e->e.o.left), eval(e->e.o.right))); case LOG: return (log(eval(e->e.o.right))); case LOG10: return (log10(eval(e->e.o.right))); 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 MIN:tar, 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;  { double left, right; left = eval(e->e.o.left); right = eval(e->e.o.right); return (left < right ? left : right); } case MAX: { double left, right; left = eval(e->e.o.left); right = eval(e->e.o.right); return (left > right ? left : right); } } return((double) 0.0); /* safety net */ } #define MAXPROP 7 EvalAll () { int repct = 0; while (RealEvalAll() && (repct++ <= MAXPROP)); } int RealEvalAll () { register ir++) 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 = malloc ((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); } moveto(v) struct ent ,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 *) malloc ((unsigned)sizeof (struct enode)); p->op = op; p->e.o.left = a1; p->e.o.right = a2; return p; *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; ol %= 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 '^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': mypriority = 12; break; } if (mypriorityop) { 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); efree (e->e.o.right); } free ((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) free(v->label); if (s && s[0]) { v->label = malloc ((unsigned)(s); break; case O_REDUCE('+'): s = "@sum("; goto more; case O_REDUCE('*'): s = "@prod("; goto more; case O_REDUCE('a'): s = "@avg("; /* fall though to more; */ more: for (; line[linelim++] = *s++;); linelim--; 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("trlen(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; { if (v) sprintf (line+linelim, "%s%d", coltoa(v->col), v->row); else sprintf (line+linelim,"VAR?"); 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; c; 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 MIN: s = "@min("; goto more2; case MAX: s = "@max("; goto more2; 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 (mypriorityplinelim) plinelim = d-pline; } } c += fwidth [col]; } fprintf (f,"%.*s\n",plinelim,pline); } fclose (f); } tblprintfile (fname) char *fname; { FILE *f = fopen(fname, "w"); char pline[1000]; register row, col; register struct ent **p; char coldelim = DEFCOLDELIM; if (f==0) { error ("Can't create %s", fname); return; } for (row=0;row<=maxrow; row++) rity) line[linelim++] = ')'; } else line[linelim++] = '?'; } editv (row, col) { sprintf (line, "let %s%d = ", coltoa(col), row); 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 = look{ 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); } fclose (f); } struct enode *copye (e, Rdelta, Cdelta) register struct enode *e; { register struct enode *ret; if (e==0) ret = 0; else { ret = (struct enode *) malloc ((unsigned) sizeof (strat (row, col); sprintf (line, "%sstring %s%d = \"", ((p->flags&is_leftflush) ? "left" : "right"), coltoa(col), row); linelim = strlen(line); if (p->label) { sprintf (line+linelim, "%s", p->label); linelim += strlen (line+linelim); } } printfile (fname) char *fname; { FILE *f = fopen(fname, "w"); char pline[1000]; int plinelim; register row, col; register struct ent **p; if (f==0) { error ("Can't create %s", fname); return; } for (row=0uct 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'): 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 = (s;row<=maxrow; row++) { register c = 0; plinelim = 0; for (p = &tbl[row][col=0]; col<=maxcol; col++, p++) { if (*p) { char *s; while (plinelimflags&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) truct 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; 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'): e->e.o.right = (struct enode *) lookat ( t Bond ihnp4!nsc!nscpdc!rgb National Semiconductor tektronix!nscpdc!rgb +; if (d-pline>plinelim) plinelim = d-pline; } } c += fwidth [col]; } fprintf (f,"%.*s\n",plinelim,pline); } fclose (f); } tblprintfile (fname) char *fname; { FILE *f = fopen(fname, "w"); char pline[1000]; register row, col; register struct ent **p; char coldelim = DEFCOLDELIM; if (f==0) { error ("Can't create %s", fname); return; } for (row=0;row<=maxrow; row++)  ((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 (J J sc.cbond "- ʀ ʔ ʜ-- ʘZd ʘ  Cc"r2 > MAXROWS-2) { error("You can't hide the last row"); return; } FullUpdate++; while (r1 <= r2) hidden_row[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) hidden_col[c1++] = 1; } showrow(r1, r2) { if (r1 < 0 || r1 > r2) { error("Invalid /* 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 #include #ifdef BSD42 #include #else #ifndef SYSIII #include #endif #endif #include #include "sc.h" #if BSD42 || SYSIII #define cbreak crmode #define nocbreak nocrmode #endif char *malloc(); /* default column wRange"); return; } if (r2 > MAXROWS-1) { r2 = MAXROWS-1; } FullUpdate++; while (r1 <= r2) hidden_row[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) hidden_col[c1++] = 0; } SHAR_EOF if test 17239 -ne "`wc -c interp.c`" then echo shar: error transmitting interp.c '(should have been 17239 characters)' fi # End of shell archive exit 0 -- Roberidth */ #define DEFWIDTH 10 #define DEFPREC 2 #define RESCOL 4 /* columns reserved for row numbers */ #define RESROW 3 /* rows reserved for prompt, error, and column numbers */ char curfile[1024]; int linelim = -1; int showme = 1; /* 1 to display the current cell in the top line */ char *rev = "$Revision: 3.1 $"; int seenerr; yyerror (err) char *err; { if (seenerr) return; seenerr++; move (1,0); clrtoeol (); printw ("%s: %.*s<=%s",err,linelim,line,line+linelim); } struct ent * lookat(row,col){ register struct ent **p; if (row < 0) row = 0; else if (row > MAXROWS-1) row = MAXROWS-1; if (col < 0) col = 0; else if (col > MAXCOLS-1) col = MAXCOLS-1; p = &tbl[row][col]; if (*p==0) { *p = (struct ent *) malloc ((unsigned) sizeof (struct ent)); if (row>maxrow) maxrow = row; if (col>maxcol) maxcol = col; (*p)->label = 0; (*p)->flags = 0; (*p)->row = row; (*p)->col = col; (*p)->expr = 0; (*p)->v = (double) 0.0; } return *p; } /* * Thi else break; } maxcol = stcol + cols - 1; maxrow = strow + rows - 1; if (FullUpdate) { register int i; move (2, 0); clrtobot (); standout(); for (row=RESROW, i=strow; i <= maxrow; i++) { if (hidden_row[i]) continue; move(row,0); printw("%-*d", RESCOL, i); row++; } move (2,0); printw("%*s", RESCOL, " "); for (col=RESCOL, i = stcol; i <= maxcol; i++) { if (hidden_col[i]) continue; move(2, col); printw("%*s", fwidth[i], coltoa(i)); cols structure is used to keep ent structs around before they * are deleted to allow the sync_refs routine a chance to fix the * variable references. * We also use it as a last-deleted buffer for the 'p' command. */ free_ent(p) register struct ent *p; { p->next = to_fix; to_fix = p; p->flags |= is_deleted; } flush_saved() { register struct ent *p; register struct ent *q; if (!(p = to_fix)) return; while (p) { clearent(p); q = p->next; free ((char *)p); p = q; } t += fwidth[i]; } standend(); } for (row = strow, r = RESROW; row <= maxrow; row++) { register c = RESCOL; if (hidden_row[row]) continue; for (p = &tbl[row][col = stcol]; col <= maxcol; col++, p++) { if (hidden_col[col]) continue; if (*p && ((*p) -> flags & is_changed || FullUpdate)) { char *s; move (r, c); (*p) -> flags &= ~is_changed; if ((*p) -> flags & is_valid) printw ("%*.*f", fwidth[col], precision[col], (*p) -> v); if (s = (*p) -> label) { charo_fix = 0; } update () { register row, col; register struct ent **p; static lastmx, lastmy; static char *under_cursor = " "; int maxcol; int maxrow; int rows; int cols; register r; while (hidden_row[currow]) /* You can't hide the last row or col */ currow++; while (hidden_col[curcol]) curcol++; if (curcol < stcol) stcol = curcol, FullUpdate++; if (currow < strow) strow = currow, FullUpdate++; whi field[1024]; strncpy(field,s,fwidth[col]); field[fwidth[col]] = 0; mvaddstr (r, (*p) -> flags & is_leftflush ? c : c - strlen (field) + fwidth[col], field); } } c += fwidth[col]; } r++; } move(lastmy, lastmx); if (inch() == '<') addstr (under_cursor); lastmy = RESROW; for (row = strow; row < currow; row++) if (!hidden_row[row]) lastmy += 1; lastmx = RESCOL; for (col = stcol; col <= curcol; col++) if (!hiddenle (1) { register i; for (i = stcol, cols = 0, col = RESCOL; (col + fwidth[i]) < COLS-1 && i < MAXCOLS; i++) { cols++; if (hidden_col[i]) continue; col += fwidth[i]; } if (curcol >= stcol + cols) stcol++, FullUpdate++; else break; } while (1) { register i; for (i = strow, rows = 0, row = RESROW; row < LINES && i < MAXROWS; i++) { rows++; if (hidden_row[i]) continue; row++; } if (currow >= strow + rows) strow++, FullUpdate++;_col[col]) lastmx += fwidth[col]; move(lastmy, lastmx); *under_cursor = inch(); addstr ("<"); move (0, 0); clrtoeol (); if (linelim >= 0) { addstr (">> "); addstr (line); } else { if (showme) { register struct ent *p; p = tbl[currow][curcol]; if (p && ((p->flags & is_valid) || p->label)) { if (p->expr || !p->label) { linelim = 0; editexp(currow, curcol); } else { sprintf(line, "%s", p->label); } addstr("["); addstr (line); addstr("]"); linelim = -1; } else { addstr("[]"); } } move (lastmy, lastmx); } FullUpdate = 0; } main (argc, argv) char **argv; { int inloop = 1; register int c; int edistate = -1; int arg = 1; int narg; int nedistate; int running; char revmsg[80]; char *revi; { register i; for (i = 0; i < MAXCOLS; i++) { fwidth[i] = DEFWIDTH; precision[i] = DEFPREC; } } curfile[0]=0; running = 1; signcurcol=0) if (linelim > 0) line[--linelim] = 0; break; case ctl (m): case ctl (j): if (linelim < 0) line[linelim = 0] = 0; else { linelim = 0; yyparse (); linelim = -1; } break; case ctl (n): while (--arg>=0) { if (currow < MAXROWS - 1) currowals(); initscr (); clear (); cbreak(); nonl(); noecho (); initkbd(); if (argc > 1) { strcpy(curfile,argv[1]); readfile (argv[1],0); } modflg = 0; strcpy(revmsg, argv[0]); for (revi=rev; *revi++ != ':';); strcat(revmsg, revi); revi = revmsg+strlen(revmsg); *--revi = 0; strcat(revmsg,"Type '?' for help."); error (revmsg); FullUpdate++; while (inloop) { running = 1; while (running) { nedistate = -1; narg = 1; if (edistate < 0 && l++; else error ("The table can't be any longer"); while (hidden_row[currow] && (currow < MAXROWS - 1)) currow++; } break; case ctl (p): while (--arg>=0) { if (currow) currow--; else error ("At row zero"); while (hidden_row[currow] && currow) currow--; } break; case ctl (q): break; /* ignore flow control */ case ctl (s): break; /* ignore flow control */ case ctl (t): showme ^= 1; break; case ctl inelim < 0 && (changed || FullUpdate)) EvalAll (), changed = 0; update (); refresh (); move (1, 0); clrtoeol (); fflush (stdout); seenerr = 0; if (((c = nmgetch ()) < ' ') || ( c == 0177 )) switch (c) { #if defined(BSD42) || defined (BSD43) case ctl (z): nocrmode (); nl (); echo (); kill(getpid(),SIGTSTP); /* the pc stops here */ crmode (); nonl (); noecho (); break; #endif case ctl (r): case ctl (l): FullUpdate++; cl(u): narg = arg * 4; nedistate = 1; break; case ctl (v): /* insert variable name */ if (linelim > 0) { sprintf (line+linelim,"%s%d", coltoa(curcol), currow); linelim = strlen (line); } break; case ctl (e): /* insert variable expression */ if (linelim > 0) editexp(currow,curcol); break; case ctl (a): /* insert variable value */ if (linelim > 0) { struct ent *p = tbl[currow][curcol]; if (p && p -> flags & is_valid) { sprintf (lineearok(stdscr,1); break; default: error ("No such command (^%c)", c + 0100); break; case ctl (b): while (--arg>=0) { if (curcol) curcol--; else error ("At column A"); while(hidden_col[curcol] && curcol) curcol--; } break; case ctl (c): running = 0; break; case ctl (f): while (--arg>=0) { if (curcol < MAXCOLS - 1) curcol++; else error ("The table can't be any wider"); while(hidden_col[curcol]&&( + linelim, "%.*f", precision[curcol],p -> v); linelim = strlen (line); } } break; } else if ('0' <= c && c <= '9' && (linelim < 0 || edistate >= 0)) { if (edistate != 0) { if (c == '0') /* just a '0' goes to left col */ curcol = 0; else { nedistate = 0; narg = c - '0'; } } else { nedistate = 0; narg = arg * 10 + (c - '0'); } } else if (linelim >= 0) { line[linelim++] = c; line[linelim] = 0; } else switch (c) { case '.': nedistate = 1; break; case ':': break; /* Be nice to vi users */ case '=': sprintf(line,"let %s%d = ",coltoa(curcol),currow); linelim = strlen (line); break; case '/': switch (nmgetch()) { case 'c': sprintf(line,"copy [to] %s%d [from] ", coltoa(curcol), currow); linelim = strlen(line); break; case 'x': sprintf(line,"erase [v:v] "); linelim = strlen(line); b sprintf (line, "merge [database from] \""); linelim = strlen (line); break; case 'G': sprintf (line, "get [database from] \""); if (*curfile) error("default file is '%s'",curfile); linelim = strlen (line); break; case 'W': sprintf (line, "write [listing to] \""); linelim = strlen (line); break; case 'T': /* tbl output */ sprintf (line, "tbl [listing to] \""); linelim = strlen (line); break; case 'i': reak; case 'f': sprintf(line,"fill [v:v start inc] "); linelim = strlen(line); break; default: error("Invalid region operation"); } break; case '$': curcol = MAXCOLS - 1; while (!tbl[currow][curcol] && curcol > 0) curcol--; break; case '#': currow = MAXROWS - 1; while (!tbl[currow][curcol] && currow > 0) currow--; break; case '^': currow = 0; break; case '?': help (); break;  switch (get_qual()) { case 'r': insertrow(arg); break; case 'c': insertcol(arg); break; default: error("Invalid insert command"); break; } break; case 'd': switch (get_qual()) { case 'r': deleterow(arg); break; case 'c': deletecol(arg); break; default: error("Invalid delete command"); break; } break; case 'v': switch (get_qual()) { case 'r': rowvalueize(a case '"': sprintf (line, "label %s%d = \"", coltoa(curcol), currow); linelim = strlen (line); break; case '<': sprintf (line, "leftstring %s%d = \"", coltoa(curcol), currow); linelim = strlen (line); break; case '>': sprintf (line, "rightstring %s%d = \"", coltoa(curcol), currow); linelim = strlen (line); break; case 'e': editv (currow, curcol); break; case 'E': edits (currow, curcol); rg); modflg++; break; case 'c': colvalueize(arg); modflg++; break; default: error("Invalid value command"); break; } break; case 'p': { register qual; qual = get_qual(); while (arg--) pullcells(qual); break; } case 'x': { register struct ent **p; register int c; flush_saved(); for (c = curcol; arg-- && c < MAXCOLS; c++) { p = &tbl[currow][c]; if (*p) { break; case 'f': sprintf (line, "format [for column] %s [is] ", coltoa(curcol)); error("Current format is %d %d", fwidth[curcol],precision[curcol]); linelim = strlen (line); break; case 'g': sprintf (line, "goto [v] "); linelim = strlen (line); break; case 'P': sprintf (line, "put [database into] \""); if (*curfile) error("default file is '%s'",curfile); linelim = strlen (line); break; case 'M':  free_ent(*p); *p = 0; } } sync_refs(); FullUpdate++; } break; case 'Q': case 'q': running = 0; break; case 'h': while (--arg>=0) { if (curcol) curcol--; else error ("At column A"); while(hidden_col[curcol] && curcol) curcol--; } break; case 'j': while (--arg>=0) { if (currow < MAXROWS - 1) currow++; else error ("The table can' t be any longer"); while (hidden_row[currow]&&(currow=0) { if (currow) currow--; else error ("At row zero"); while (hidden_row[currow] && currow) currow--; } break; case 'l': while (--arg>=0) { if (curcol < MAXCOLS - 1) curcol++; else error ("The table can't be any wider"); while(hidden_col[curcol]&&(curcol flags = p -> flags; n -> v = p -> v; n -> expr = copye(p->expr, currow - savedrow, c (SIGFPE, quit); signal(SIGBUS, quit); } quit() { move (LINES - 1, 0); clrtoeol(); refresh(); nocbreak(); nl(); echo(); resetkbd(); endwin(); exit(1); } modcheck(endstr) char *endstr; { if (modflg && curfile[0]) { char ch, lin[100]; move (0, 0); clrtoeol (); sprintf (lin,"File '%s' is modified, save%s? ",curfile,endstr); addstr (lin); refresh(); ch = nmgetch(); if (ch != 'n' && ch != 'N') if (writefile(curfile) < 0) return (1); else if (ch == - savedcol); n -> label = 0; if (p -> label) { n -> label = malloc((unsigned)(strlen(p->label)+1)); strcpy (n -> label, p -> label); } } break; } case 'z': switch (get_qual()) { case 'r': hiderow(arg); break; case 'c': hidecol(arg); break; default: error("Invalid zap command"); break; } break; case 's': switch (get_qual()) { case 'r': rowshow_op(); break; cctl (g) || ch == ctl([)) return(1); } else if (modflg) { char ch, lin[100]; move (0, 0); clrtoeol (); sprintf (lin,"Do you want a chance to save the data? "); addstr (lin); refresh(); ch = nmgetch(); if (ch == 'n' || ch == 'N') return(0); else return(1); } return(0); } writefile (fname) char *fname; { register FILE *f; register struct ent **p; register r, c; char save[1024]; if (*fname == 0) fname = &curfile[0]; strcpy(save,fname); f = fopen (fnamase 'c': colshow_op(); break; default: error("Invalid show command"); break; } break; case 'a': switch (get_qual()) { case 'r': while (arg--) duprow(); break; case 'c': while (arg--) dupcol(); break; default: error("Invalid add row/col command"); break; } break; default: if ((c & 0177) != c) error("Weird character, decimal '%d'.\n", (int) c); else error ("No suce, "w"); if (f==0) { error ("Can't create %s", fname); 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; clabel) 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); strcpy(curfile,save); modflg = 0; error("File '%s' written.",curfile); return (0); } readfile (fname,eraseflg) char *fname; int eraseflg; { register FILE *f; char save[1024]; if (*fname == 0) fname = &curfile[0]; strcpy(save,,_ ,` sc.docbond "- ʀ ʔ ʜ-- ʘZd ʘ  Cc"fname); if (eraseflg && strcmp(fname,curfile) && modcheck(" first")) return; f = fopen (save, "r"); if (f==0) { error ("Can't read %s", save); return; } if (eraseflg) erasedb (); while (fgets(line,sizeof line,f)) { linelim = 0; if (line[0] != '#') yyparse (); } fclose (f); linelim = -1; modflg++; if (eraseflg) { strcpy(curfile,save); modflg = 0; } EvalAll(); } erasedb () { register r, c; for (c = 0; c<=maxcol; c++) { fwidth[c] = DEFWIDT.TH SC 1 .SH NAME pname \- spread sheet calculator .SH SYNOPSIS .B pname [ .I file ] .SH DESCRIPTION The spread sheet calculator .I pname is based on rectangular tables, in much the same style as Visicalc or Lotus 123. When it is invoked it presents you with an empty table organized as rows and columns of cells. Each cell may have a label string associated with it and an expression. The expression may be a constant or it may compute something based on other entries. When \fIpname\fR is running, the scrH; precision[c] = DEFPREC; } for (r = 0; r<=maxrow; r++) { register struct ent **p = &tbl[r][0]; for (c=0; c++<=maxcol; p++) if (*p) { if ((*p)->expr) efree ((*p) -> expr); if ((*p)->label) free ((*p) -> label); free ((char *)*p); *p = 0; } } maxrow = 0; maxcol = 0; FullUpdate++; } #if DEBUG debugout(g,fmt,args) FILE *g; char *fmt; { int op; if (g == 0) g = fopen("debug","a"),op = 1; if (g == 0) return; _doprnt(fmt, &args, g); fflush(g); een is divided into four regions. The top line is for entering commands. The second line is for messages from \fIpname\fR. The third line and the first four columns show the row and column numbers. The rest of the screen forms a window looking at the table. The screen has two cursors: a cell cursor (indicated by a '<' on the screen) and a character cursor (indicated by the terminal's hardware cursor). The cell and character cursors are often the same. They will differ when a command is being typed on the  if (op) fclose(g); } #endif reak; default: error("Invalid show command"); break; } break; case 'a': switch (get_qual()) { case 'r': while (arg--) duprow(); break; case 'c': while (arg--) dupcol(); break; default: error("Invalid add row/col command"); break; } break; default: if ((c & 0177) != c) error("Weird character, decimal '%d'.\n", (int) c); else error ("No suctop line. Commands which use the terminal's control key such as ^N will work both when a command is being typed and when in normal mode. The cursor control commands and the row, column commands can be prefixed by a numeric argument indicating how many times the command is to be executed. "^U" can be used before the number if the number is to be entered while a command is being typed into the command line. Cursor control commands: .IP ^N Move the cell cursor to the next row. .IP ^P Move the cell curso!r to the previous row. .IP ^F Move the cell cursor forward one column. .IP ^B Move the cell cursor backward one column. .IP ^H Backspace one character. .IP "h, j, k, l" Alternate cursor controls (left, down, up, right). .IP "Arrow Keys" The terminal's arrow keys provide another alternate set of cell cursor controls if they exist and are supported in the .I termcap entry. Some terminals have arrow keys which conflict with other control key codes. For example, a terminal could send ^H when the back arrofact that the command line starts out with the old string. .IP m Mark a cell to be used as the source for the copy command. .IP c Copy the last marked cell to the current cell, updating the row and column references. .IP ^T Toggle cell display. The current cell's contents are displayed in line one when no command being entered or edited. ^T turns the display on or off. .PP File operations .IP G Get a new database from a file. .IP P Put the current database into a file. .IP W Write a listing of thew key is depressed. In these cases, the conflicting arrow key performs the same function as the key combination it mimics. .IP 0 Move the cell cursor to column 0 of the current row. .IP $ Move the cell cursor to the last valid column in the current row. .IP ^ Move the cell cursor to row 0 of the current column. .IP # Move the cell cursor to the last valid row in the current column. .IP g Go to a cell. The program will prompt for the name of a cell. Enter a cell number such as "a0" or "ae122". .PP C current database in a form that matches its appearance on the screen. This differs from the "put" command in that "put"s files are intended to be reloaded with "get", while "write" produces a file for people to look at. .IP T Write a listing of the current database to a file, but put ":"s between each field. This is useful for tables that will be further formatted by the .I tbl preprocessor of .I nroff. .IP M Merges the database from the named file into the current database. Values, expressions and nell entry and editing commands: .IP = Prompts for an expression which will be evaluated dynamically to produce a value for the cell pointed at by the cell cursor. This may be used in conjunction with ^V to make one entries value be dependent on anothers. .IP """ Enter a label for the current cell. .IP < Enter a label that will be flushed left against the left edge of the cell. .IP > Enter a label that will be flushed right against the right edge of the cell. .IP x Clears the current cell. You may preames defined in the named file are written into the current file, overwriting the existing entries at those locations. .PP Row and Column operations. Members of this class of commands can be used on either rows or columns. The second letter of the command is either a column designator (one of the characters c, j, k, ^N, ^p) or a row designator (one of r, l, h, ^B, ^F). Commands which move or copy cells also modify the variable references in affected cell expressions. Variable references may be frozen bfix this command with a count of the number of cells on the current row to clear. Cells cleared with this command may be recalled with any of the variations of the pull command. .IP e Edit the value associated with the current cell. This is identical to '=' except that the command line starts out containing the old value or expression associated with the cell. .IP E Edit the string associated with the current cell. This is the same as either "leftstring", "rightstring", or "label", with the additional y using the "fixed" operator. .IP "ar, ac" Creates a new row (column) immediately following the current row (column). It is initialized to be a copy of the current one. .IP "dr, dc" Delete this row (column). .IP "pr, pc, pm" Pull deleted rows (columns) back into the spread sheet. The last deleted set of cells is put back into the spread sheet at the current location. .I Pr inserts enough rows to hold the data. .I Pc inserts enough columns to hold the data. .I Pm (merge) does not insert rows or columns. !It overwrites the cells beginning at the current cursor location. .IP "ir, ic" Insert a new row (column) by moving the row (column) containing the cell cursor, and all following, down (right) one. The new position will be empty. .IP "zr, zc" Hide ("zap") the current row (column). This keeps a row or column from being displayed but keeps it in the data base. .IP "vr, vc" Removes expressions from the affected rows (columns), leaving only the values which were in the cells before the command was executed.y of the current command. .IP "^R or ^L" Redraw the screen. .IP ^V Types, in the command line, the name of the cell referenced by the cell cursor. This is used when typing in expressions which refer to entries in the table. .IP ^E Types, in the command line, the expression of the cell referenced by the cell cursor. .IP ^A Types, in the command line, the value of the cell referenced by the cell cursor. .PP Expressions that are used with the '=' and 'e' commands have a fairly conventional syntax. Terms .IP "sr, sc" Show hidden rows (columns). Type in a range of rows or columns to be revealed. The command default is the first range of rows or columns currently hidden. .IP f Sets the output format to be used for printing the numbers in each cell in the current column. Type in two numbers which will be the width in characters of a column and the number of digits which will follow the decimal point. Note that this command has only a column version and does have a second letter. .PP Region Operations:  may be variable names (from the ^V command), parenthesised expressions, negated terms, and constants. Rectangular regions of the screen may be operated upon with '@' functions such as sum (@sum), average (@avg) and product (@prod). Terms may be combined using many binary operators. Their precedences (from highest to lowest) are: ^; *,/; +,-; <,=,>,<=,>=; &; |; ?. .TP 15 e+e Addition. .TP 15 e-e Subtraction. .TP 15 e*e Multiplication. .TP 15 e/e Division. .TP 15 e^e Exponentiation. .TP 15 @sum(v:v) Region commands affect a rectangular region on the screen. All of the commands in this class start with a slash; the second letter of the command indicates which command to do. The program will prompt for needed paramters. Phrases surrounded by square brackets in the prompt are informational only and may be erased with the backspace key. .IP "/x" Clear a region. Cells cleared with this command may be recalled via any of the pull row or column commands. .IP "/c" Copy a region to the area starting at tSum all valid (nonblank) entries in the region whose two corners are defined by the two variable (cell) names given. .TP 15 @avg(v:v) Average all valid (nonblank) entries in the region whose two corners are defined by the two variable (cell) names given. .TP 15 @prod(v:v) Multiply together all valid (nonblank) entries in the region whose two corners are defined by the two variable (cell) names given. .TP 15 e?e:e Conditional: If the first expression is true then the value of the second is returned, otherhe current cell. .IP "/f" Fill a region with constant values. The start and increment numbers may be positive or negative. .PP Miscellaneous commands: .IP q Exit from \fIpname\fR. If you were editing a file, and you modified it, then \fIpname\fR will ask about saving before exiting. If you aren't editing a file and haven't saved the data you entered, you will get a chance to save the data before you exit. .IP ^C Alternate exit command. .IP ? Types a brief helpful message. .IP "^G or ESC" Abort entrwise the value of the third is. .TP 15 <,=,>,<=,>= Relationals: true iff the indicated relation holds. .TP 15 &,| Boolean connectives. .TP 15 fixed To make a variable not change automatically when a cell moves, put the word \*(lqfixed\*(rq in front of the reference. I.e. B1*fixed C3 .PP Assorted math functions. Most of these are standard system functions more fully described in .I math(3). All of them operate on floating point numbers (doubles); the trig functions operate with angles in radians. .TP "15 @exp(expr) Returns exponential function of . .TP 15 @ln(expr) Returns the natural logarithm of . .TP 15 @log(expr) Returns the base 10 logarithm of . .TP 15 @pow(expr1,expr2) Returns raised to the power of . .TP 15 @floor(expr) Returns returns the largest integer not greater than . .TP 15 @ceil(expr) Returns the smallest integer not less than . .TP 15 @hypot(x,y) Returns SQRT(x*x+y*y), taking precautions against unwarranted overflows. .TP 15 @fabs(expr)  sc.hbond "- ʀ ʔ ʜ-- ʘZd ʘ  Ch" Returns the absolute value |expr|. .TP 15 @sin(expr), @cos(expr), @tan(expr) Return trigonometric functions of radian arguments. The magnitude of the arguments are not checked to assure meaningful results. .TP 15 @asin(expr) Returns the arc sin in the range -pi/2 to pi/2 .TP 15 @acos(expr) Returns the arc cosine in the range 0 to pi. .TP 15 @atan(expr) Returns the arc tangent of in the range -pi/2 to pi/2. .TP 15 @dtr(expr) Converts in degrees to radians. .TP 15 @rtd(expr) Converts in radians to degrees. .TP 15 pi A constant quite close to pi. .TP 15 @max(expr1,expr2) Returns the largest value of the two expressions. .TP 15 @min(expr1,expr2) Returns the smallest value of the two expressions. .TP 15 @gamma(expr1) Returns the natural log of the gamma function. .SH SEE ALSO bc(1), dc(1) .SH BUGS Expression reevaluation is done in the same top-to-bottom, left-to-right manner as is done in other spread sheet calculators. This is silly. A proper following of the dependency graph } e; }; /* op values */ #define O_VAR 'v' #define O_CONST 'k' #define O_REDUCE(c) (c+0200) #define ACOS 0 #define ASIN 1 #define ATAN 2 #define CEIL 3 #define COS 4 #define EXP 5 #define FABS 6 #define FLOOR 7 #define HYPOT 8 #define LOG 9 #define LOG10 10 #define POW 11 #define SIN 12 #define SQRT 13 #define TAN 14 #define DTR 15 #define RTD 16 #define MIN 17 #define MAX 18 /* flag values */ #define is_valid 0001 #define is_changed 0002 #define is_lchanged 0004 #define is_leftflush 0010 #de with (perhaps) recourse to relaxation should be implemented. At most 200 rows and 40 columns. may be positive or negative. .PP Miscellaneous commands: .IP q Exit from \fIpname\fR. If you were editing a file, and you modified it, then \fIpname\fR will ask about saving before exiting. If you aren't editing a file and haven't saved the data you entered, you will get a chance to save the data before you exit. .IP ^C Alternate exit command. .IP ? Types a brief helpful message. .IP "^G or ESC" Abort entrfine is_deleted 0020 #define ctl(c) ('c'&037) struct ent *tbl[MAXROWS][MAXCOLS]; int strow, stcol; int currow, curcol; int savedrow, savedcol; int FullUpdate; int maxrow, maxcol; int fwidth[MAXCOLS]; int precision[MAXCOLS]; char hidden_col[MAXCOLS]; char hidden_row[MAXROWS]; char line[1000]; int linelim; int changed; struct ent *to_fix; struct enode *new(); struct enode *new_const(); struct enode *new_var(); struct ent *lookat(); struct enode *copye(); char *coltoa(); int modflg; les in radians. .TP ">{ >| sc.manbond "- ʀ ʔ ʜ-- ʘZd ʘ  Cn" a numeric argument indicating how many times the command is to be executed. "^U" can be used before the number if the number is to be entered while a command is being typed into the command line. Cursor control commands: ^N Move the cell cursor to the next row. ^P Move the cell cursor to the previous row. ^F Move the cell cursor forward one column. ^B Move the cell cursor backward one column. Page 1  SC(1) UNIX 3.0 SC(1) NAME sc - spread sheet calculator SYNOPSIS sc [ _f_i_l_e ] DESCRIPTION The spread sheet calculator _s_c is based on rectangular tables, in much the same style as Visicalc or Lotus 123. When it is invoked it presents you with an empty table organized as rows and columns of cells. Each cell may have a label string associated with it and an  (printed 1/26/87) SC(1) UNIX 3.0 SC(1) ^H Backspace one character. h, j, k, l Alternate cursor controls (left, down, up, right). Arrow Keys The terminal's arrow keys provide another alternate set of cell cursor controls if they exist and are supported in the _t_e_r_m_c_a_p entry. Some terminals have arrow kexpression. The expression may be a constant or it may compute something based on other entries. When _s_c is running, the screen is divided into four regions. The top line is for entering commands. The second line is for messages from _s_c. The third line and the first four columns show the row and column numbers. The rest of the screen forms a window looking at the table. The screen has two cursors: a cell cursor (indeys which conflict with other control key codes. For example, a terminal could send ^H when the back arrow key is depressed. In these cases, the conflicting arrow key performs the same function as the key combination it mimics. 0 Move the cell cursor to column 0 of the current row. $ Move the cell cursor to the last valid column in the current row. ^ Move the cell cursor ticated by a '<' on the screen) and a character cursor (indicated by the terminal's hardware cursor). The cell and character cursors are often the same. They will differ when a command is being typed on the top line. Commands which use the terminal's control key such as ^N will work both when a command is being typed and when in normal mode. The cursor control commands and the row, column commands can be prefixed byo row 0 of the current column. # Move the cell cursor to the last valid row in the current column. g Go to a cell. The program will prompt for the name of a cell. Enter a cell number such as "a0" or "ae122". Cell entry and editing commands: = Prompts for an expression which will be evaluated dynamically to produce a value for the cell pointed at by the cell cursor. This may be used in conj#unction with ^V to make one entries value be dependent on anothers. " Enter a label for the current cell. < Enter a label that will be flushed left against the left edge of the cell. Page 2 (printed 1/26/87) SC(1) UNIX 3.0 SC(1) > Enter a label that will be flushed right against the right edge of thles are intended to be reloaded with "get", while "write" produces a file for people to look at. Page 3 (printed 1/26/87) SC(1) UNIX 3.0 SC(1) T Write a listing of the current database to a file, but put ":"s between each field. This is useful for tables that will be further formatted by the _t_b_l preprocese cell. x Clears the current cell. You may prefix this command with a count of the number of cells on the current row to clear. Cells cleared with this command may be recalled with any of the variations of the pull command. e Edit the value associated with the current cell. This is identical to '=' except that the command line starts out containing the old value or expression associatedsor of _n_r_o_f_f. M Merges the database from the named file into the current database. Values, expressions and names defined in the named file are written into the current file, overwriting the existing entries at those locations. Row and Column operations. Members of this class of commands can be used on either rows or columns. The second letter of the command is either a column designator (o with the cell. E Edit the string associated with the current cell. This is the same as either "leftstring", "rightstring", or "label", with the additional fact that the command line starts out with the old string. m Mark a cell to be used as the source for the copy command. c Copy the last marked cell to the current cell, updating the row and column references. ne of the characters c, j, k, ^N, ^p) or a row designator (one of r, l, h, ^B, ^F). Commands which move or copy cells also modify the variable references in affected cell expressions. Variable references may be frozen by using the "fixed" operator. ar, ac Creates a new row (column) immediately following the current row (column). It is initialized to be a copy of the current one. dr, dc  ^T Toggle cell display. The current cell's contents are displayed in line one when no command being entered or edited. ^T turns the display on or off. File operations G Get a new database from a file. P Put the current database into a file. W Write a listing of the current database in a form that matches its appearance on the screen. This differs from the "put" command in that "put"s fi Delete this row (column). pr, pc, pm Pull deleted rows (columns) back into the spread sheet. The last deleted set of cells is put back into the spread sheet at the current location. _P_r inserts enough rows to hold the data. _P_c inserts enough columns to hold the data. _P_m (merge) does not insert rows or columns. It overwrites the cells beginning at the current cursor #location. ir, ic Insert a new row (column) by moving the row (column) containing the cell cursor, and all following, down (right) one. The new position will be empty. zr, zc Hide ("zap") the current row (column). This keeps a row or column from being displayed but keeps it in the Page 4 (printed 1/26/87) SC(1) UNIX 3.0 ill a region with constant values. The start and increment numbers may be positive or negative. Miscellaneous commands: q Exit from _s_c. If you were editing a file, and you modified it, then _s_c will ask about saving before exiting. If you aren't editing a file and haven't saved the data you entered, you will get a chance to save the data before you exit. Page 5  SC(1) data base. vr, vc Removes expressions from the affected rows (columns), leaving only the values which were in the cells before the command was executed. sr, sc Show hidden rows (columns). Type in a range of rows or columns to be revealed. The command default is the first range of rows or columns currently hidden. f Sets the output format to (printed 1/26/87) SC(1) UNIX 3.0 SC(1) ^C Alternate exit command. ? Types a brief helpful message. ^G or ESC Abort entry of the current command. ^R or ^L Redraw the screen. ^V Types, in the command line, the name of the cell referenced by the cell cursor. This is used when typing in expressions which refer to ent be used for printing the numbers in each cell in the current column. Type in two numbers which will be the width in characters of a column and the number of digits which will follow the decimal point. Note that this command has only a column version and does have a second letter. Region Operations: Region commands affect a rectangular region on the screen. All of the commands in this class start witries in the table. ^E Types, in the command line, the expression of the cell referenced by the cell cursor. ^A Types, in the command line, the value of the cell referenced by the cell cursor. Expressions that are used with the '=' and 'e' commands have a fairly conventional syntax. Terms may be variable names (from the ^V command), parenthesised expressions, negated terms, and constants. Rectah a slash; the second letter of the command indicates which command to do. The program will prompt for needed paramters. Phrases surrounded by square brackets in the prompt are informational only and may be erased with the backspace key. /x Clear a region. Cells cleared with this command may be recalled via any of the pull row or column commands. /c Copy a region to the area starting at the current cell. /f Fngular regions of the screen may be operated upon with '@' functions such as sum (@sum), average (@avg) and product (@prod). Terms may be combined using many binary operators. Their precedences (from highest to lowest) are: ^; *,/; +,-; <,=,>,<=,>=; &; |; ?. e+e Addition. e-e Subtraction. e*e Multiplication. e/e Division. e^e Exponentiation. Pa$ge 6 (printed 1/26/87) SC(1) UNIX 3.0 SC(1) @sum(v:v) Sum all valid (nonblank) entries in the region whose two corners are defined by the two variable (cell) names given. @avg(v:v) Average all valid (nonblank) entries in the region whose two corners are defined by the two variabl SC(1) @floor(expr) Returns returns the largest integer not greater than . @ceil(expr) Returns the smallest integer not less than . @hypot(x,y) Returns SQRT(x*x+y*y), taking precautions against unwarranted overflows. @fabs(expr) Returns the absolute value |expr|. @sin(expr), @cos(expr), @tan(expr) Return trigone (cell) names given. @prod(v:v) Multiply together all valid (nonblank) entries in the region whose two corners are defined by the two variable (cell) names given. e?e:e Conditional: If the first expression is true then the value of the second is returned, otherwise the value of the third is. <,=,>,<=,>= Relationals: true iff the indometric functions of radian arguments. The magnitude of the arguments are not checked to assure meaningful results. @asin(expr) Returns the arc sin in the range -pi/2 to pi/2 @acos(expr) Returns the arc cosine in the range 0 to pi. @atan(expr) Returns the arc tangent of in the range -pi/2 to pi/2. @dtr(expr) Converts in degrees to radiicated relation holds. &,| Boolean connectives. fixed To make a variable not change automatically when a cell moves, put the word fixed in front of the reference. I.e. B1*fixed C3 Assorted math functions. Most of these are standard system functions more fully described in _m_a_t_h(_3). All of them operate on floating point numbers (doubles); the trig ans. @rtd(expr) Converts in radians to degrees. pi A constant quite close to pi. @max(expr1,expr2) Returns the largest value of the two expressions. @min(expr1,expr2) Returns the smallest value of the two expressions. @gamma(expr1) Returns the natural log of the gamma Page 8 (pr functions operate with angles in radians. @exp(expr) Returns exponential function of . @ln(expr) Returns the natural logarithm of . @log(expr) Returns the base 10 logarithm of . @pow(expr1,expr2) Returns raised to the power of . Page 7 (printed 1/26/87) SC(1) UNIX 3.0 inted 1/26/87) SC(1) UNIX 3.0 SC(1) function. SEE ALSO bc(1), dc(1) BUGS Expression reevaluation is done in the same top-to-bottom, left-to-right manner as is done in other spread sheet calculators. This is silly. A proper following of the dependency graph with (perhaps) recourse to relaxation should be implemented. At most 200 rows and 40$ columns. Page 9 (printed 1/26/87) SC(1) @sum(v:v) Sum all valid (nonblank) entries in the region whose two corners are defined by the two variable (cell) names given. @avg(v:v) Average all valid (nonblank) entries in the region whose two corners are defined by the two variabl a ;Makefileextralibs "- ʀ ʔ ʜ-- ȰZd Ȱ  Ce"1 2 sres.sedbond "- ʀ ʔ ʜ-- ʘZd ʘ  Cd"# Makefile 4.1 83/06/27 # DESTDIR= CFLAGS= +Ow +DPEGASUS +DCM_N +DCM_GT +DCM_B +DCM_D termcap: termcap.r tgoto.r tputs.r libgen n=termcap u=termcap.r u=tgoto.r u=tputs.r clean: -remove *.r -remove termcap install: termcap move termcap ${DESTDIR}/lib/termcap perms u+rw o+r o-w ${DESTDIR}/lib/termcap remove ${DESTDIR}/lib/termlib +q link ${DESTDIR}/lib/termcap ${DESTDIR}/lib/termlib otherwise the value of the third is. <,=,>,<=,>= Relationals: true iff the ind/%token.*S_/!d /%token.*S_\(.*\)/s// "\1", S_\1,/ ultiply together all valid (nonblank) entries in the region whose two corners are defined by the two variable (cell) names given. e?e:e Conditional: If the first expression is true then the value of the second is returned, otherwise the value of the third is. <,=,>,<=,>= Relationals: true iff the inda  rJ/ 7cursesextralibs "- ʀ ʔ ʜ-- ȰZd Ȱ  Cs"2v ? ;extralibssres- VONVH0*n4-H.4H,4-H¼l4-H¾lJmJlp`\.HH `$DP,$SJgt .HUNXJfp` `p`.N9f~`~`Sl~`4- Hg$ m"p(1x.gj$Ԃ m p(f$Ԃ m1($Ԃ"m3((`>$Ԃ m40(H¾l$Ԃ m1(`$Ԃ m40(H¾o $Ԃ m1((mg4-H2,HDԁDԆ*4- H2, HDԁDԇ(4,Hºl4,H¸lJmJm$ l"p(1H.gj$Ԃ l p(f$Ԃ l%1($Ԃ"l3((`>$Ԃ l40(H¸l$Ԃ l1(`$Ԃ l40(H¸o $Ԃ l1((l`$$ m"R"p(4-H¾m*~4-HRn-fp`D.N.NS`(Q b6@ |00N$$;G:pL0N^NujA _wclrtoeol_NONLX _wrefresh`_scrollxA _waddchaddch.c>NVH0*n(n gHH.HUNXJfp``pL0N^Nu"_waddch _waddstraddstr.cP` t .N.Jg..t//9NP` t .N.S`t#$9Sl&$9SDԹDչ $9S#$9S l.9 $9S# $9So*,9J9f9ft#N\#$9SoHJg"9g..t//9NP` t .N.SJ9ft#`$9 l"9fJgp`pf # 9gR. /9/9NP*@.N.N,Jo t.N,`..t/HUNP` t.N,# #L N^NuNV$9gS` .NNVH8*n4-H*4-HS, m(P$ m&p(~oxxxR`S~m&$ m"p(X$ m p(XR`-f4- Hgt XX.NL8N^Nu _touchwin _boxbox.cJUNVH *nf.N.N`.NtBpL N^Nu_curscr_stdscrA$_stdscr* _wrefresh4_werase _wclearclear.c.N^NuNVH##(9&9Jg|9g t./9NX$9Ђ.`.9$9mH$9"9Dԁ,9g$gt./9NX܀`$9,`8$9m"9fJg$9,.`$R,$9 *JlD*܅$Թ n$9f6$9 l(. t//9NPt##`ZJgR$9S *ԇTo:JoJg.. t//9NPt#$9S#`$9f$9 lp`9g $9r./9NXԀ.`.9$9 NVH<*n4-H,4H.4-H¾lz$ m2-HҰ(&A$ m$0(Ԇ(Bo(  g$L f$ m" (*t R` gh$Ԃ m40(Hºm$Ԃ m p(f $Ԃ m1($ m" ($Ԃ m40(H²o$ m" ($Ԃ m1(|R`,BUBmLJmDSJg. t//9NP` t.N `$9 o*S. t//9NPJm`9g$9 o` gh$Ԃ m40(Hºm$Ԃ m p(f $Ԃ m1($ m" ($Ԃ m40(H²o$ m" ($Ԃ m1(L__iobL_fputch_COLSpx_COLS~ldiv_COLSlmod_COLSƀ_COLS΀ldivހ_COLSlmod_AM__pfast _CRA_CR$_tputs2A8_NL@AJ_NLP_tputs^Ajp_LINESx_LINA_UP_tputs_GT,2A<D_TALAV_TA\_tputsjApx~_COLS_BC_BS_TAA_TA€_tputsA_BCA_BC_tputsA$.__win6>F_curscrLXl_curscr__iob_fputc_NDA_ND_tputsES_LINES_LINES_LINES̀_LINES__pfast_CAA_LINES_NL__pfast"A,_NL2_tputs@AH__pfastRZ`h_CAp_UP_CA_CM_tgoto_strlenAAAڀ_tputsA$A:@A _COLS _COLS ldiv $_COLS ,lmul Nlmod _mvcur. __putchar\ _fgoto _plodput, _plod _tabcolcr_put.c$<  UNV./9NXJl`./9NX9#./9NXJl $99B39#9fp`p9gp`p9DJPV_HO`_GTlrlmodz_GTȀlmod_BS_BC "6@_UPHNVA`_HOf_tputspv~_LL_LINES_UPA_LL_tputsʀ_LINESڀ_UP_GT lmod$*gp`p9./9NXN^NuNVH *nJf*|~./<NX gR./<NXJf.N# nt#Jf.N# ntP##NV. /9/9N @P OfB9t#`tJg yHH`p#./<NX./<NX$gp`pL N^NuNVH8(|*|.NX mTf(|&|,X.HTNX k Tf.6NJot#.9N2_NONL:__pfastBHR_NCZ`rx_BS_BC_CRA_CR_tputsA_NCȀ_NLAڀ_NL_tputsA_NL__pfast&A0_NL6_tputsDAJT_NONL\__pfastfn_BTv_BT|_strlen_BCA_BC_tputsAJot#$9fJg##L8N^NuNV./.NXN^Nuxxxx|dumb:licoambseohzinmimsncosulxnalbcbtcdceclcmcrdcdldmdoedeihoicimipllmandnlpcsesfsosrtatetiucueupusvbvsvesgug_AM_BS_EO _HZ_IN_MI_MS_NC _OS$_UL&(_XN,_AL0_BC4_BT8_CD<_CE@_CLD_CMH_CRL_DCP_DLT_DMX_DO\_ED`_EId_HOh_ICl_IMp_IPt_LLx_MA|_ND_NL_SE_SF_SO_SR_TA_TE_TI_UC_UE_UP_US_VB_VS_VE__tty __tty_ch_gtty"__tty(__tty_ch._gtty6__ttyXN+ _NONL, _UPPERCASE- _normtty. __pfast0 _AL4 _BC8 _BT< _CD@ _CED _CLH _CML _CRP _DCT _DLX _DM\ _DO` _EDd _EIh _HOl _ICp _IMt _IPx _LL| _MA _ND _NL _SE _SF _SO _SR _TA _TE _TI _UC _UE _UP _US _B __res_flgH__ttyN__tty_chT_stty` __res_flgf__ttyl__ttyv|__tty __res_flg__tty _UPPERCASE__ttyȀ_GT΀__tty_NONL__tty__tty__tty_ch_stty *0_tgetentBHN_strcpyV_LINES^d_tgetnumj_LINESt_LINES~_LINES_COLS_tgetnum_COLS_COLS_COLSVB _VE _VS _PCcurses.cNVH<*n4H m2-HSҰ($A4H m2-HҰ((A$ R&Bo`t 4-HS2Hҁ m14HԂ m p(g4HԂ m40(mo4HԂ m1(pL<N^Nu _wdelchdelch.c NVH8*n4H m(p(4H.4-HSl<$ m"R"m!($Ԃ mBp(4-HS"ҁ m1R`4-HԌ&Bot `4-HS m2-HA΀_CMԀ_tgoto_CA_CM_CA_PC&, _longname6_ttytype<_strcpybhp _tgetflag_tgetstr_tgetnum_SÒ_tgetnum؀_USހ_SO_US_US_SO_UE_SE_tgetstr _ospeed _gettmode _settermV _zap _getcapcr_tty.cDҌ!(L8N^Nu _wdeletelndeleteln.cINVH8*nJ"f>~4-H¾l$ mJ(g NR`(mg&l.N(K``(mgNq(l`)mNNNNL8N^Nu0_freeHAl_freer_freex_free~_free _delwindelwin.cNV$9./9NX.t//9NP.t//9NPJg> ytek4404 __echoit __rawmode _My_term __endwin _ttytype _Def_term __tty_ch _LINES _COLS __res_flg _stdscr _curscr __tty _AM _BS _CA _DA _DB! _EO" _GT# _HZ$ _IN% _MI& _MS' _NC( _OS) _UL* _4( Hg$.t//9NP yh tN^Nu __res_flg __tty__tty__tty_ch_stty& __putchar0_VE6_tputs> __putcharH_TEN_tputsV_curscr^_curscrp __putcharz_SE_tputs_curscr__endwin _endwinendwin.cNVH<*n~4-H¾l|$ m$p(4-HԊ&B(Jo  g-L f$ ,t R` gl$Ԃ &m40(H¼m$Ԃ m p(f $Ԃ m1($ m".($Ԃ m40(H²o$ m".($Ԃ m1(R`>J"g m"4(H2-HDԁ& m"4( H2- HDԁ(.z4-Hºl$Ԃ m40(HԄ m""ҁ"h21Hm m"$Ԃ"h q(f $Ԃ m40(HԄ m""ҁ"h3$Ԃ m40(HԄ m""ҁ"h21Ho $Ԃ m40(HԄ m""ҁ"h3RR`NgBUBmL __sprintwp_wmove __sprintw _mvprintwR _mvwprintwmvprintw.cZ% NVH..,. .//9NP fA././9NP`pLN^NuNVH *n.. ,../HUNP fA./.HUNP`pL N^Nu_stdscr_wmove8_'stdscr>__sscansp_wmove__sscans _mvscanwR _mvwscanwmvscanw.cvGNVH *n.. ,.4-H´n4-Hԇop`44-H´n4-HԆop`;G;F .NpL N^Nu_LINES._LINES@_COLSP_COLSf _touchwin _mvwinmvwin.c^n"NVH0,.*.(.&. Jf $9(Jf $9&.///NO *@NPJfp`HH.HTNXRR`R`vLPN^NuNVA./. /.N>PN^NuNVt-BA-H-|A.Hn NXA.t/NXA./.NXN^Nu_stdscrA4Ad__fprtfv_fputc_waddstr _printw _wprintw> __sprintwprintw.c0" NVH *n9g6.t//9NP.t//9NPBNX+@f Np`t./NX+@fNNp`t./NX+@fNNNp`BmBUfgp`p@;D;C;F;E Bm B-B-~o $Ԃ m1($Ԃ"m3(R`$ԃf. Jff Jf $Ԅf L N^Nureturning ERR (2) _LINES._COLS@Ar_calloc_free_free_free_free_freeA__iob_fprintf2_callocL_callocZ_freel_call9 y3 y3BG#gp`p-f y(fJg4- Hf y(g.t//9NPByBy9f( yB( yBP yBh.N.Nt./$9S/$9S/NO B-BGmlL4H´l@4HԂ m p(g*4H.HUNXJfp`4HԂ m1(RG`f04-H.4H/49H/49H/NO `.-gp y0 y1y4-y4- yJym04-yo$Jym4-yo:;y`BmBU`4-H2Hԁ ocz_free_free_calloc_free_free_free_LINESƀ_COLS_COLS0_LINESF_LINES _newwin _subwinnewwin.c8. NVH<*n(n 4-H.4-lo0-`0,H&4- H.4- l o0- `0, H-@4-H.4-ll0-`0,HS*4- H.4-ll0-`0,HS(,m$ m$0(Ԅ$B4- HԮ.$ m$0(Ԯ&BmNH |0 HHf0.4-HԆ/HTy04- H2-Hԁ y1B y4H´m $9S0 yJPlBP y4(H´m $9S1B yJhlBh y4(H.4H/49H/49H/NO |t#.N L N^NuNVH<*n4.HԂ m>0(4-H2.H҂:4.HԂ m<0(9g&|`, y4-H2.H҂"h4- H0HЂб&@4.H m2HҰ((AJgR9fJ4.H m2-HSҰ($A  f4.H m(oS`4.H m" ((9f$y`ʼGmg4- H2H҂.4H/49H/49H/N'O 34- H2H҂3gGm g4H¸n  f y49H"h"9Sұ($A  f $ Sl`4- H y29H"h DԀ&.N$nH4-H¶l>.t//9NP4- H2H҂34RGH¶mt ``Jgz y4( HHHgVHHg&.t//9NP y `$.t//9NP yh RGmm4-HS2.Hf-g y4( Hg84- Hg,9f$.t//9NP yh 9f .H_tputs(D_SON_curscr| __putchar_SO_tputs_curscr __putchar_SE_tputs_curscr_curscr _MS __putchar_SE"_tputs*_curscr6>__iobT_fputc^__iobr_fputc|_scroll_curscr_scroll__iob_fputc__iob&_fputc._UCB__iobL_fputcT __putchar^_UCdH/NX`.HH/NX.N4- Hg9f .N4H2-Hԁ34-H2- Hԁ3p`4- HgSG3p`9f".+HH/NX`.HH/NXJg6HHg*.t/NX.t//9NPR`4- H2H҂49H´g<4- H2H҂3`$GofGmR9fRRG``R``LpLPN^NuNVA./. /.N>PN^NuNV|t-BA-H-nA./.NXJfp` A.N-@. HnNXN^Nu_stdscrA4Ab_wgetstrx_strlen__sscnf _scanw _wscanw> __sscanss __putchar"_VS(_tputs0 __putchar:_TI@_tputsH__endwinN_curscrTZ_curscrbjp_curscr~_curscr_curscr __putchar_CLƀ_tputs_curscr_curscr_curscr_curscr_werase  _touchwin_COLS"_LINES,_mvcurF_LINEShA_curscrÀ_curscr؀_curscrcanw.cHNVH8*n-fp` m&P~4-H¾l$S m""m!(R`(K4-Hԋlt `4-HS m!(SUf.t /NX9fBm.NpL8N^Nur_curscrz__iob_fputc_NONL _touchwin _scrollscroll.cn( NVH *n$9f $9fp` Jg y` y L N^NuNVH *n$9f $9fp`m"(H_curscr^_curscrh_curscrr_LINESz_LINES_curscr_curscr_COLS_COLS_curscr_curscrA__iob_fflushRZb_curscr_CE_CE2<FAPb_curscr_COLSƀ_curscr_CE_strlen __putchar_CE Jg y` y L N^Nu_SO_UC*_SO2_SO:_UCZ_SOb_UCt_SE|_SE_UC _wstandoutJ _wstandendstandout.c NVH0*n.N6(mg.N6(l`L0N^NuNVH *n4-H,4-HS*~o$Ԃ mBp($Ԃ m1(R`L N^NuA"A _touchwintouchwin.cNVN^Nu