[net.sources] VC 2.1 - Part 1 of 2

rgb@nscpdc.NSC.COM (Robert Bond) (01/06/87)

This is a new release of a public domain spread sheet calculator.  
The user interface has been completely redone; I have added lots
of new commands in a never ending attempt to satisfy our Lotus 123
users.

See the README file for machine and build details.  Part 1 contains
all of the code.  Part 2 is the documentation.

I hope it helps with the tax man.

#	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
#	sc.h
#	interp.c
#	sc.c
#	lex.c
#	cmds.c
#	gram.y
#	eres.sed
#	sres.sed
#	makefile
# This archive created: Mon Jan  5 21:40:59 1987
# By:	Robert Bond (NSC Portland, Oregon)
echo shar: extracting README '(790 characters)'
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 from 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 sc.h '(1129 characters)'
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
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_changed   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 enode *copye();
XXchar *coltoa();
XX
XXint modflg;
SHAR_EOF
if test 1129 -ne "`wc -c sc.h`"
then
echo shar: error transmitting sc.h '(should have been 1129 characters)'
fi
echo shar: extracting interp.c '(13539 characters)'
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 */
XX
XX#include "sc.h"
XX#include <stdio.h>
XX#define DEFCOLDELIM ':'
XX
XXchar *malloc();
XX
XXdouble 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 = minc; 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 struct 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) && 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->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	case '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	            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<=maxrow; 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 *)&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    if (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);
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}
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,"",-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) free(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 col;
XX{
XX    static char rname[3];
XX    register char *p = rname;
XX
XX    if (col < 0 || col > 25*26) 
XX	debug("coltoa: invalid col: %d", col);
XX
XX    if (col > 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 ':': mypriority = 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 (mypriority<priority) line[linelim++] = '(';
XX	switch (e->op) {
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			decompile (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,"%g",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:		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<priority) line[linelim++] = ')';
XX    } else line[linelim++] = '?';
XX}
XX
XXeditv (row, col) {
XX    sprintf (line, "let %s%d = ", coltoa(col), row);
XX    linelim = strlen(line);
XX    editexp(row,col);
XX}
XX
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, "%g", 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);
XX    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 (plinelim<c) pline[plinelim++] = ' ';
XX		plinelim = c;
XX		if ((*p)->flags&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 (d<pline) d = pline;
XX		    while (*s) *d++ = *s++;
XX		    if (d-pline>plinelim) plinelim = d-pline;
XX		}
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; col++, 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));
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 		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 around 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		break;
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    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 (c2 > MAXCOLS-1) {
XX	c2 = MAXCOLS-1;
XX    }
XX    FullUpdate++;
XX    while (c1 <= c2)
XX	hidden_col[c1++] = 0;
XX}
SHAR_EOF
if test 13539 -ne "`wc -c interp.c`"
then
echo shar: error transmitting interp.c '(should have been 13539 characters)'
fi
echo shar: extracting sc.c '(17780 characters)'
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 *
XX */
XX
XX
XX#include <signal.h>
XX#include <curses.h>
XX#include "sc.h"
XX
XX/* default column width */
XX
XX#define DEFWIDTH 10
XX#define DEFPREC   2
XX
XX#define RESCOL 4  /* columns reserved for row numbers */
XX#define RESROW 3  /* rows reserved for prompt, error, and column numbers */
XX
XXchar curfile[1024];
XX
XXint linelim = -1;
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    printw ("%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    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     rows;
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];
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 < LINES && 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	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	register    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[fwidth[col]] = 0;
XX		    mvaddstr (r,
XX			    (*p) -> flags & is_leftflush
XX			    ? c : c - strlen (field) + fwidth[col],
XX			    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[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
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] = DEFWIDTH;
XX	    precision[i] = DEFPREC;
XX	}
XX    }
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	signals();
XX	initscr ();
XX	clear ();
XX#ifdef BSD42
XX	raw ();
XX#endif
XX#ifdef SYSV
XX	nonl(); cbreak();
XX#endif
XX	noecho ();
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) {
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#ifdef BSD42
XX		case ctl (z):
XX		    noraw ();
XX		    echo ();
XX		    kill(getpid(),SIGTSTP);
XX
XX		    /* the pc stops here */
XX
XX		    raw ();
XX		    noecho ();
XX		    break;
XX#endif
XX		case ctl (r):
XX		    FullUpdate++;
XX		    clearok(stdscr,1);
XX		    break;
XX		default:
XX		    error ("No such command  (^%c)", c + 0100);
XX		    break;
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<MAXCOLS-1))
XX			    curcol++;
XX		    }
XX		    break;
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 (currow < 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 flow 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 (linelim > 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		} else {
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				      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			    linelim = 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			    linelim = 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);
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()) {
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(qual);
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 (curcol)
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<MAXROWS-1))
XX				    currow++;
XX			    }
XX			    break;
XX			case 'k':
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 '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<MAXCOLS-1))
XX				    curcol++;
XX			    }
XX			    break;
XX			case 'm':
XX			    savedrow = currow;
XX			    savedcol = curcol;
XX			    break;
XX			case 'c': {
XX			    register struct ent *p = tbl[savedrow][savedcol];
XX			    register c;
XX			    register struct ent *n;
XX			    if (!p)
XX				break;
XX			    FullUpdate++;
XX			    modflg++;
XX			    for (c = curcol; arg-- && c < MAXCOLS; c++) {
XX				n = lookat (currow, c);
XX				clearent(n);
XX				n -> 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);
XX				strcpy (n -> 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':
XX			    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 = modcheck(" before exiting");
XX    }				/*  while (inloop) */
XX    move (LINES - 1, 0);
XX    clrtoeol();
XX    refresh ();
XX#ifdef BSD42
XX    noraw ();
XX#endif
XX#ifdef SYSV
XX    nocbreak(); nl();
XX#endif
XX    echo ();
XX    endwin ();
XX}
XX
XXsignals()
XX{
XX    void quit();
XX    void timeout();
XX
XX    signal(SIGINT, SIG_IGN);
XX    signal(SIGQUIT, quit);
XX    signal(SIGPIPE, quit);
XX    signal(SIGTERM, quit);
XX    signal(SIGALRM, timeout);
XX}
XX
XXvoid
XXquit()
XX{
XX    move (LINES - 1, 0);
XX    clrtoeol();
XX    refresh ();
XX#ifdef BSD42
XX    noraw ();
XX#endif
XX#ifdef SYSV
XX    nocbreak(); nl();
XX#endif
XX    echo ();
XX    endwin ();
XX    exit();
XX}
XX    
XX
XXmodcheck(endstr) char *endstr; {
XX    if (modflg && curfile[0]) {
XX	char ch, lin[100];
XX
XX	move (0, 0);
XX	clrtoeol ();
XX	sprintf (lin,"File '%s' is modified, save%s? ",curfile,endstr);
XX	addstr (lin);
XX	refresh();
XX	ch = nmgetch();
XX	if (ch == 'y' || ch == 'Y') writefile(curfile);
XX	else if (ch == ctl (g)) return(1);
XX    }
XX    return(0);
XX}
XX    
XXwritefile (fname)
XXchar *fname; {
XX    register FILE *f;
XX    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<MAXCOLS; c++)
XX	if (fwidth[c] != DEFWIDTH || precision[c] != 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    modflg = 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)->label) free ((*p) -> label);
XX		free (*p);
XX		*p = 0;
XX	    }
XX    }
XX    maxrow = 0;
XX    maxcol = 0;
XX    FullUpdate++;
XX}
XX
XXdebugout(g,fmt,args) FILE *g; char *fmt; {
XX    int i,op;
XX
XX    if (g == 0) g = fopen("debug","a"),op = 1;
XX    if (g == 0) return;
XX
XX    _doprnt(fmt, &args, g);
XX
XX    fflush(g);
XX    if (op) fclose(g);
XX}
SHAR_EOF
if test 17780 -ne "`wc -c sc.c`"
then
echo shar: error transmitting sc.c '(should have been 17780 characters)'
fi
echo shar: extracting lex.c '(7536 characters)'
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
XX *
XX *              More mods Robert Bond, 12/86
XX *
XX */
XX
XX
XX
XX#include <curses.h>
XX#include <signal.h>
XX#include <setjmp.h>
XX#include "sc.h"
XX#include <ctype.h>
XX#include "y.tab.h"
XX
XXchar *strtof();
XX
XXjmp_buf wakeup;
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 () {
XX    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	    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 (i<tokenl && ((tokenst[i]^tbl->key[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	register 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    } else 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#ifdef BSD42
XX#define N_KEY 4
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
XXchar keyarea[N_KEY*10];
XX
XXchar *tgetstr();
XX
XXinitkbd()
XX{
XX    char buf[1024]; /* Why do I have to do this again? */
XX    char *p = keyarea;
XX    char *ks;
XX    int i;
XX
XX    if (tgetent(buf, getenv("TERM")) <= 0)
XX	return;
XX
XX    km[0].k_str = tgetstr("kl", &p); km[0].k_val = ctl(b);
XX    km[1].k_str = tgetstr("kr", &p); km[1].k_val = ctl(f);
XX    km[2].k_str = tgetstr("ku", &p); km[2].k_val = ctl(p);
XX    km[3].k_str = tgetstr("kd", &p); km[3].k_val = ctl(n);
XX    ks = tgetstr("ks",&p);
XX    if (ks) 
XX	printf("%s",ks);
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 = getchar() & 0x7f;
XX    biggest = 0;
XX    almost = 0;
XX
XX    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]) {
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    if (almost) { 
XX
XX        signal(SIGALRM, timeout);
XX        alarm(1);
XX
XX	if (setjmp(wakeup) == 0) { 
XX	    maybe = nmgetch();
XX	    alarm(0);
XX	    return(maybe);
XX	}
XX
XX    }
XX    
XX    if (biggest) {
XX	for (i = 0; i<biggest->k_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#endif
XX
XX#ifdef SYSV
XX
XXinitkbd()
XX{
XX    keypad(stdscr, TRUE);
XX}
XX
XXnmgetch()
XX{
XX    register int c;
XX
XX    c = getch();
XX    switch (c) {
XX    case KEY_LEFT:  c = ctl(b); break;
XX    case KEY_RIGHT: c = ctl(f); break;
XX    case KEY_UP:    c = ctl(p); break;
XX    case KEY_DOWN:  c = ctl(n); break;
XX    default:   c = c & 0x7f; 
XX    }
XX    return (c);
XX}
XX
XX#endif
XX
XXvoid
XXtimeout()
XX{
XX    longjmp(wakeup, -1);
XX}
XX
XXint dbline;
XX
XXdebug (fmt, a, b, c) {
XX	mvprintw (2+(dbline++%22),80-60,fmt,a,b,c);
XX	clrtoeol();
XX}
XX
XX/*
XX * This converts a floating point number of 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 + (double)(*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 = 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 ("                 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    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 7536 -ne "`wc -c lex.c`"
then
echo shar: error transmitting lex.c '(should have been 7536 characters)'
fi
echo shar: extracting cmds.c '(7952 characters)'
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 *              More mods Robert Bond, 12/86
XX *
XX */
XX
XX#include <curses.h>
XX#include "sc.h"
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 = lookat (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 = 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;
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, 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, 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 (c = sc; c <= ec; c++) {
XX	    p = tbl[r][c];
XX	    if (p && p->expr) {
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    mincol = MAXCOLS;
XX    maxrow = 0;
XX    maxcol = 0;
XX
XX    for (p = to_fix; p; p = p->next) {
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    } 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()
XX{
XX    register int i,j;
XX    for (i=0; i<MAXCOLS; i++)
XX	if (hidden_col[i]) 
XX	    break;
XX    for(j=i; j<MAXCOLS; j++)
XX	if (!hidden_col[j])
XX	    break;
XX    j--;
XX    if (i<MAXCOLS) {
XX	sprintf(line,"show %s:", coltoa(i));
XX	sprintf(line + strlen(line),"%s",coltoa(j));
XX	linelim = strlen (line);
XX    }
XX}
XX
XXshowrow_op()
XX{
XX    register int i,j;
XX    for (i=0; i<MAXROWS; i++)
XX	if (hidden_row[i]) 
XX	    break;
XX    for(j=i; j<MAXROWS; j++)
XX	if (!hidden_row[j]) {
XX	    break;
XX	}
XX    j--;
XX    if (i<MAXROWS) {
XX	sprintf(line,"show %d:%d", i, j);
XX        linelim = strlen (line);
XX    }
XX}
XX
XXget_qual()
XX{
XX    register int c;
XX
XX    c = nmgetch();
XX    switch (c) {
XX    case 'c':
XX    case 'j':
XX    case 'k':
XX    case ctl(p):
XX    case ctl(n):
XX	return('c');
XX	break;
XX    case 'r':
XX    case 'l':
XX    case 'h':
XX    case ctl(f):
XX    case ctl(b):
XX	return('r');
XX	break;
XX    default:
XX	return(c);
XX    	break;
XX    }
XX}
XX
XXopenrow (rs) {
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 = maxcol + 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<maxrow) {
XX	for (c = maxcol+1, p = &tbl[r][0]; --c>=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[i] = 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 = maxcol-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 test 7952 -ne "`wc -c cmds.c`"
then
echo shar: error transmitting cmds.c '(should have been 7952 characters)'
fi
echo shar: extracting gram.y '(2777 characters)'
sed 's/^XX//' << \SHAR_EOF > gram.y
XX/*	SC	A Spreadsheet Calculator
XX *		Command and expression parser
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 *
XX */
XX
XX
XX
XX%{
XX#include "sc.h"
XX%}
XX
XX%union {
XX    int ival;
XX    double fval;
XX    struct ent *ent;
XX    struct enode *enode;
XX    char *sval;
XX}
XX
XX%type <ent> var
XX%type <enode> e term
XX%token <sval> STRING
XX%token <ival> NUMBER
XX%token <fval> FNUMBER
XX%token <sval> WORD
XX%token <ival> COL
XX%token S_FORMAT
XX%token S_LABEL
XX%token S_LEFTSTRING
XX%token S_RIGHTSTRING
XX%token S_GET
XX%token S_PUT
XX%token S_MERGE
XX%token S_LET
XX%token S_WRITE
XX%token S_TBL
XX%token S_PROGLET
XX%token S_COPY
XX%token S_SHOW
XX%token K_FIXED
XX%token K_SUM
XX%token K_PROD
XX%token K_AVE
XX
XX%left '?' ':'
XX%left '|'
XX%left '&'
XX%nonassoc '<' '=' '>'
XX%left '+' '-'
XX%left '*' '/'
XX
XX%%
XXcommand:	S_LET var '=' e	{ let ($2, $4); }
XX	|	S_LABEL var '=' STRING
XX				{ label ($2, $4, 0); }
XX	|	S_LEFTSTRING var '=' STRING
XX				{ label ($2, $4, -1); }
XX	|	S_RIGHTSTRING var '=' STRING
XX				{ label ($2, $4, 1); }
XX	|	S_FORMAT COL NUMBER NUMBER
XX				{ fwidth[$2] = $3;
XX				  FullUpdate++;
XX				  modflg++;
XX				  precision[$2] = $4; }
XX	|	S_GET STRING	{ readfile ($2,1); }
XX	|	S_MERGE STRING	{ readfile ($2,0); }
XX	|	S_PUT STRING	{ writefile ($2); }
XX	|	S_WRITE STRING	{ printfile ($2); }
XX	|	S_TBL STRING	{ tblprintfile ($2); }
XX	|       S_SHOW COL ':' COL  { showcol( $2, $4); }
XX	|       S_SHOW NUMBER ':' NUMBER  { showrow( $2, $4); }
XX	|	S_COPY var var ':' var
XX				{ copy($2, $3, $5); }
XX	|	/* nothing */
XX	|	error;
XX
XXterm: 		var		{ $$ = new ('v', $1); }
XX	|	K_FIXED term	{ $$ = new ('f', 0, $2); }
XX	|       '@' K_SUM '(' var ':' var ')' 
XX				{ $$ = new (O_REDUCE('+'), $4, $6); }
XX	|       '@' K_PROD '(' var ':' var ')' 
XX				{ $$ = new (O_REDUCE('*'), $4, $6); }
XX	|       '@' K_AVE '(' var ':' var ')' 
XX				{ $$ = new (O_REDUCE('a'), $4, $6); }
XX	|	'(' e ')'	{ $$ = $2; }
XX	|	'+' term	{ $$ = $2; }
XX	|	'-' term	{ $$ = new ('m', 0, $2); }
XX	|	NUMBER		{ $$ = new ('k', (double) $1); }
XX	|	FNUMBER		{ $$ = new ('k', $1); }
XX	|	'~' term	{ $$ = new ('~', 0, $2); }
XX	|	'!' term	{ $$ = new ('~', 0, $2); }
XX	;
XX
XXe:		e '+' e		{ $$ = new ('+', $1, $3); }
XX	|	e '-' e		{ $$ = new ('-', $1, $3); }
XX	|	e '*' e		{ $$ = new ('*', $1, $3); }
XX	|	e '/' e		{ $$ = new ('/', $1, $3); }
XX	|	term
XX	|	e '?' e ':' e	{ $$ = new ('?', $1, new(':', $3, $5)); }
XX	|	e '<' e		{ $$ = new ('<', $1, $3); }
XX	|	e '=' e		{ $$ = new ('=', $1, $3); }
XX	|	e '>' e		{ $$ = new ('>', $1, $3); }
XX	|	e '&' e		{ $$ = new ('&', $1, $3); }
XX	|	e '|' e		{ $$ = new ('|', $1, $3); }
XX	|	e '<' '=' e	{ $$ = new ('~', 0, new ('>', $1, $4)); }
XX	|	e '!' '=' e	{ $$ = new ('~', 0, new ('=', $1, $4)); }
XX	|	e '>' '=' e	{ $$ = new ('~', 0, new ('<', $1, $4)); }
XX	;
XX
XXvar:		COL NUMBER	{ $$ = lookat($2 , $1); };
SHAR_EOF
if test 2777 -ne "`wc -c gram.y`"
then
echo shar: error transmitting gram.y '(should have been 2777 characters)'
fi
echo shar: extracting eres.sed '(50 characters)'
sed 's/^XX//' << \SHAR_EOF > eres.sed
XX/%token.*K_/!d
XX/%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)'
sed 's/^XX//' << \SHAR_EOF > sres.sed
XX/%token.*S_/!d
XX/%token.*S_\(.*\)/s//	"\1",	S_\1,/
SHAR_EOF
if test 50 -ne "`wc -c sres.sed`"
then
echo shar: error transmitting sres.sed '(should have been 50 characters)'
fi
echo shar: extracting makefile '(1073 characters)'
sed 's/^XX//' << \SHAR_EOF > makefile
XXEXDIR=/a/rgb/bin
XXMANDIR=/usr/man/man1
XX
XX# Use me for system V.
XX#CFLAGS= -O -DSYSV
XX#LIB=-lcurses
XX
XX#Use me for BSD 4.2
XXCFLAGS= -O -DBSD42
XXLIB=-lcurses -ltermcap
XX
XXvc:	sc.o lex.o gram.o interp.o cmds.o
XX	cc ${CFLAGS} sc.o lex.o gram.o interp.o cmds.o ${LIB} -o vc
XX
XXdiff_to_vc:	diff_to_vc.c
XX	cc ${CFLAGS} -o dtv diff_to_vc.c
XX
XXlex.o:	sc.h y.tab.h gram.o
XX
XXinterp.o:	sc.h
XX
XXsc.o:	sc.h
XX
XXgram.o:	sc.h y.tab.h
XX
XXcmds.o: cmds.c sc.h
XX
XXy.tab.h:	gram.y
XX
XXgram.o:	gram.y
XX	yacc -d gram.y;mv y.tab.c gram.c;cc ${CFLAGS} -c gram.c; rm gram.c
XX	sed<gram.y >experres.h -f eres.sed;sed < gram.y > statres.h -f sres.sed
XX
XXprint:
XX	(pr gram.y sc.h;cpr interp.c lex.c sc.c) | lpr
XX
XXclean:
XX	rm -f *.o *res.h y.tab.h vc vc.old debug core
XX
XXco: co-all
XX
XXcoall: co-all
XX
XXco-all:
XX	co RCS/*
XX
XXshar:
XX	shar -a README sc.h interp.c sc.c lex.c cmds.c gram.y eres.sed sres.sed makefile > vc.shar.1 
XX	shar -a vc.man vc.1 cvt.sed > vc.shar.2
XX
XXinst-all: inst-vc inst-man
XX
XXinstall: $(EXDIR)/vc
XX
XXinst-man: $(MANDIR)/vc.1
XX
XX$(EXDIR)/vc: vc
XX	mv $(EXDIR)/vc $(EXDIR)/vc.old
XX	cp vc $(EXDIR)
XX
XX$(MANDIR)/vc.1: vc.1
XX	cp vc.1 $(MANDIR)
SHAR_EOF
if test 1073 -ne "`wc -c makefile`"
then
echo shar: error transmitting makefile '(should have been 1073 characters)'
fi
#	End of shell archive
exit 0
-- 
    Robert Bond 			ihnp4!nsc!nscpdc!rgb
    National Semiconductor		tektronix!nscpdc!rgb

gupta@mas1.UUCP (01/27/87)

This sounds like a piece of software that I would like to have.  However, we
never got either of the two parts.  Could a kind soul mail them to me?

adThanksvance.
-- 
Yogesh Gupta				{ ihnp4!mas1!gupta }
Measurex Automation Systems		           ^
						This is a "one"