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