Sc 3.1 - 2 of 2 spread sheet
rgb at nscpdc.UUCP
rgb at nscpdc.UUCP
Tue Jan 27 13:41:35 AEST 1987
# This is a shell archive.
# Remove everything above and including the cut line.
# Then run the rest of the file through sh.
#-----cut here-----cut here-----cut here-----cut here-----
#!/bin/sh
# shar: Shell Archiver
# Run the following text with /bin/sh to create:
# sc.h
# sc.c
# lex.c
# gram.y
# interp.c
# This archive created: Mon Jan 26 19:36:31 1987
# By: Robert Bond (NSC Portland, Oregon)
echo shar: extracting sc.h '(1515 characters)'
cat << \SHAR_EOF > sc.h
/* VC A Table Calculator
* Common definitions
*
* original by James Gosling, September 1982
* modified by Mark Weiser and Bruce Israel,
* University of Maryland
*
*/
#define MAXROWS 200
#define MAXCOLS 40
#define error move(1,0), clrtoeol(), printw
struct ent {
double v;
char *label;
struct enode *expr;
short flags;
short row, col;
struct ent *next;
};
struct enode {
int op;
union {
double k;
struct ent *v;
struct {
struct enode *left, *right;
} o;
} e;
};
/* op values */
#define O_VAR 'v'
#define O_CONST 'k'
#define O_REDUCE(c) (c+0200)
#define ACOS 0
#define ASIN 1
#define ATAN 2
#define CEIL 3
#define COS 4
#define EXP 5
#define FABS 6
#define FLOOR 7
#define HYPOT 8
#define LOG 9
#define LOG10 10
#define POW 11
#define SIN 12
#define SQRT 13
#define TAN 14
#define DTR 15
#define RTD 16
#define MIN 17
#define MAX 18
/* flag values */
#define is_valid 0001
#define is_changed 0002
#define is_lchanged 0004
#define is_leftflush 0010
#define is_deleted 0020
#define ctl(c) ('c'&037)
struct ent *tbl[MAXROWS][MAXCOLS];
int strow, stcol;
int currow, curcol;
int savedrow, savedcol;
int FullUpdate;
int maxrow, maxcol;
int fwidth[MAXCOLS];
int precision[MAXCOLS];
char hidden_col[MAXCOLS];
char hidden_row[MAXROWS];
char line[1000];
int linelim;
int changed;
struct ent *to_fix;
struct enode *new();
struct enode *new_const();
struct enode *new_var();
struct ent *lookat();
struct enode *copye();
char *coltoa();
int modflg;
SHAR_EOF
if test 1515 -ne "`wc -c sc.h`"
then
echo shar: error transmitting sc.h '(should have been 1515 characters)'
fi
echo shar: extracting sc.c '(18976 characters)'
cat << \SHAR_EOF > sc.c
/* SC A Spreadsheet Calculator
* Main driver
*
* original by James Gosling, September 1982
* modifications by Mark Weiser and Bruce Israel,
* University of Maryland
*
* More mods Robert Bond, 12/86
*
*/
#include <signal.h>
#include <curses.h>
#ifdef BSD42
#include <strings.h>
#else
#ifndef SYSIII
#include <string.h>
#endif
#endif
#include <stdio.h>
#include "sc.h"
#if BSD42 || SYSIII
#define cbreak crmode
#define nocbreak nocrmode
#endif
char *malloc();
/* default column width */
#define DEFWIDTH 10
#define DEFPREC 2
#define RESCOL 4 /* columns reserved for row numbers */
#define RESROW 3 /* rows reserved for prompt, error, and column numbers */
char curfile[1024];
int linelim = -1;
int showme = 1; /* 1 to display the current cell in the top line */
char *rev = "$Revision: 3.1 $";
int seenerr;
yyerror (err)
char *err; {
if (seenerr) return;
seenerr++;
move (1,0);
clrtoeol ();
printw ("%s: %.*s<=%s",err,linelim,line,line+linelim);
}
struct ent *
lookat(row,col){
register struct ent **p;
if (row < 0)
row = 0;
else if (row > MAXROWS-1)
row = MAXROWS-1;
if (col < 0)
col = 0;
else if (col > MAXCOLS-1)
col = MAXCOLS-1;
p = &tbl[row][col];
if (*p==0) {
*p = (struct ent *) malloc ((unsigned) sizeof (struct ent));
if (row>maxrow) maxrow = row;
if (col>maxcol) maxcol = col;
(*p)->label = 0;
(*p)->flags = 0;
(*p)->row = row;
(*p)->col = col;
(*p)->expr = 0;
(*p)->v = (double) 0.0;
}
return *p;
}
/*
* This structure is used to keep ent structs around before they
* are deleted to allow the sync_refs routine a chance to fix the
* variable references.
* We also use it as a last-deleted buffer for the 'p' command.
*/
free_ent(p)
register struct ent *p;
{
p->next = to_fix;
to_fix = p;
p->flags |= is_deleted;
}
flush_saved()
{
register struct ent *p;
register struct ent *q;
if (!(p = to_fix))
return;
while (p) {
clearent(p);
q = p->next;
free ((char *)p);
p = q;
}
to_fix = 0;
}
update () {
register row,
col;
register struct ent **p;
static lastmx,
lastmy;
static char *under_cursor = " ";
int maxcol;
int maxrow;
int rows;
int cols;
register r;
while (hidden_row[currow]) /* You can't hide the last row or col */
currow++;
while (hidden_col[curcol])
curcol++;
if (curcol < stcol)
stcol = curcol, FullUpdate++;
if (currow < strow)
strow = currow, FullUpdate++;
while (1) {
register i;
for (i = stcol, cols = 0, col = RESCOL;
(col + fwidth[i]) < COLS-1 && i < MAXCOLS; i++) {
cols++;
if (hidden_col[i])
continue;
col += fwidth[i];
}
if (curcol >= stcol + cols)
stcol++, FullUpdate++;
else
break;
}
while (1) {
register i;
for (i = strow, rows = 0, row = RESROW;
row < LINES && i < MAXROWS; i++) {
rows++;
if (hidden_row[i])
continue;
row++;
}
if (currow >= strow + rows)
strow++, FullUpdate++;
else
break;
}
maxcol = stcol + cols - 1;
maxrow = strow + rows - 1;
if (FullUpdate) {
register int i;
move (2, 0);
clrtobot ();
standout();
for (row=RESROW, i=strow; i <= maxrow; i++) {
if (hidden_row[i])
continue;
move(row,0);
printw("%-*d", RESCOL, i);
row++;
}
move (2,0);
printw("%*s", RESCOL, " ");
for (col=RESCOL, i = stcol; i <= maxcol; i++) {
if (hidden_col[i])
continue;
move(2, col);
printw("%*s", fwidth[i], coltoa(i));
col += fwidth[i];
}
standend();
}
for (row = strow, r = RESROW; row <= maxrow; row++) {
register c = RESCOL;
if (hidden_row[row])
continue;
for (p = &tbl[row][col = stcol]; col <= maxcol; col++, p++) {
if (hidden_col[col])
continue;
if (*p && ((*p) -> flags & is_changed || FullUpdate)) {
char *s;
move (r, c);
(*p) -> flags &= ~is_changed;
if ((*p) -> flags & is_valid)
printw ("%*.*f", fwidth[col], precision[col], (*p) -> v);
if (s = (*p) -> label) {
char field[1024];
strncpy(field,s,fwidth[col]);
field[fwidth[col]] = 0;
mvaddstr (r,
(*p) -> flags & is_leftflush
? c : c - strlen (field) + fwidth[col],
field);
}
}
c += fwidth[col];
}
r++;
}
move(lastmy, lastmx);
if (inch() == '<')
addstr (under_cursor);
lastmy = RESROW;
for (row = strow; row < currow; row++)
if (!hidden_row[row])
lastmy += 1;
lastmx = RESCOL;
for (col = stcol; col <= curcol; col++)
if (!hidden_col[col])
lastmx += fwidth[col];
move(lastmy, lastmx);
*under_cursor = inch();
addstr ("<");
move (0, 0);
clrtoeol ();
if (linelim >= 0) {
addstr (">> ");
addstr (line);
} else {
if (showme) {
register struct ent *p;
p = tbl[currow][curcol];
if (p && ((p->flags & is_valid) || p->label)) {
if (p->expr || !p->label) {
linelim = 0;
editexp(currow, curcol);
} else {
sprintf(line, "%s", p->label);
}
addstr("[");
addstr (line);
addstr("]");
linelim = -1;
} else {
addstr("[]");
}
}
move (lastmy, lastmx);
}
FullUpdate = 0;
}
main (argc, argv)
char **argv; {
int inloop = 1;
register int c;
int edistate = -1;
int arg = 1;
int narg;
int nedistate;
int running;
char revmsg[80];
char *revi;
{
register i;
for (i = 0; i < MAXCOLS; i++) {
fwidth[i] = DEFWIDTH;
precision[i] = DEFPREC;
}
}
curfile[0]=0;
running = 1;
signals();
initscr ();
clear ();
cbreak();
nonl();
noecho ();
initkbd();
if (argc > 1) {
strcpy(curfile,argv[1]);
readfile (argv[1],0);
}
modflg = 0;
strcpy(revmsg, argv[0]);
for (revi=rev; *revi++ != ':';);
strcat(revmsg, revi);
revi = revmsg+strlen(revmsg);
*--revi = 0;
strcat(revmsg,"Type '?' for help.");
error (revmsg);
FullUpdate++;
while (inloop) { running = 1;
while (running) {
nedistate = -1;
narg = 1;
if (edistate < 0 && linelim < 0 && (changed || FullUpdate))
EvalAll (), changed = 0;
update ();
refresh ();
move (1, 0);
clrtoeol ();
fflush (stdout);
seenerr = 0;
if (((c = nmgetch ()) < ' ') || ( c == 0177 ))
switch (c) {
#if defined(BSD42) || defined (BSD43)
case ctl (z):
nocrmode ();
nl ();
echo ();
kill(getpid(),SIGTSTP);
/* the pc stops here */
crmode ();
nonl ();
noecho ();
break;
#endif
case ctl (r):
case ctl (l):
FullUpdate++;
clearok(stdscr,1);
break;
default:
error ("No such command (^%c)", c + 0100);
break;
case ctl (b):
while (--arg>=0) {
if (curcol)
curcol--;
else
error ("At column A");
while(hidden_col[curcol] && curcol)
curcol--;
}
break;
case ctl (c):
running = 0;
break;
case ctl (f):
while (--arg>=0) {
if (curcol < MAXCOLS - 1)
curcol++;
else
error ("The table can't be any wider");
while(hidden_col[curcol]&&(curcol<MAXCOLS-1))
curcol++;
}
break;
case ctl (g):
case ctl ([):
linelim = -1;
move (1, 0);
clrtoeol ();
break;
case 0177:
case ctl (h):
while (--arg>=0) if (linelim > 0)
line[--linelim] = 0;
break;
case ctl (m):
case ctl (j):
if (linelim < 0)
line[linelim = 0] = 0;
else {
linelim = 0;
yyparse ();
linelim = -1;
}
break;
case ctl (n):
while (--arg>=0) {
if (currow < MAXROWS - 1)
currow++;
else
error ("The table can't be any longer");
while (hidden_row[currow] && (currow < MAXROWS - 1))
currow++;
}
break;
case ctl (p):
while (--arg>=0) {
if (currow)
currow--;
else
error ("At row zero");
while (hidden_row[currow] && currow)
currow--;
}
break;
case ctl (q):
break; /* ignore flow control */
case ctl (s):
break; /* ignore flow control */
case ctl (t):
showme ^= 1;
break;
case ctl (u):
narg = arg * 4;
nedistate = 1;
break;
case ctl (v): /* insert variable name */
if (linelim > 0) {
sprintf (line+linelim,"%s%d", coltoa(curcol), currow);
linelim = strlen (line);
}
break;
case ctl (e): /* insert variable expression */
if (linelim > 0) editexp(currow,curcol);
break;
case ctl (a): /* insert variable value */
if (linelim > 0) {
struct ent *p = tbl[currow][curcol];
if (p && p -> flags & is_valid) {
sprintf (line + linelim, "%.*f",
precision[curcol],p -> v);
linelim = strlen (line);
}
}
break;
}
else
if ('0' <= c && c <= '9' && (linelim < 0 || edistate >= 0)) {
if (edistate != 0) {
if (c == '0') /* just a '0' goes to left col */
curcol = 0;
else {
nedistate = 0;
narg = c - '0';
}
} else {
nedistate = 0;
narg = arg * 10 + (c - '0');
}
}
else
if (linelim >= 0) {
line[linelim++] = c;
line[linelim] = 0;
}
else
switch (c) {
case '.':
nedistate = 1;
break;
case ':':
break; /* Be nice to vi users */
case '=':
sprintf(line,"let %s%d = ",coltoa(curcol),currow);
linelim = strlen (line);
break;
case '/':
switch (nmgetch()) {
case 'c':
sprintf(line,"copy [to] %s%d [from] ",
coltoa(curcol), currow);
linelim = strlen(line);
break;
case 'x':
sprintf(line,"erase [v:v] ");
linelim = strlen(line);
break;
case 'f':
sprintf(line,"fill [v:v start inc] ");
linelim = strlen(line);
break;
default:
error("Invalid region operation");
}
break;
case '$':
curcol = MAXCOLS - 1;
while (!tbl[currow][curcol] && curcol > 0)
curcol--;
break;
case '#':
currow = MAXROWS - 1;
while (!tbl[currow][curcol] && currow > 0)
currow--;
break;
case '^':
currow = 0;
break;
case '?':
help ();
break;
case '"':
sprintf (line, "label %s%d = \"",
coltoa(curcol), currow);
linelim = strlen (line);
break;
case '<':
sprintf (line, "leftstring %s%d = \"",
coltoa(curcol), currow);
linelim = strlen (line);
break;
case '>':
sprintf (line, "rightstring %s%d = \"",
coltoa(curcol), currow);
linelim = strlen (line);
break;
case 'e':
editv (currow, curcol);
break;
case 'E':
edits (currow, curcol);
break;
case 'f':
sprintf (line, "format [for column] %s [is] ",
coltoa(curcol));
error("Current format is %d %d",
fwidth[curcol],precision[curcol]);
linelim = strlen (line);
break;
case 'g':
sprintf (line, "goto [v] ");
linelim = strlen (line);
break;
case 'P':
sprintf (line, "put [database into] \"");
if (*curfile)
error("default file is '%s'",curfile);
linelim = strlen (line);
break;
case 'M':
sprintf (line, "merge [database from] \"");
linelim = strlen (line);
break;
case 'G':
sprintf (line, "get [database from] \"");
if (*curfile)
error("default file is '%s'",curfile);
linelim = strlen (line);
break;
case 'W':
sprintf (line, "write [listing to] \"");
linelim = strlen (line);
break;
case 'T': /* tbl output */
sprintf (line, "tbl [listing to] \"");
linelim = strlen (line);
break;
case 'i':
switch (get_qual()) {
case 'r':
insertrow(arg);
break;
case 'c':
insertcol(arg);
break;
default:
error("Invalid insert command");
break;
}
break;
case 'd':
switch (get_qual()) {
case 'r':
deleterow(arg);
break;
case 'c':
deletecol(arg);
break;
default:
error("Invalid delete command");
break;
}
break;
case 'v':
switch (get_qual()) {
case 'r':
rowvalueize(arg);
modflg++;
break;
case 'c':
colvalueize(arg);
modflg++;
break;
default:
error("Invalid value command");
break;
}
break;
case 'p':
{
register qual;
qual = get_qual();
while (arg--)
pullcells(qual);
break;
}
case 'x':
{
register struct ent **p;
register int c;
flush_saved();
for (c = curcol; arg-- && c < MAXCOLS; c++) {
p = &tbl[currow][c];
if (*p) {
free_ent(*p);
*p = 0;
}
}
sync_refs();
FullUpdate++;
}
break;
case 'Q':
case 'q':
running = 0;
break;
case 'h':
while (--arg>=0) {
if (curcol)
curcol--;
else
error ("At column A");
while(hidden_col[curcol] && curcol)
curcol--;
}
break;
case 'j':
while (--arg>=0) {
if (currow < MAXROWS - 1)
currow++;
else
error ("The table can't be any longer");
while (hidden_row[currow]&&(currow<MAXROWS-1))
currow++;
}
break;
case 'k':
while (--arg>=0) {
if (currow)
currow--;
else
error ("At row zero");
while (hidden_row[currow] && currow)
currow--;
}
break;
case 'l':
while (--arg>=0) {
if (curcol < MAXCOLS - 1)
curcol++;
else
error ("The table can't be any wider");
while(hidden_col[curcol]&&(curcol<MAXCOLS-1))
curcol++;
}
break;
case 'm':
savedrow = currow;
savedcol = curcol;
break;
case 'c': {
register struct ent *p = tbl[savedrow][savedcol];
register c;
register struct ent *n;
if (!p)
break;
FullUpdate++;
modflg++;
for (c = curcol; arg-- && c < MAXCOLS; c++) {
n = lookat (currow, c);
clearent(n);
n -> flags = p -> flags;
n -> v = p -> v;
n -> expr = copye(p->expr,
currow - savedrow,
c - savedcol);
n -> label = 0;
if (p -> label) {
n -> label =
malloc((unsigned)(strlen(p->label)+1));
strcpy (n -> label, p -> label);
}
}
break;
}
case 'z':
switch (get_qual()) {
case 'r':
hiderow(arg);
break;
case 'c':
hidecol(arg);
break;
default:
error("Invalid zap command");
break;
}
break;
case 's':
switch (get_qual()) {
case 'r':
rowshow_op();
break;
case 'c':
colshow_op();
break;
default:
error("Invalid show command");
break;
}
break;
case 'a':
switch (get_qual()) {
case 'r':
while (arg--)
duprow();
break;
case 'c':
while (arg--)
dupcol();
break;
default:
error("Invalid add row/col command");
break;
}
break;
default:
if ((c & 0177) != c)
error("Weird character, decimal '%d'.\n",
(int) c);
else error ("No such command (%c)", c);
break;
}
edistate = nedistate;
arg = narg;
} /* while (running) */
inloop = modcheck(" before exiting");
} /* while (inloop) */
move (LINES - 1, 0);
clrtoeol();
refresh ();
nocbreak();
nl();
echo ();
resetkbd();
endwin ();
}
signals()
{
int quit();
int timeout();
signal(SIGINT, SIG_IGN);
signal(SIGQUIT, quit);
signal(SIGPIPE, quit);
signal(SIGTERM, quit);
signal(SIGALRM, timeout);
signal(SIGFPE, quit);
signal(SIGBUS, quit);
}
quit()
{
move (LINES - 1, 0);
clrtoeol();
refresh();
nocbreak();
nl();
echo();
resetkbd();
endwin();
exit(1);
}
modcheck(endstr) char *endstr; {
if (modflg && curfile[0]) {
char ch, lin[100];
move (0, 0);
clrtoeol ();
sprintf (lin,"File '%s' is modified, save%s? ",curfile,endstr);
addstr (lin);
refresh();
ch = nmgetch();
if (ch != 'n' && ch != 'N')
if (writefile(curfile) < 0)
return (1);
else if (ch == ctl (g) || ch == ctl([)) return(1);
} else if (modflg) {
char ch, lin[100];
move (0, 0);
clrtoeol ();
sprintf (lin,"Do you want a chance to save the data? ");
addstr (lin);
refresh();
ch = nmgetch();
if (ch == 'n' || ch == 'N') return(0);
else return(1);
}
return(0);
}
writefile (fname)
char *fname; {
register FILE *f;
register struct ent **p;
register r, c;
char save[1024];
if (*fname == 0) fname = &curfile[0];
strcpy(save,fname);
f = fopen (fname, "w");
if (f==0) {
error ("Can't create %s", fname);
return (-1);
}
fprintf (f, "# This data file was generated by the Spreadsheet ");
fprintf (f, "Calculator.\n");
fprintf (f, "# You almost certainly shouldn't edit it.\n\n");
for (c=0; 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);
strcpy(curfile,save);
modflg = 0;
error("File '%s' written.",curfile);
return (0);
}
readfile (fname,eraseflg)
char *fname; int eraseflg; {
register FILE *f;
char save[1024];
if (*fname == 0) fname = &curfile[0];
strcpy(save,fname);
if (eraseflg && strcmp(fname,curfile) && modcheck(" first")) return;
f = fopen (save, "r");
if (f==0) {
error ("Can't read %s", save);
return;
}
if (eraseflg) erasedb ();
while (fgets(line,sizeof line,f)) {
linelim = 0;
if (line[0] != '#') yyparse ();
}
fclose (f);
linelim = -1;
modflg++;
if (eraseflg) {
strcpy(curfile,save);
modflg = 0;
}
EvalAll();
}
erasedb () {
register r, c;
for (c = 0; c<=maxcol; c++) {
fwidth[c] = DEFWIDTH;
precision[c] = DEFPREC;
}
for (r = 0; r<=maxrow; r++) {
register struct ent **p = &tbl[r][0];
for (c=0; c++<=maxcol; p++)
if (*p) {
if ((*p)->expr) efree ((*p) -> expr);
if ((*p)->label) free ((*p) -> label);
free ((char *)*p);
*p = 0;
}
}
maxrow = 0;
maxcol = 0;
FullUpdate++;
}
#if DEBUG
debugout(g,fmt,args) FILE *g; char *fmt; {
int op;
if (g == 0) g = fopen("debug","a"),op = 1;
if (g == 0) return;
_doprnt(fmt, &args, g);
fflush(g);
if (op) fclose(g);
}
#endif
SHAR_EOF
if test 18976 -ne "`wc -c sc.c`"
then
echo shar: error transmitting sc.c '(should have been 18976 characters)'
fi
echo shar: extracting lex.c '(9305 characters)'
cat << \SHAR_EOF > lex.c
/* SC A Spreadsheet Calculator
* Lexical analyser
*
* original by James Gosling, September 1982
* modifications by Mark Weiser and Bruce Israel,
* University of Maryland
*
* More mods Robert Bond, 12/86
*
*/
#if defined(BSD42) || defined(BSD43)
#include <sys/ioctl.h>
#endif
#include <curses.h>
#include <signal.h>
#include <setjmp.h>
#include "sc.h"
#include <ctype.h>
#ifdef BSD42
#include <strings.h>
#else
#ifndef SYSIII
#include <string.h>
#endif
#endif
#include "y.tab.h"
char *strtof();
char *malloc();
jmp_buf wakeup;
struct key {
char *key;
int val;
};
struct key experres[] = {
#include "experres.h"
0, 0};
struct key statres[] = {
#include "statres.h"
0, 0};
#define ctl(x) ('x'&037)
yylex () {
register char *p = line+linelim;
int ret;
while (isspace(*p)) p++;
if (*p==0) ret = -1;
else if (isalpha(*p)) {
char *tokenst = p;
register tokenl;
register struct key *tbl;
while (isalpha(*p)) p++;
if ((tokenl = p-tokenst) <= 2) {
register col; /* a COL is 1 or 2 char alpha (and not pi or ln!) */
if (tokenl == 2 && tokenst[0] == 'p' && tokenst[1] == 'i') {
ret = K_PI;
} else if (tokenl == 2 && tokenst[0] == 'l' && tokenst[1] == 'n') {
ret = K_LN;
} else {
ret = COL;
col = ((tokenst[0] & 0137) - 'A');
if (p == tokenst+2)
col = (col + 1)*26 + ((tokenst[1] & 0137) - 'A');
yylval.ival = col;
}
} else {
ret = WORD;
tokenl = p-tokenst;
for (tbl = linelim ? experres : statres; tbl->key; tbl++)
if (((tbl->key[0]^tokenst[0])&0137)==0
&& tbl->key[tokenl]==0) {
register i = 1;
while (i<tokenl && ((tokenst[i]^tbl->key[i])&0137)==0)
i++;
if (i>=tokenl) {
ret = tbl->val;
break;
}
}
if (ret==WORD) {
linelim = p-line;
yyerror ("Unintelligible word");
}
}
} else if ((*p == '.') || isdigit(*p)) {
register long v = 0;
char *nstart = p;
if (*p != '.') {
do v = v*10 + (*p-'0');
while (isdigit(*++p));
}
if (*p=='.' || *p == 'e' || *p == 'E') {
ret = FNUMBER;
p = strtof(nstart, &yylval.fval);
} else {
if((int)v != v)
{
ret = FNUMBER;
yylval.fval = v;
}
else
{
ret = NUMBER;
yylval.ival = v;
}
}
} else if (*p=='"') {
/* This storage is never freed. Oh well. -MDW */
char *ptr;
ptr = p+1;
while(*ptr && *ptr++ != '"');
ptr = malloc((unsigned)(ptr-p));
yylval.sval = ptr;
p += 1;
while (*p && *p!='"') *ptr++ = *p++;
*ptr = 0;
if (*p) p += 1;
ret = STRING;
} else if (*p=='[') {
while (*p && *p!=']') p++;
if (*p) p++;
linelim = p-line;
return yylex();
} else ret = *p++;
linelim = p-line;
return ret;
}
#ifdef SIMPLE
initkbd()
{}
resetkbd()
{}
nmgetch()
{
return (getchar() & 0x7f);
}
#else /*SIMPLE*/
#if defined(BSD42) || defined (SYSIII) || defined(BSD43)
#define N_KEY 4
struct key_map {
char *k_str;
char k_val;
char k_index;
};
struct key_map km[N_KEY];
char keyarea[N_KEY*10];
char *tgetstr();
char *getenv();
#ifdef TIOCSLTC
struct ltchars old_chars, new_chars;
#endif
char dont_use[] = {
ctl(z), ctl(r), ctl(l), ctl(b), ctl(c), ctl(f), ctl(g), ctl([),
ctl(h), ctl(m), ctl(j), ctl(n), ctl(p), ctl(q), ctl(s), ctl(t),
ctl(u), ctl(v), ctl(e), ctl(a), 0,
};
initkbd()
{
register struct key_map *kp;
register i,j;
char *ks;
char *p = keyarea;
static char buf[1024]; /* Why do I have to do this again? */
if (tgetent(buf, getenv("TERM")) <= 0)
return;
km[0].k_str = tgetstr("kl", &p); km[0].k_val = ctl(b);
km[1].k_str = tgetstr("kr", &p); km[1].k_val = ctl(f);
km[2].k_str = tgetstr("ku", &p); km[2].k_val = ctl(p);
km[3].k_str = tgetstr("kd", &p); km[3].k_val = ctl(n);
ks = tgetstr("ks",&p);
if (ks)
printf("%s",ks);
/* Unmap arrow keys which conflict with our ctl keys */
/* Ignore unset, longer than length 1, and 1-1 mapped keys */
for (i = 0; i < N_KEY; i++) {
kp = &km[i];
if (kp->k_str && (kp->k_str[1] == 0) && (kp->k_str[0] != kp->k_val))
for (j = 0; dont_use[j] != 0; j++)
if (kp->k_str[0] == dont_use[j]) {
kp->k_str = (char *)0;
break;
}
}
#ifdef TIOCSLTC
ioctl(fileno(stdin), TIOCGLTC, (char *)&old_chars);
new_chars = old_chars;
if (old_chars.t_lnextc == ctl(v))
new_chars.t_lnextc = -1;
if (old_chars.t_rprntc == ctl(r))
new_chars.t_rprntc = -1;
ioctl(fileno(stdin), TIOCSLTC, (char *)&new_chars);
#endif
}
resetkbd()
{
#ifdef TIOCSLTC
ioctl(fileno(stdin), TIOCSLTC, (char *)&old_chars);
#endif
}
nmgetch()
{
register int c;
register struct key_map *kp;
register struct key_map *biggest;
register int i;
int almost;
int maybe;
static char dumpbuf[10];
static char *dumpindex;
int timeout();
if (dumpindex && *dumpindex)
return (*dumpindex++);
c = getchar() & 0x7f;
biggest = 0;
almost = 0;
for (kp = &km[0]; kp < &km[N_KEY]; kp++) {
if (!kp->k_str)
continue;
if (c == kp->k_str[kp->k_index]) {
almost = 1;
kp->k_index++;
if (kp->k_str[kp->k_index] == 0) {
c = kp->k_val;
for (kp = &km[0]; kp < &km[N_KEY]; kp++)
kp->k_index = 0;
return(c);
}
}
if (!biggest && kp->k_index)
biggest = kp;
else if (kp->k_index && biggest->k_index < kp->k_index)
biggest = kp;
}
if (almost) {
signal(SIGALRM, timeout);
alarm(1);
if (setjmp(wakeup) == 0) {
maybe = nmgetch();
alarm(0);
return(maybe);
}
}
if (biggest) {
for (i = 0; i<biggest->k_index; i++)
dumpbuf[i] = biggest->k_str[i];
dumpbuf[i++] = c;
dumpbuf[i] = 0;
dumpindex = &dumpbuf[1];
for (kp = &km[0]; kp < &km[N_KEY]; kp++)
kp->k_index = 0;
return (dumpbuf[0]);
}
return(c);
}
#endif
#ifdef SYSV
initkbd()
{
keypad(stdscr, TRUE);
}
resetkbd()
{}
nmgetch()
{
register int c;
c = getch();
switch (c) {
case KEY_LEFT: c = ctl(b); break;
case KEY_RIGHT: c = ctl(f); break;
case KEY_UP: c = ctl(p); break;
case KEY_DOWN: c = ctl(n); break;
default: c = c & 0x7f;
}
return (c);
}
#endif /* SYSV */
#endif /* SIMPLE */
timeout()
{
longjmp(wakeup, -1);
}
int dbline;
/*VARARGS*/
void
debug (str)
char *str;
{
mvprintw (2+(dbline++%22),80-70,str);
clrtoeol();
}
/*
* This converts a floating point number of the form
* [s]ddd[.d*][esd*] where s can be a + or - and e is E or e.
* to floating point.
* p is advanced.
*/
char *
strtof(p, res)
register char *p;
double *res;
{
double acc;
int sign;
double fpos;
int exp;
int exps;
acc = 0.0;
sign = 1;
exp = 0;
exps = 1;
if (*p == '+')
p++;
else if (*p == '-') {
p++;
sign = -1;
}
while (isdigit(*p)) {
acc = acc * 10.0 + (double)(*p - '0');
p++;
}
if (*p == 'e' || *p == 'E') {
p++;
if (*p == '+')
p++;
else if (*p == '-') {
p++;
exps = -1;
}
while(isdigit(*p)) {
exp = exp * 10 + (*p - '0');
p++;
}
}
if (*p == '.') {
fpos = 1.0/10.0;
p++;
while(isdigit(*p)) {
acc += (*p - '0') * fpos;
fpos *= 1.0/10.0;
p++;
}
}
if (*p == 'e' || *p == 'E') {
exp = 0;
exps = 1;
p++;
if (*p == '+')
p++;
else if (*p == '-') {
p++;
exps = -1;
}
while(isdigit(*p)) {
exp = exp * 10 + (*p - '0');
p++;
}
}
if (exp) {
if (exps > 0)
while (exp--)
acc *= 10.0;
else
while (exp--)
acc *= 1.0/10.0;
}
if (sign > 0)
*res = acc;
else
*res = -acc;
return(p);
}
help () {
move(2,0);
clrtobot();
dbline = 0;
debug ("Cursor: ^n j next row ^p k prev. row ESC ^g erase cmd");
debug (" ^f l fwd col ^b h back col ^l ^r redraw screen");
debug (" 0 col A $ last col g goto ");
debug (" ^ row 0 # last row");
debug ("Cell: \" < > enter label = enter value x clear cell");
debug (" c copy cell m mark cell ^t line 1 on/off");
debug (" ^a type value ^e type expr. ^v type vbl name");
debug ("Row, Col: ar ac dup ir ic insert sr sc show");
debug (" dr dc delete zr zc hide pr pc pull");
debug (" vr vc value only f format");
debug ("Region: /c copy /x clear /f fill");
debug ("File: G get database M merge database T write tbl fmt");
debug (" P put database W write listing");
debug ("Misc: Q q quit pm pull (merge)");
debug ("Expr: +-*/^ arithmetic ?e:e conditional & | booleans");
debug (" < = > relations <= >= relations != relations");
debug (" @sum(v1:v2) @avg(v1:v2) @prod(v1:v2)");
debug (" @func(e) - lots of other math functions");
}
SHAR_EOF
if test 9305 -ne "`wc -c lex.c`"
then
echo shar: error transmitting lex.c '(should have been 9305 characters)'
fi
echo shar: extracting gram.y '(4962 characters)'
cat << \SHAR_EOF > gram.y
/* SC A Spreadsheet Calculator
* Command and expression parser
*
* original by James Gosling, September 1982
* modified by Mark Weiser and Bruce Israel,
* University of Maryland
*
* more mods Robert Bond 12/86
*
*/
%{
#include <curses.h>
#include "sc.h"
%}
%union {
int ival;
double fval;
struct ent *ent;
struct enode *enode;
char *sval;
}
%type <ent> var
%type <fval> num
%type <enode> e term
%token <sval> STRING
%token <ival> NUMBER
%token <fval> FNUMBER
%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_PROGLET
%token S_COPY
%token S_SHOW
%token S_ERASE
%token S_FILL
%token S_GOTO
%token K_FIXED
%token K_SUM
%token K_PROD
%token K_AVG
%token K_ACOS
%token K_ASIN
%token K_ATAN
%token K_CEIL
%token K_COS
%token K_EXP
%token K_FABS
%token K_FLOOR
%token K_HYPOT
%token K_LN
%token K_LOG
%token K_PI
%token K_POW
%token K_SIN
%token K_SQRT
%token K_TAN
%token K_DTR
%token K_RTD
%token K_MAX
%token K_MIN
%left '?' ':'
%left '|'
%left '&'
%nonassoc '<' '=' '>'
%left '+' '-'
%left '*' '/'
%left '^'
%%
command: S_LET var '=' e { let ($2, $4); }
| S_LABEL var '=' STRING
{ label ($2, $4, 0); }
| S_LEFTSTRING var '=' STRING
{ label ($2, $4, -1); }
| S_RIGHTSTRING var '=' STRING
{ label ($2, $4, 1); }
| S_FORMAT COL NUMBER NUMBER
{ fwidth[$2] = $3;
FullUpdate++;
modflg++;
precision[$2] = $4; }
| S_GET STRING { readfile ($2,1); }
| S_MERGE STRING { readfile ($2,0); }
| S_PUT STRING { (void) writefile ($2); }
| S_WRITE STRING { printfile ($2); }
| S_TBL STRING { tblprintfile ($2); }
| S_SHOW COL ':' COL { showcol( $2, $4); }
| S_SHOW NUMBER ':' NUMBER { showrow( $2, $4); }
| S_COPY var var ':' var { copy($2, $3, $5); }
| S_ERASE var ':' var { eraser($2, $4); }
| S_FILL var ':' var num num { fill($2, $4, $5, $6); }
| S_GOTO var {moveto($2); }
| /* nothing */
| error;
term: var { $$ = new_var('v', $1); }
| K_FIXED term { $$ = new ('f', (struct enode *)0, $2); }
| '@' K_SUM '(' var ':' var ')'
{ $$ = new (O_REDUCE('+'),
(struct enode *)$4, (struct enode *)$6); }
| '@' K_PROD '(' var ':' var ')'
{ $$ = new (O_REDUCE('*'),
(struct enode *)$4, (struct enode *)$6); }
| '@' K_AVG '(' var ':' var ')'
{ $$ = new (O_REDUCE('a'),
(struct enode *)$4, (struct enode *)$6); }
| '@' K_ACOS '(' e ')' { $$ = new(ACOS, (struct enode *)0, $4); }
| '@' K_ASIN '(' e ')' { $$ = new(ASIN, (struct 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_MAX '(' e ',' e ')' { $$ = new(MAX, $4, $6); }
| '@' K_MIN '(' e ',' e ')' { $$ = new(MIN, $4, $6); }
| '(' e ')' { $$ = $2; }
| '+' term { $$ = $2; }
| '-' term { $$ = new ('m', (struct enode *)0, $2); }
| NUMBER { $$ = new_const('k', (double) $1); }
| FNUMBER { $$ = new_const('k', $1); }
| K_PI { $$ = new_const('k', (double)3.14159265358979323846); }
| '~' term { $$ = new ('~', (struct enode *)0, $2); }
| '!' term { $$ = new ('~', (struct enode *)0, $2); }
;
e: e '+' 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)); }
;
var: COL NUMBER { $$ = lookat($2 , $1); };
num: NUMBER { $$ = (double) $1; }
| FNUMBER { $$ = $1; }
| '-' num { $$ = -$2; }
| '+' num { $$ = $2; }
;
SHAR_EOF
if test 4962 -ne "`wc -c gram.y`"
then
echo shar: error transmitting gram.y '(should have been 4962 characters)'
fi
echo shar: extracting interp.c '(17239 characters)'
cat << \SHAR_EOF > interp.c
/* 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 *malloc();
#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 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'):
{ register r,c;
register maxr, maxc;
register minr, minc;
maxr = ((struct ent *) e->e.o.right) -> row;
maxc = ((struct ent *) e->e.o.right) -> col;
minr = ((struct ent *) e->e.o.left) -> row;
minc = ((struct ent *) e->e.o.left) -> col;
if (minr>maxr) r = maxr, maxr = minr, minr = r;
if (minc>maxc) c = maxc, maxc = minc, minc = c;
switch (e->op) {
case O_REDUCE('+'): return dosum(minr, minc, maxr, maxc);
case O_REDUCE('*'): return doprod(minr, minc, maxr, maxc);
case O_REDUCE('a'): return doavg(minr, minc, maxr, maxc);
}
}
case ACOS: return (acos(eval(e->e.o.right)));
case ASIN: return (asin(eval(e->e.o.right)));
case ATAN: return (atan(eval(e->e.o.right)));
case CEIL: return (ceil(eval(e->e.o.right)));
case COS: return (cos(eval(e->e.o.right)));
case EXP: return (exp(eval(e->e.o.right)));
case FABS: return (fabs(eval(e->e.o.right)));
case FLOOR: return (floor(eval(e->e.o.right)));
case HYPOT: return (hypot(eval(e->e.o.left), eval(e->e.o.right)));
case LOG: return (log(eval(e->e.o.right)));
case LOG10: return (log10(eval(e->e.o.right)));
case POW: return (pow(eval(e->e.o.left), eval(e->e.o.right)));
case SIN: return (sin(eval(e->e.o.right)));
case SQRT: return (sqrt(eval(e->e.o.right))) ^t line 1 on/off");
debug (" ^a type value ^e type expr. ^v type vbl name");
debug ("Row, Col: ar ac dup ir ic insert sr sc show");
debug (" dr dc delete zr zc hide pr pc pull");
debug (" vr vc value only f format");
debug ("Region: /c copy /x clear /f fill");
debug ("File: G get database M merge database T write tbl fmt");
debug (" P put database W write listing");
debug ("Misc: Q q quit pm pull (merge)");
debug ("Expr: +-*/^ arithmetic ?e:e conditional & | booleans");
debug (" < = > relations <= >= relations != relations");
debug (" @sum(v1:v2) @avg(v1:v2) @prod(v1:v2)");
debug (" @func(e) - lots of other math functions");
}
SHAR_EOF
if test 9305 -ne "`wc -c lex.c`"
then
echo shar: error transmitting lex.c '(should have been 9305 characters)'
fi
echo shar: extracting gram.y '(4962 characters)'
cat << \SHAR_EOF > gram.y
/* SC A Spreadsheet Calculator
* Command and expression parser
*
* original by James Gosling, September 1982
* modified by Mark Weiser and Bruce Israel,
* University of Maryland
*
* more mods Robert Bond 12/86
*
*/
%{
#include <curses.h>
#include "sc.h"
%}
%union {
int ival;
double fval;
struct ent *ent;
struct enode *enode;
char *sval;
}
%type <ent> var
%type <fval> num
%type <enode> e term
%token <sval> STRING
%token <ival> NUMBER
%token <fval> FNUMBER
%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_PROGLET
%token S_COPY
%token S_SHOW
%token S_ERASE
%token S_FILL
%token S_GOTO
%token K_FIXED
%token K_SUM
%token K_PROD
%token K_AVG
%token K_ACOS
%token K_ASIN
%token K_ATAN
%token K_CEIL
%token K_COS
%token K_EXP
%token K_FABS
%token K_FLOOR
%token K_HYPOT
%token K_LN
%token K_LOG
%token K_PI
%token K_POW
%token K_SIN
%token K_SQRT
%token K_TAN
%token K_DTR
%token K_RTD
%token K_MAX
%token K_MIN
%left '?' ':'
%left '|'
%left '&'
%nonassoc '<' '=' '>'
%left '+' '-'
%left '*' '/'
%left '^'
%%
command: S_LET var '=' e { let ($2, $4); }
| S_LABEL var '=' STRING
{ label ($2, $4, 0); }
| S_LEFTSTRING var '=' STRING
{ label ($2, $4, -1); }
| S_RIGHTSTRING var '=' STRING
{ label ($2, $4, 1); }
| S_FORMAT COL NUMBER NUMBER
{ fwidth[$2] = $3;
FullUpdate++;
modflg++;
precision[$2] = $4; }
| S_GET STRING { readfile ($2,1); }
| S_MERGE STRING { readfile ($2,0); }
| S_PUT STRING { (void) writefile ($2); }
| S_WRITE STRING { printfile ($2); }
| S_TBL STRING { tblprintfile ($2); }
| S_SHOW COL ':' COL { showcol( $2, $4); }
| S_SHOW NUMBER ':' NUMBER { showrow( $2, $4); }
| S_COPY var var ':' var { copy($2, $3, $5); }
| S_ERASE var ':' var { eraser($2, $4); }
| S_FILL var ':' var num num { fill($2, $4, $5, $6); }
| S_GOTO var {moveto($2); }
| /* nothing */
| error;
term: var { $$ = new_var('v', $1); }
| K_FIXED term { $$ = new ('f', (struct enode *)0, $2); }
| '@' K_SUM '(' var ':' var ')'
{ $$ = new (O_REDUCE('+'),
(struct enode *)$4, (struct enode *)$6); }
| '@' K_PROD '(' var ':' var ')'
{ $$ = new (O_REDUCE('*'),
(struct enode *)$4, (struct enode *)$6); }
| '@' K_AVG '(' var ':' var ')'
{ $$ = new (O_REDUCE('a'),
(struct enode *)$4, (struct enode *)$6); }
| '@' K_ACOS '(' e ')' { $$ = new(ACOS, (struct enode *)0, $4); }
| '@' K_ASIN '(' e ')' { $$ = new(ASIN, (struct 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_MAX '(' e ',' e ')' { $$ = new(MAX, $4, $6); }
| '@' K_MIN '(' e ',' e ')' { $$ = new(MIN, $4, $6); }
| '(' e ')' { $$ = $2; }
| '+' term { $$ = $2; }
| '-' term { $$ = new ('m', (struct enode *)0, $2); }
| NUMBER { $$ = new_const('k', (double) $1); }
| FNUMBER { $$ = new_const('k', $1); }
| K_PI { $$ = new_const('k', (double)3.14159265358979323846); }
| '~' term { $$ = new ('~', (struct enode *)0, $2); }
| '!' term { $$ = new ('~', (struct enode *)0, $2); }
;
e: e '+' 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)); }
;
var: COL NUMBER { $$ = lookat($2 , $1); };
num: NUMBER { $$ = (double) $1; }
| FNUMBER { $$ = $1; }
| '-' num { $$ = -$2; }
| '+' num { $$ = $2; }
;
SHAR_EOF
if test 4962 -ne "`wc -c gram.y`"
then
echo shar: error transmitting gram.y '(should have been 4962 characters)'
fi
echo shar: extracting interp.c '(17239 characters)'
cat << \SHAR_EOF > interp.c
/* 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 *malloc();
#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 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'):
{ register r,c;
register maxr, maxc;
register minr, minc;
maxr = ((struct ent *) e->e.o.right) -> row;
maxc = ((struct ent *) e->e.o.right) -> col;
minr = ((struct ent *) e->e.o.left) -> row;
minc = ((struct ent *) e->e.o.left) -> col;
if (minr>maxr) r = maxr, maxr = minr, minr = r;
if (minc>maxc) c = maxc, maxc = minc, minc = c;
switch (e->op) {
case O_REDUCE('+'): return dosum(minr, minc, maxr, maxc);
case O_REDUCE('*'): return doprod(minr, minc, maxr, maxc);
case O_REDUCE('a'): return doavg(minr, minc, maxr, maxc);
}
}
case ACOS: return (acos(eval(e->e.o.right)));
case ASIN: return (asin(eval(e->e.o.right)));
case ATAN: return (atan(eval(e->e.o.right)));
case CEIL: return (ceil(eval(e->e.o.right)));
case COS: return (cos(eval(e->e.o.right)));
case EXP: return (exp(eval(e->e.o.right)));
case FABS: return (fabs(eval(e->e.o.right)));
case FLOOR: return (floor(eval(e->e.o.right)));
case HYPOT: return (hypot(eval(e->e.o.left), eval(e->e.o.right)));
case LOG: return (log(eval(e->e.o.right)));
case LOG10: return (log10(eval(e->e.o.right)));
case POW: return (pow(eval(e->e.o.left), eval(e->e.o.right)));
case SIN: return (sin(eval(e->e.o.right)));
case SQRT: return (sqrt(eval(e->e.o.right)));
case TAN: return (tan(eval(e->e.o.right)));
case DTR: return (dtr(eval(e->e.o.right)));
case RTD: return (rtd(eval(e->e.o.right)));
case MIN: {
double left, right;
left = eval(e->e.o.left);
right = eval(e->e.o.right);
return (left < right ? left : right);
}
case MAX: {
double left, right;
left = eval(e->e.o.left);
right = eval(e->e.o.right);
return (left > right ? left : right);
}
}
return((double) 0.0); /* safety net */
}
#define MAXPROP 7
EvalAll () {
int repct = 0;
while (RealEvalAll() && (repct++ <= MAXPROP));
}
int RealEvalAll () {
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 *) malloc ((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 *) malloc ((unsigned)sizeof (struct enode));
p->op = op;
p->e.v = a1;
return p;
}
struct enode *new_const(op, a1)
double a1;
{
register struct enode *p = (struct enode *) malloc ((unsigned)sizeof (struct enode));
p->op = op;
p->e.k = a1;
return p;
}
copy (dv, v1, v2)
struct ent *dv, *v1, *v2;
{
register r,c;
register struct ent *p;
register struct ent *n;
register deltar, deltac;
int maxr, maxc;
int minr, minc;
int dr, dc;
dr = dv->row;
dc = dv->col;
maxr = v2->row;
maxc = v2->col;
minr = v1->row;
minc = v1->col;
if (minr>maxr) r = maxr, maxr = minr, minr = r;
if (minc>maxc) c = maxc, maxc = minc, minc = c;
if (dr+maxr-minr >= MAXROWS ||
dc+maxc-minc >= MAXCOLS) {
error ("The table can't be any bigger");
return;
}
deltar = dr-minr;
deltac = dc-minc;
FullUpdate++;
for (r = minr; r<=maxr; r++)
for (c = minc; c<=maxc; c++) {
n = lookat (r+deltar, c+deltac);
clearent(n);
if (p = tbl[r][c]) {
n -> v = p -> v;
n -> flags = p -> flags;
n -> expr = copye(p->expr, deltar, deltac);
n -> label = 0;
if (p -> label) {
n -> label = malloc ((unsigned)(strlen (p -> label) + 1));
strcpy (n -> label, p -> label);
}
}
}
}
eraser(v1, v2)
struct ent *v1, *v2;
{
FullUpdate++;
flush_saved();
erase_area(v1->row, v1->col, v2->row, v2->col);
}
moveto(v)
struct 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
More information about the Comp.sources.unix
mailing list