v13i018: SC spreadsheet program, version 5.1, Part03/03
Rich Salz
rsalz at bbn.com
Fri Feb 5 08:13:50 AEST 1988
Submitted-by: nscpdc.nsc.com!rgb
Posting-number: Volume 13, Issue 18
Archive-name: sc5.1/part03
# 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:
# ./interp.c
# ./cmds.c
# ./crypt.c
# ./xmalloc.c
# ./range.c
# ./eres.sed
# ./sres.sed
# ./Makefile
# ./cvt.sed
# ./psc.c
#
if `test ! -s ./interp.c`
then
echo "Extracting ./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 <signal.h>
#include <setjmp.h>
#include <stdio.h>
#ifdef BSD42
#include <strings.h>
#include <sys/time.h>
#else
#include <time.h>
#ifndef SYSIII
#include <string.h>
#endif
#endif
#include <curses.h>
#include "sc.h"
#define DEFCOLDELIM ':'
extern char curfile[];
jmp_buf fpe_save;
int exprerr; /* Set by eval() and seval() if expression errors */
#ifdef SYSV3
void exit();
#endif
#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
dotime(which, when)
int which;
double when;
{
long time();
static long t_cache;
static struct tm *tp;
long tloc;
if (which == NOW)
return (double)time((long *)0);
tloc = (long)when;
if (tloc != t_cache) {
tp = localtime(&tloc);
tp->tm_mon += 1;
tp->tm_year += 1900;
t_cache = tloc;
}
switch (which) {
case HOUR: return((double)(tp->tm_hour));
case MINUTE: return((double)(tp->tm_min));
case SECOND: return((double)(tp->tm_sec));
case MONTH: return((double)(tp->tm_mon));
case DAY: return((double)(tp->tm_mday));
case YEAR: return((double)(tp->tm_year));
}
/* Safety net */
return (0.0);
}
double
doston(s)
char *s;
{
char *strtof();
double v;
if (!s)
return((double)0.0);
(void)strtof(s, &v);
xfree(s);
return(v);
}
double
doeqs(s1, s2)
char *s1, *s2;
{
double v;
if (strcmp(s1, s2) == 0)
v = 1.0;
else
v = 0.0;
if (s1)
xfree(s1);
if (s2)
xfree(s2);
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 (eval(e->e.o.right) == 0.0);
case 'k': return (e->e.k);
case 'v': return (e->e.v.vp->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 = e->e.r.right.vp -> row;
maxc = e->e.r.right.vp -> col;
minr = e->e.r.left.vp -> row;
minc = e->e.r.left.vp -> 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));
}
case HOUR: return (dotime(HOUR, eval(e->e.o.right)));
case MINUTE: return (dotime(MINUTE, eval(e->e.o.right)));
case SECOND: return (dotime(SECOND, eval(e->e.o.right)));
case MONTH: return (dotime(MONTH, eval(e->e.o.right)));
case DAY: return (dotime(DAY, eval(e->e.o.right)));
case YEAR: return (dotime(YEAR, eval(e->e.o.right)));
case NOW: return (dotime(NOW, (double)0.0));
case STON: return (doston(seval(e->e.o.right)));
case EQS: return (doeqs(seval(e->e.o.right),seval(e->e.o.left)));
default: error("Illegal Numeric Expression");
exprerr = 1;
return((double)0.0);
}
}
/*
* Rules for string functions:
* Take string arguments which they xfree.
* All returned strings are assumed to be xalloced.
*/
char *
docat(s1, s2)
register char *s1, *s2;
{
register char *p;
p = xmalloc((unsigned)(strlen(s1)+strlen(s2)+1));
(void) strcpy(p, s1);
(void) strcat(p, s2);
if (s1)
xfree(s1);
if (s2)
xfree(s2);
return(p);
}
char *
dodate(tloc)
long tloc;
{
char *tp;
char *p;
tp = ctime(&tloc);
tp[24] = 0;
p = xmalloc((unsigned)25);
(void) strcpy(p, tp);
return(p);
}
char *
dofmt(fmtstr, v)
char *fmtstr;
double v;
{
char buff[1024];
char *p;
if (!fmtstr)
return(0);
(void)sprintf(buff, fmtstr, v);
p = xmalloc((unsigned)(strlen(buff)+1));
(void) strcpy(p, buff);
xfree(fmtstr);
return(p);
}
char *
dosubstr(s, v1, v2)
char *s;
register int v1,v2;
{
register char *s1, *s2;
char *p;
if (!s)
return(0);
if (v1 < 0 || v2 < v1 || strlen(s) <= v2 ) {
xfree(s);
p = xmalloc((unsigned)1);
p[0] = 0;
return(p);
}
s2 = p = xmalloc((unsigned)(v2-v1+2));
s1 = &s[v1];
for(; v1 <= v2; s1++, s2++, v1++)
*s2 = *s1;
*s2 = 0;
xfree(s);
return(p);
}
char *
seval(se)
register struct enode *se;
{
register char *p;
if (se==0) return 0;
switch (se->op) {
case O_SCONST: p = xmalloc((unsigned)(strlen(se->e.s)+1));
(void) strcpy(p, se->e.s);
return(p);
case O_VAR: {
struct ent *ep;
ep = se->e.v.vp;
p = xmalloc((unsigned)(strlen(ep->label)+1));
(void) strcpy(p, ep->label);
return(p);
}
case '#': return(docat(seval(se->e.o.left), seval(se->e.o.right)));
case 'f': return(seval(se->e.o.right));
case '?': return(eval(se->e.o.left) ? seval(se->e.o.right->e.o.left)
: seval(se->e.o.right->e.o.right));
case DATE: return(dodate((long)(eval(se->e.o.right))));
case FMT: return(dofmt(seval(se->e.o.left), eval(se->e.o.right)));
case SUBSTR: return(dosubstr(seval(se->e.o.left),
(int)eval(se->e.o.right->e.o.left) - 1,
(int)eval(se->e.o.right->e.o.right) - 1));
default:
error("Illegal String Expression");
exprerr = 1;
return(0);
}
}
#define MAXPROP 7
EvalAll () {
int repct = 0;
while (RealEvalAll() && (repct++ <= MAXPROP));
}
#ifdef SYSV3
void
#endif
eval_fpe() /* Trap for FPE errors in eval */
{
longjmp(fpe_save, 1);
}
int
RealEvalAll () {
register i,j;
int chgct = 0;
register struct ent *p;
#ifdef SYSV3
void quit();
#else
int quit();
#endif
(void) signal(SIGFPE, eval_fpe);
for (i=0; i<=maxrow; i++)
for (j=0; j<=maxcol; j++)
if ((p=tbl[i][j]) && p->expr) {
if (p->flags & is_strexpr) {
char *v;
if (setjmp(fpe_save)) {
error("Floating point exception %s", v_name(i,j));
v = "";
} else {
v = seval(p->expr);
}
if (strcmp(v, p->label) != 0) {
chgct++;
p->flags |= is_changed;
}
if(p->label)
xfree(p->label);
p->label = v;
} else {
double v;
if (setjmp(fpe_save)) {
error("Floating point exception %s", v_name(i,j));
v = 0.0;
} else {
v = eval (p->expr);
}
if (v != p->v) {
p->v = v; chgct++;
p->flags |= (is_changed|is_valid);
}
}
}
(void) signal(SIGFPE, quit);
return(chgct);
}
struct enode *
new(op, a1, a2)
struct enode *a1, *a2;
{
register struct enode *p;
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_ptr a1;
{
register struct enode *p;
p = (struct enode *) xmalloc ((unsigned)sizeof (struct enode));
p->op = op;
p->e.v = a1;
return p;
}
struct enode *
new_range(op, a1)
struct range_s a1;
{
register struct enode *p;
p = (struct enode *) xmalloc ((unsigned)sizeof (struct enode));
p->op = op;
p->e.r = a1;
return p;
}
struct enode *
new_const(op, a1)
double a1;
{
register struct enode *p;
p = (struct enode *) xmalloc ((unsigned)sizeof (struct enode));
p->op = op;
p->e.k = a1;
return p;
}
struct enode *
new_str(s)
char *s;
{
register struct enode *p;
p = (struct enode *) xmalloc ((unsigned)sizeof(struct enode));
p->op = O_SCONST;
p->e.s = s;
return(p);
}
copy(dv1, dv2, v1, v2)
struct ent *dv1, *dv2, *v1, *v2;
{
int minsr, minsc;
int maxsr, maxsc;
int mindr, mindc;
int maxdr, maxdc;
int vr, vc;
int r, c;
mindr = dv1->row;
mindc = dv1->col;
maxdr = dv2->row;
maxdc = dv2->col;
if (mindr>maxdr) r = maxdr, maxdr = mindr, mindr = r;
if (mindc>maxdc) c = maxdc, maxdc = mindc, mindc = c;
maxsr = v2->row;
maxsc = v2->col;
minsr = v1->row;
minsc = v1->col;
if (minsr>maxsr) r = maxsr, maxsr = minsr, minsr = r;
if (minsc>maxsc) c = maxsc, maxsc = minsc, minsc = c;
if (maxdr >= MAXROWS ||
maxdc >= MAXCOLS) {
error ("The table can't be any bigger");
return;
}
erase_area(mindr, mindc, maxdr, maxdc);
if (minsr == maxsr && minsc == maxsc) {
/* Source is a single cell */
for(vr = mindr; vr <= maxdr; vr++)
for (vc = mindc; vc <= maxdc; vc++)
copyrtv(vr, vc, minsr, minsc, maxsr, maxsc);
} else if (minsr == maxsr) {
/* Source is a single row */
for (vr = mindr; vr <= maxdr; vr++)
copyrtv(vr, mindc, minsr, minsc, maxsr, maxsc);
} else if (minsc == maxsc) {
/* Source is a single column */
for (vc = mindc; vc <= maxdc; vc++)
copyrtv(mindr, vc, minsr, minsc, maxsr, maxsc);
} else {
/* Everything else */
copyrtv(mindr, mindc, minsr, minsc, maxsr, maxsc);
}
sync_refs();
}
copyrtv(vr, vc, minsr, minsc, maxsr, maxsc)
int vr, vc, minsr, minsc, maxsr, maxsc;
{
register struct ent *p;
register struct ent *n;
register int sr, sc;
register int dr, dc;
for (dr=vr, sr=minsr; sr<=maxsr; sr++, dr++)
for (dc=vc, sc=minsc; sc<=maxsc; sc++, dc++) {
n = lookat (dr, dc);
(void) clearent(n);
if (p = tbl[sr][sc]) {
n -> v = p -> v;
n -> flags = p -> flags;
n -> expr = copye(p->expr, dr - sr, dc - sc);
n -> label = 0;
if (p -> label) {
n -> label = xmalloc ((unsigned)(strlen (p -> label) + 1));
(void) 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);
(void) clearent(n);
n->v = start;
start += inc;
n->flags |= (is_changed|is_valid);
}
}
let (v, e)
struct ent *v;
struct enode *e;
{
double val;
exprerr = 0;
(void) signal(SIGFPE, eval_fpe);
if (setjmp(fpe_save)) {
error("Floating point exception %s", v_name(v->row, v->col));
val = 0.0;
} else {
val = eval(e);
}
(void) signal(SIGFPE, quit);
if (exprerr) {
efree(e);
return;
}
if (constant(e)) {
v->v = val;
if (!(v->flags & is_strexpr)) {
efree (v->expr);
v->expr = 0;
}
efree(e);
v->flags |= (is_changed|is_valid);
changed++;
modflg++;
return;
}
efree (v->expr);
v->expr = e;
v->flags |= (is_changed|is_valid);
v->flags &= ~is_strexpr;
changed++;
modflg++;
}
slet (v, se, flushdir)
struct ent *v;
struct enode *se;
int flushdir;
{
char *p;
exprerr = 0;
(void) signal(SIGFPE, eval_fpe);
if (setjmp(fpe_save)) {
error("Floating point exception %s", v_name(v->row, v->col));
p = "";
} else {
p = seval(se);
}
(void) signal(SIGFPE, quit);
if (exprerr) {
efree(se);
return;
}
if (constant(se)) {
label(v, p, flushdir);
if (p)
xfree(p);
efree(se);
if (v->flags & is_strexpr) {
efree (v->expr);
v->expr = 0;
v->flags &= ~is_strexpr;
}
return;
}
efree (v->expr);
v->expr = se;
v->flags |= (is_changed|is_strexpr);
if (flushdir<0) v->flags |= is_leftflush;
else v->flags &= ~is_leftflush;
FullUpdate++;
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_SCONST
|| (e->op != O_VAR
&& (e->op&~0177) != O_REDUCE(0)
&& constant (e->e.o.left)
&& constant(e->e.o.right)
&& e->op != NOW);
}
efree (e)
register struct enode *e; {
if (e) {
if (e->op != O_VAR && e->op !=O_CONST && e->op != O_SCONST
&& (e->op&~0177) != O_REDUCE(0)) {
efree(e->e.o.left);
efree(e->e.o.right);
}
if (e->op == O_SCONST && e->e.s)
xfree(e->e.s);
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));
(void) strcpy (v->label, s);
} else
v->label = 0;
if (flushdir<0) v->flags |= is_leftflush;
else v->flags &= ~is_leftflush;
FullUpdate++;
modflg++;
}
}
decodev (v)
struct ent_ptr v;
{
register struct range *r;
if (!v.vp) (void)sprintf (line+linelim,"VAR?");
else if (r = find_range((char *)0, 0, v.vp, v.vp))
(void)sprintf(line+linelim, "%s", r->r_name);
else
(void)sprintf (line+linelim, "%s%s%s%d",
v.vf & FIX_COL ? "$" : "",
coltoa(v.vp->col),
v.vf & FIX_ROW ? "$" : "",
v.vp->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 '-': 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': (void)sprintf (line+linelim,"%.15g",e->e.k);
linelim += strlen (line+linelim);
break;
case '$': (void)sprintf (line+linelim, "\"%s\"", e->e.s);
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, e->e.r.left.vp,
e->e.r.right.vp)) {
(void)sprintf(line+linelim, "%s", r->r_name);
linelim += strlen(line+linelim);
} else {
decodev (e->e.r.left);
line[linelim++] = ':';
decodev (e->e.r.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;
case HOUR: s = "@hour("; goto more1;
case MINUTE: s = "@minute("; goto more1;
case SECOND: s = "@second("; goto more1;
case MONTH: s = "@month("; goto more1;
case DAY: s = "@day("; goto more1;
case YEAR: s = "@year("; goto more1;
case DATE: s = "@date("; goto more1;
case STON: s = "@ston("; goto more1;
case FMT: s = "@fmt("; goto more2;
case EQS: s = "@eqs("; goto more2;
more1: for (; line[linelim++] = *s++;);
linelim--;
decompile (e->e.o.right, 0);
line[linelim++] = ')';
break;
more2: for (; line[linelim++] = *s++;);
linelim--;
decompile (e->e.o.left, 0);
line[linelim++] = ',';
decompile (e->e.o.right, 0);
line[linelim++] = ')';
break;
case NOW: s = "@now"; goto more0;
more0: for (; line[linelim++] = *s++;);
linelim--;
break;
case SUBSTR: s = "@substr(";
for (; line[linelim++] = *s++;);
linelim--;
decompile (e->e.o.left, 0);
line[linelim++] = ',';
decompile (e->e.o.right->e.o.left, 0);
line[linelim++] = ',';
decompile (e->e.o.right->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) {
register struct ent *p;
p = lookat (row, col);
(void)sprintf (line, "let %s = ", v_name(row, col));
linelim = strlen(line);
if (p->flags & is_strexpr || p->expr == 0) {
(void)sprintf (line+linelim, "%.15g", p->v);
linelim += strlen (line+linelim);
} else {
editexp(row,col);
}
}
editexp(row,col) {
register struct ent *p;
p = lookat (row, col);
decompile (p->expr, 0);
line[linelim] = 0;
}
edits (row, col) {
register struct ent *p;
p = lookat (row, col);
(void)sprintf (line, "%sstring %s = ",
((p->flags&is_leftflush) ? "left" : "right"),
v_name(row, col));
linelim = strlen(line);
if (p->flags & is_strexpr && p->expr) {
editexp(row, col);
} else {
(void)sprintf (line+linelim, "\"%s\"", p->label);
linelim += strlen (line+linelim);
}
}
printfile (fname, r0, c0, rn, cn)
char *fname;
{
FILE *f;
char pline[1000];
int plinelim;
int pid;
int fieldlen, nextcol;
register row, col;
register struct ent **p;
char ch, lin[100];
if (strcmp(fname, curfile) == 0) {
(void) move (0, 0);
(void) clrtoeol ();
(void) sprintf (lin,
"Confirm that you want to destroy the data base: (y,n)");
(void) addstr (lin);
(void) refresh();
ch = nmgetch();
if (ch != 'y' && ch != 'Y')
return;
}
f = openout(fname, &pid);
if (f==0) {
error ("Can't create %s", fname);
return;
}
for (row=r0;row<=rn; row++) {
register c = 0;
pline[plinelim=0] = '\0';
for (p = &tbl[row][col=c0]; col<=cn;
p += nextcol-col, col = nextcol, c += fieldlen) {
fieldlen = fwidth[col];
nextcol = col+1;
if (*p) {
char *s;
while (plinelim<c) pline[plinelim++] = ' ';
plinelim = c;
if ((*p)->flags&is_valid) {
(void)sprintf (pline+plinelim,"%*.*f",fwidth[col],
precision[col], (*p)->v);
plinelim += strlen (pline+plinelim);
}
if (s = (*p)->label) {
int slen;
char *start, *last;
register char *fp;
struct ent *nc;
/* Figure out if the label slops over to a blank field */
slen = strlen(s);
while (slen > fieldlen && nextcol <= cn &&
!((nc = lookat(row,nextcol))->flags & is_valid) &&
!(nc->label)) {
fieldlen += fwidth[nextcol];
nextcol++;
}
if (slen > fieldlen)
slen = fieldlen;
/* Now justify and print */
start = (*p)->flags & is_leftflush ? pline + c
: pline + c + fieldlen - slen;
last = pline + c + fieldlen;
fp = plinelim < c ? pline + plinelim : pline + c;
while (fp < start)
*fp++ = ' ';
while (slen--)
*fp++ = *s++;
if (!((*p)->flags & is_valid) || fieldlen != fwidth[col])
while(fp < last)
*fp++ = ' ';
if (plinelim < fp - pline)
plinelim = fp - pline;
}
}
}
(void) fprintf (f,"%.*s\n",plinelim,pline);
}
closeout(f, pid);
}
tblprintfile (fname, r0, c0, rn, cn)
char *fname;
{
FILE *f;
char pline[1000];
int pid;
register row, col;
register struct ent **p;
char coldelim = DEFCOLDELIM;
char ch, lin[100];
if (strcmp(fname, curfile) == 0) {
(void) move (0, 0);
(void) clrtoeol ();
(void) sprintf (lin,
"Confirm that you want to destroy the data base: (y,n)");
(void) addstr (lin);
(void) refresh();
ch = nmgetch();
if (ch != 'y' && ch != 'Y')
return;
}
f = openout(fname, &pid);
if (f==0) {
error ("Can't create %s", fname);
return;
}
for (row=r0; row<=rn; row++) {
for (p = &tbl[row][col=c0]; col<=cn; col++, p++) {
if (*p) {
char *s;
if ((*p)->flags&is_valid) {
(void) fprintf (f,"%.*f",precision[col],
(*p)->v);
}
if (s = (*p)->label) {
(void) fprintf (f,"%s",s);
}
}
(void) fprintf(f,"%c",coldelim);
}
(void) 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':
{
int newrow, newcol;
newrow=e->e.v.vf & FIX_ROW ? e->e.v.vp->row :
e->e.v.vp->row+Rdelta;
newcol=e->e.v.vf & FIX_COL ? e->e.v.vp->col :
e->e.v.vp->col+Cdelta;
ret->e.v.vp = lookat (newrow, newcol);
ret->e.v.vf = e->e.v.vf;
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 '$':
ret->e.s = xmalloc((unsigned) strlen(e->e.s)+1);
(void) strcpy(ret->e.s, e->e.s);
break;
case O_REDUCE('+'):
case O_REDUCE('*'):
case O_REDUCE('a'):
case O_REDUCE('s'):
case O_REDUCE(MAX):
case O_REDUCE(MIN):
{
int newrow, newcol;
newrow=e->e.r.left.vf & FIX_ROW ?e->e.r.left.vp->row :
e->e.r.left.vp->row+Rdelta;
newcol=e->e.r.left.vf & FIX_COL ?e->e.r.left.vp->col :
e->e.r.left.vp->col+Cdelta;
ret->e.r.left.vp = lookat (newrow, newcol);
ret->e.r.left.vf = e->e.r.left.vf;
newrow=e->e.r.right.vf & FIX_ROW ?e->e.r.right.vp->row :
e->e.r.right.vp->row+Rdelta;
newcol=e->e.r.right.vf & FIX_COL ?e->e.r.right.vp->col :
e->e.r.right.vp->col+Cdelta;
ret->e.r.right.vp = lookat (newrow, newcol);
ret->e.r.right.vf = e->e.r.right.vf;
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.vp = lookat(e->e.v.vp->row, e->e.v.vp->col);
break;
case 'k':
break;
case '$':
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.r.right.vp = lookat ( e->e.r.right.vp->row,
e->e.r.right.vp->col);
e->e.r.left.vp = lookat ( e->e.r.left.vp->row,
e->e.r.left.vp->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 | */
if ( pipe (pipefd) < 0) {
error("Can't make pipe to child");
*rpid = 0;
return(0);
}
deraw();
if ((pid=fork()) == 0) /* if child */
{
(void) close (0); /* close stdin */
(void) close (pipefd[1]);
(void) dup (pipefd[0]); /* connect to pipe input */
(void) execl ("/bin/sh", "sh", "-c", fname, 0);
exit (-127);
}
else /* else parent */
{
*rpid = pid;
f = fdopen (pipefd[1], "w");
if (f == 0)
{
(void) kill (pid, -9);
error ("Can't fdopen output");
(void) close (pipefd[1]);
*rpid = 0;
return(0);
}
}
return(f);
}
closeout(f, pid)
FILE *f;
int pid;
{
int temp;
(void) fclose (f);
if (pid) {
while (pid != wait(&temp)) /**/;
(void) printf("Press <return> to continue");
(void) fflush(stdout);
(void) nmgetch();
goraw();
}
}
\SHAR\EOF\
else
echo "will not over write ./interp.c"
fi
if [ `wc -c ./interp.c | awk '{printf $1}'` -ne 31137 ]
then
echo `wc -c ./interp.c | awk '{print "Got " $1 ", Expected " 31137}'`
fi
if `test ! -s ./cmds.c`
then
echo "Extracting ./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
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));
(void) 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));
(void) 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;
p->flags &= ~is_strexpr;
}
}
}
}
pullcells(to_insert)
{
register struct ent *p, *n;
register int deltar, deltac;
int minrow, mincol;
int mxrow, mxcol;
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;
mxrow = 0;
mxcol = 0;
for (p = to_fix; p; p = p->next) {
if (p->row < minrow)
minrow = p->row;
if (p->row > mxrow)
mxrow = p->row;
if (p->col < mincol)
mincol = p->col;
if (p->col > mxcol)
mxcol = p->col;
}
numrows = mxrow - minrow + 1;
numcols = mxcol - 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);
(void) 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));
(void) 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) {
(void) sprintf(line,"show %s:", coltoa(i));
(void) 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) {
(void) 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++;
}
doend(rowinc, colinc)
{
register struct ent *p;
int r, c;
if (VALID_CELL(p, currow, curcol)) {
r = currow + rowinc;
c = curcol + colinc;
if (r >= 0 && r < MAXROWS &&
c >= 0 && c < MAXCOLS &&
!VALID_CELL(p, r, c)) {
currow = r;
curcol = c;
}
}
if (!VALID_CELL(p, currow, curcol)) {
switch (rowinc) {
case -1:
while (!VALID_CELL(p, currow, curcol) && currow > 0)
currow--;
break;
case 1:
while (!VALID_CELL(p, currow, curcol) && currow < MAXROWS-1)
currow++;
break;
case 0:
switch (colinc) {
case -1:
while (!VALID_CELL(p, currow, curcol) && curcol > 0)
curcol--;
break;
case 1:
while (!VALID_CELL(p, currow, curcol) && curcol < MAXCOLS-1)
curcol++;
break;
}
break;
}
return;
}
switch (rowinc) {
case -1:
while (VALID_CELL(p, currow, curcol) && currow > 0)
currow--;
break;
case 1:
while (VALID_CELL(p, currow, curcol) && currow < MAXROWS-1)
currow++;
break;
case 0:
switch (colinc) {
case -1:
while (VALID_CELL(p, currow, curcol) && curcol > 0)
curcol--;
break;
case 1:
while (VALID_CELL(p, currow, curcol) && curcol < MAXCOLS-1)
curcol++;
break;
}
break;
}
if (!VALID_CELL(p, currow, curcol)) {
currow -= rowinc;
curcol -= colinc;
}
}
doformat(c1,c2,w,p)
int c1,c2,w,p;
{
register int i;
if (w > COLS - RESCOL - 2) {
error("Format too large - Maximum = %d", COLS - RESCOL - 2);
w = COLS-RESCOL-2;
}
if (p > w) {
error("Precision too large");
p = w;
}
for(i = c1; i<=c2; i++)
fwidth[i] = w, precision[i] = p;
FullUpdate++;
modflg++;
}
\SHAR\EOF\
else
echo "will not over write ./cmds.c"
fi
if [ `wc -c ./cmds.c | awk '{printf $1}'` -ne 9940 ]
then
echo `wc -c ./cmds.c | awk '{print "Got " $1 ", Expected " 9940}'`
fi
if `test ! -s ./crypt.c`
then
echo "Extracting ./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 <fcntl.h>
#endif
#include "sc.h"
extern char curfile[];
char *strcpy();
#ifdef SYSV3
void exit();
#endif
int Crypt = 0;
#define DEFWIDTH 10
#define DEFPREC 2
creadfile (save, eraseflg)
char *save;
{
register FILE *f;
int pipefd[2];
int fildes;
int pid;
if (eraseflg && strcmp(save, curfile) && modcheck(" first")) return;
fildes = open (save, O_RDONLY, 0);
if (fildes < 0)
{
error ("Can't read %s", save);
return;
}
if (eraseflg) erasedb ();
if (pipe(pipefd) < 0) {
error("Can't make pipe to child");
return;
}
deraw();
if ((pid=fork()) == 0) /* if child */
{
(void) close (0); /* close stdin */
(void) close (1); /* close stdout */
(void) close (pipefd[0]); /* close pipe input */
(void) dup (fildes); /* standard in from file */
(void) dup (pipefd[1]); /* connect to pipe */
(void) fprintf (stderr, " ");
(void) execl ("/bin/sh", "sh", "-c", "crypt", 0);
exit (-127);
}
else /* else parent */
{
(void) close (fildes);
(void) close (pipefd[1]); /* close pipe output */
f = fdopen (pipefd[0], "r");
if (f == 0)
{
(void) kill (pid, -9);
error ("Can't fdopen file %s", save);
(void) close (pipefd[0]);
return;
}
}
while (fgets(line,sizeof line,f)) {
linelim = 0;
if (line[0] != '#') (void) yyparse ();
}
(void) fclose (f);
(void) close (pipefd[0]);
while (pid != wait(&fildes)) /**/;
goraw();
linelim = -1;
modflg++;
if (eraseflg) {
(void) strcpy (curfile, save);
modflg = 0;
}
EvalAll();
}
cwritefile (fname, r0, c0, rn, cn)
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];
(void) strcpy(save,fname);
fildes = open (save, O_WRONLY|O_CREAT, 0600);
if (fildes < 0)
{
error ("Can't create %s", save);
return(-1);
}
if (pipe (pipefd) < 0) {
error ("Can't make pipe to child\n");
return(-1);
}
deraw();
if ((pid=fork()) == 0) /* if child */
{
(void) close (0); /* close stdin */
(void) close (1); /* close stdout */
(void) close (pipefd[1]); /* close pipe output */
(void) dup (pipefd[0]); /* connect to pipe input */
(void) dup (fildes); /* standard out to file */
(void) fprintf (stderr, " ");
(void) execl ("/bin/sh", "sh", "-c", "crypt", 0);
exit (-127);
}
else /* else parent */
{
(void) close (fildes);
(void) close (pipefd[0]); /* close pipe input */
f = fdopen (pipefd[1], "w");
if (f == 0)
{
(void) kill (pid, -9);
error ("Can't fdopen file %s", save);
(void) close (pipefd[1]);
return(-1);
}
}
(void) fprintf (f, "# This data file was generated by the Spreadsheet ");
(void) fprintf (f, "Calculator.\n");
(void) fprintf (f, "# You almost certainly shouldn't edit it.\n\n");
for (c=0; c<MAXCOLS; c++)
if (fwidth[c] != DEFWIDTH || precision[c] != DEFPREC)
(void)fprintf(f,"format %s %d %d\n",coltoa(c),fwidth[c],precision[c]);
write_range(f);
if (mdir)
(void) fprintf(f, "mdir \"%s\"\n", mdir);
for (r=r0; r<=rn; r++) {
p = &tbl[r][0];
for (c=c0; c<=cn; c++, p++)
if (*p) {
if ((*p)->label) {
edits(r, c);
(void) fprintf(f, "%s\n", line);
}
if ((*p)->flags&is_valid) {
editv(r, c);
(void) fprintf (f, "%s\n",line);
}
}
}
(void) fclose (f);
(void) close (pipefd[1]);
while (pid != wait(&fildes)) /**/;
(void) 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 3930 ]
then
echo `wc -c ./crypt.c | awk '{print "Got " $1 ", Expected " 3930}'`
fi
if `test ! -s ./xmalloc.c`
then
echo "Extracting ./xmalloc.c"
cat > ./xmalloc.c << '\SHAR\EOF\'
/*
* A safer saner malloc, for careless programmers
*/
#include <stdio.h>
#include <curses.h>
extern char *malloc();
#ifdef SYSV3
extern void free();
extern void exit();
#endif
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();
(void) 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 640 ]
then
echo `wc -c ./xmalloc.c | awk '{print "Got " $1 ", Expected " 640}'`
fi
if `test ! -s ./range.c`
then
echo "Extracting ./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
static struct range *rng_base;
add_range(name, left, right, is_range)
char *name;
struct ent_ptr left, right;
int is_range;
{
struct range *r;
register char *p;
int len;
int minr,minc,maxr,maxc;
int minrf, mincf, maxrf, maxcf;
if (left.vp->row < right.vp->row) {
minr = left.vp->row; minrf = left.vf & FIX_ROW;
maxr = right.vp->row; maxrf = right.vf & FIX_ROW;
} else {
minr = right.vp->row; minrf = right.vf & FIX_ROW;
maxr = left.vp->row; maxrf = right.vf & FIX_ROW;
}
if (left.vp->col < right.vp->col) {
minc = left.vp->col; mincf = left.vf & FIX_COL;
maxc = right.vp->col; maxcf = right.vf & FIX_COL;
} else {
minc = right.vp->col; mincf = right.vf & FIX_COL;
maxc = left.vp->col; maxcf = left.vf & FIX_COL;
}
left.vp = lookat(minr, minc);
left.vf = minrf | mincf;
right.vp = lookat(maxr, maxc);
right.vf = maxrf | maxcf;
if (find_range(name, strlen(name), (struct ent *)0, (struct ent *)0)) {
error("Error: range name already defined");
xfree(name);
return;
}
if (strlen(name) <= 2) {
error("Invalid range name - too short");
xfree(name);
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");
xfree(name);
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;
r->r_is_range = is_range;
if (rng_base)
rng_base->r_prev = r;
rng_base = r;
}
del_range(left, right)
struct ent *left, *right;
{
register struct range *r;
int minr,minc,maxr,maxc;
minr = left->row < right->row ? left->row : right->row;
minc = left->col < right->col ? left->col : right->col;
maxr = left->row > right->row ? left->row : right->row;
maxc = left->col > right->col ? left->col : right->col;
left = lookat(minr, minc);
right = lookat(maxr, maxc);
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);
}
clean_range()
{
register struct range *r;
register struct range *nextr;
r = rng_base;
rng_base = 0;
while (r) {
nextr = r->r_next;
xfree((char *)(r->r_name));
xfree((char *)r);
r = nextr;
}
}
/* 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.vp) && (rmatch == r->r_right.vp))
return(r);
}
return(0);
}
sync_ranges()
{
register struct range *r;
r = rng_base;
while(r) {
r->r_left.vp = lookat(r->r_left.vp->row, r->r_left.vp->col);
r->r_right.vp = lookat(r->r_right.vp->row, r->r_right.vp->col);
r = r->r_next;
}
}
write_range(f)
FILE *f;
{
register struct range *r;
for (r = rng_base; r; r = r->r_next) {
(void) fprintf(f, "define \"%s\" %s%s%s%d",
r->r_name,
r->r_left.vf & FIX_COL ? "$":"",
coltoa(r->r_left.vp->col),
r->r_left.vf & FIX_ROW ? "$":"",
r->r_left.vp->row);
if (r->r_is_range)
(void) fprintf(f, ":%s%s%s%d\n",
r->r_right.vf & FIX_COL ? "$":"",
coltoa(r->r_right.vp->col),
r->r_right.vf & FIX_ROW ? "$":"",
r->r_right.vp->row);
else
(void) fprintf(f, "\n");
}
}
list_range(f)
FILE *f;
{
register struct range *r;
for (r = rng_base; r; r = r->r_next) {
(void) fprintf(f, "%-30s %s%s%s%d",
r->r_name,
r->r_left.vf & FIX_COL ? "$":"",
coltoa(r->r_left.vp->col),
r->r_left.vf & FIX_ROW ? "$":"",
r->r_left.vp->row);
if (r->r_is_range)
(void) fprintf(f, ":%s%s%s%d\n",
r->r_right.vf & FIX_COL ? "$":"",
coltoa(r->r_right.vp->col),
r->r_right.vf & FIX_ROW ? "$":"",
r->r_right.vp->row);
else
(void) 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 {
(void) sprintf(buf, "%s%d", coltoa(col), row);
return(buf);
}
}
char *
r_name(r1, c1, r2, c2)
int r1, c1, r2, c2;
{
struct ent *v1, *v2;
struct range *r;
static char buf[100];
v1 = lookat(r1, c1);
v2 = lookat(r2, c2);
if (r = find_range((char *)0, 0, v1, v2)) {
return(r->r_name);
} else {
(void) sprintf(buf, "%s", v_name(r1, c1));
(void) sprintf(buf+strlen(buf), ":%s", v_name(r2, c2));
return(buf);
}
}
\SHAR\EOF\
else
echo "will not over write ./range.c"
fi
if [ `wc -c ./range.c | awk '{printf $1}'` -ne 5412 ]
then
echo `wc -c ./range.c | awk '{print "Got " $1 ", Expected " 5412}'`
fi
if `test ! -s ./eres.sed`
then
echo "Extracting ./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 "Extracting ./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 "Extracting ./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 psc.c
# The documents in the Archive
DOCS=README sc.doc psc.doc tutorial.sc
# Set SIMPLE for lex.c if you don't want arrow keys or lex.c blows up
#SIMPLE=-DSIMPLE
# Use this for system V.2
#CFLAGS= -O -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
p$(name): psc.c
cc ${CFLAGS} -o p$(name) psc.c
cp p$(name) $(EXDIR)/p$(name)
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) p$(name) debug core gram.c $(name).1 \
$(name).man p$(name).man p$(name).1 y.output
shar: ${SRC} ${DOCS}
shar -c -m 64000 -f shar ${DOCS} ${SRC}
lint: sc.h sc.c lex.c gram.c interp.c cmds.c crypt.c
lint ${CFLAGS} ${SIMPLE} sc.c lex.c gram.c interp.c cmds.c crypt.c \
range.c xmalloc.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
nroff -man $(name).1 > $(name).man
p$(name).1: psc.doc
sed -e s/pname/$(name)/g -e s/PNAME/$(NAME)/g psc.doc > p$(name).1
p$(name).man: p$(name).1
nroff -man p$(name).1 > p$(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)
diffs: ${SRC}
for i in ${SRC} ;\
do \
rcsdiff -c $$i ;\
done
\SHAR\EOF\
else
echo "will not over write ./Makefile"
fi
if [ `wc -c ./Makefile | awk '{printf $1}'` -ne 2787 ]
then
echo `wc -c ./Makefile | awk '{print "Got " $1 ", Expected " 2787}'`
fi
if `test ! -s ./cvt.sed`
then
echo "Extracting ./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
if `test ! -s ./psc.c`
then
echo "Extracting ./psc.c"
cat > ./psc.c << '\SHAR\EOF\'
/* Sc parse routine
*
* usage psc options
* options:
* -L Left justify strings. Default is right justify.
* -r Assemble data into rows first, not columns.
* -R n Increment by n between rows
* -C n Increment by n between columns
* -n n Length of the row (column) should be n.
* -s v Top left location in the spreadsheet should be v; eg, k5
* -d c Use c as the delimiter between the fields.
* -k Keep all delimiters - Default is strip multiple delimiters to 1.
*
* Author: Robert Bond
*/
#include <ctype.h>
#include <stdio.h>
#include "sc.h"
#define END 0
#define NUM 1
#define ALPHA 2
#define SPACE 3
#define EOL 4
extern char *optarg;
extern int optind;
char *coltoa();
char *progname;
int colfirst = 0;
int r0 = 0;
int c0 = 0;
int rinc = 1;
int cinc = 1;
int leftadj = 0;
int len = 20000;
char delim1 = ' ';
char delim2 = '\t';
int strip_delim = 1;
int fwidth[MAXCOLS];
int precision[MAXCOLS];
char token[1000];
main(argc, argv)
int argc;
char **argv;
{
int curlen;
int curcol, coff;
int currow, roff;
int first;
int c;
register effr, effc;
int i,j;
register char *p;
progname = argv[0];
while ((c = getopt(argc, argv, "rLks:R:C:n:d:")) != EOF) {
switch(c) {
case 'r':
colfirst = 1;
break;
case 'L':
leftadj = 1;
break;
case 's':
c0 = getcol(optarg);
r0 = getrow(optarg);
break;
case 'R':
rinc = atoi(optarg);
break;
case 'C':
cinc = atoi(optarg);
break;
case 'n':
len = atoi(optarg);
break;
case 'd':
delim1 = optarg[0];
delim2 = 0;
break;
case 'k':
strip_delim = 0;
break;
default:
(void) fprintf(stderr,"Usage: %s [-rkL] [-s v] [-R i] [-C i] [-n i] [-d c]\n", progname);
exit(1);
}
}
if (optind < argc) {
(void) fprintf(stderr,"Usage: %s [-rL] [-s v] [-R i] [-C i] [-n i] [-d c]\n", progname);
exit(1);
}
curlen = 0;
curcol = c0; coff = 0;
currow = r0; roff = 0;
first = 1;
while(1) {
effr = currow+roff;
effc = curcol+coff;
switch(scan()) {
case END:
for (i = 0; i<MAXCOLS; i++) {
if (precision[i])
(void) printf("format %s %d %d\n", coltoa(i), precision[i]+1,
fwidth[i]);
}
exit(0);
case NUM:
first = 0;
(void) printf("let %s%d = %s\n", coltoa(effc), effr, token);
if (effc > MAXCOLS-1)
(void) fprintf(stderr, "Invalid column used: %s\n", coltoa(effc));
else {
i = 0;
j = 0;
p = token;
while (*p && *p != '.') {
p++; i++;
}
if (*p) {
p++; i++;
}
while (*p) {
p++; i++; j++;
}
if (precision[effc] < i)
precision[effc] = i;
if (fwidth[effc] < j)
fwidth[effc] = j;
}
break;
case ALPHA:
first = 0;
if (leftadj)
(void) printf("leftstring %s%d = \"%s\"\n", coltoa(effc),effr,token);
else
(void) printf("rightstring %s%d = \"%s\"\n",coltoa(effc),effr,token);
if (effc > MAXCOLS-1)
(void) fprintf(stderr, "Invalid column used: %s\n", coltoa(effc));
else {
i = strlen(token);
if (i > precision[effc])
precision[effc] = i;
}
break;
case SPACE:
if (first && strip_delim)
break;
if (colfirst)
roff++;
else
coff++;
break;
case EOL:
curlen++;
roff = 0;
coff = 0;
first = 1;
if (colfirst) {
if (curlen >= len) {
curcol = c0;
currow += rinc;
curlen = 0;
} else {
curcol += cinc;
}
} else {
if (curlen >= len) {
currow = r0;
curcol += cinc;
curlen = 0;
} else {
currow += rinc;
}
}
break;
}
}
}
scan()
{
register int c;
register char *p;
p = token;
c = getchar();
if (c == EOF)
return(END);
if (c == '\n')
return(EOL);
if (c == delim1 || c == delim2) {
if (strip_delim) {
while ((c = getchar()) && (c == delim1 || c == delim2))
;
(void)ungetc(c, stdin);
}
return(SPACE);
}
if (c == '\"') {
while ((c = getchar()) && c != '\"' && c != '\n' && c != EOF)
*p++ = c;
if (c != '\"')
(void)ungetc(c, stdin);
*p = 0;
return(ALPHA);
}
while (c != delim1 && c != delim2 && c!= '\n' && c != EOF) {
*p++ = c;
c = getchar();
}
*p = 0;
(void)ungetc(c, stdin);
p = token;
c = *p;
if (isdigit(c) || c == '.' || c == '-' || c == '+') {
while(isdigit(c) || c == '.' || c == '-' || c == '+' || c == 'e'
|| c == 'E') {
c = *p++;
}
if (c == 0)
return(NUM);
else
return(ALPHA);
}
return(ALPHA);
}
getcol(p)
char *p;
{
register col;
if (!p)
return(0);
while(*p && !isalpha(*p))
p++;
if (!*p)
return(0);
col = ((*p & 0137) - 'A');
if (isalpha(*++p))
col = (col + 1)*26 + ((*p & 0137) - 'A');
return(col);
}
getrow(p)
char *p;
{
int row;
if (!p)
return(0);
while(*p && !isdigit(*p))
p++;
if (!*p)
return(0);
if (sscanf(p, "%d", &row) != 1)
return(0);
return(row);
}
char *
coltoa(col)
int col;
{
static char rname[3];
register char *p = rname;
if (col < 0 || col > 25*26)
(void) fprintf(stderr,"coltoa: invalid col: %d", col);
if (col > 25) {
*p++ = col/26 + 'A' - 1;
col %= 26;
}
*p++ = col+'A';
*p = 0;
return(rname);
}
\SHAR\EOF\
else
echo "will not over write ./psc.c"
fi
if [ `wc -c ./psc.c | awk '{printf $1}'` -ne 5321 ]
then
echo `wc -c ./psc.c | awk '{print "Got " $1 ", Expected " 5321}'`
fi
echo "Finished archive 3 of 3"
# if you want to concatenate archives, remove anything after this line
exit
--
For comp.sources.unix stuff, mail to sources at uunet.uu.net.
More information about the Comp.sources.unix
mailing list