[net.sources] Trimmed down spread sheet program for U**X/VMS/AMIGA, happy taxes!

wecker@cookie.dec.com (DAVE CUM GRANO SALIS WECKER) (01/18/87)

This is an updated version of the public domain spreadsheet released recently
by Bob Bond (called at the time: vc (don't flame at me :-)).

This version is designed for people with varying systems:

	1) FIXES A **MAJOR** bug. If you use numbers in the 10000 - 99999
	   range and save the table, then get back in and restore it (P,G)
	   numbers will be rounded to 1 place accuracy (e.g., 12345.67
	   becomes 12345.7 (not too good for taxes!!!)).

	   Simple fix:  replace the two occurances of "%g" in interp.c with
			"%.8g"

	2) uses no TERMCAP file or facilities (expects a VT100 class terminal)
	3) uses no system CURSES package (has its own (sort of) built in)
	4) Runs on any U**X, VMS or AMIGA system (plus probably lots more)
	   (define either VMS, U__X, or MCH_AMIGA to your compiler)
	5) Does not require YACC (output already pre-built)
	6) Does not require nroff (compiled man page provided)

Enjoy!!
dave	(decwrl.dec.com!cookie.dec.com!wecker)

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	README
#	vc.man
#	makefile.amiga
#	sc.c
#	lex.c
#	gram.c
#	interp.c
#	cmds.c
#	curses.c
#	experres.h
#	sc.h
#	statres.h
#	y.tab.h
# This archive created: Sat Jan 17 16:31:12 1987
echo shar: extracting README
sed 's/^XX//' << \SHAR_EOF > README
XXThis is a much modified version of the public domain spread sheet vc,
XXposted a year or two ago by Mark Weiser, orginally by James Gosling
XX
XXI have completely reworked the user interface.  The save file format is
XXdifferent so I have included a sed script, cvt.sed, which will convert to
XXthe new file formats.  I have also added lots of new features and fixed
XXlots of bugs.  Any bugs you find at this point are probably mine.
XXI would love to hear from you if you have any problems.
XX
XXThe code has been tested against a Vax running 4.2 and a National ICM-3216 
XXwith system V.2.  The ICM has a National Semi 32016.  Just check the makefile
XXfor the system flags.
XX
XXGood luck with the tax man.
XX
XX					Bob Bond
XX
XX    Robert Bond 			ihnp4!nsc!nscpdc!rgb
XX    National Semiconductor		tektronix!nscpdc!rgb
SHAR_EOF
if test 790 -ne "`wc -c README`"
then
echo shar: error transmitting README '(should have been 790 characters)'
fi
echo shar: extracting vc.man
sed 's/^XX//' << \SHAR_EOF > vc.man
XX
XX
XX
XX     VC(1)                       UNIX 3.0                        VC(1)
XX
XX
XX
XX     NAME
XX          vc - spread sheet calculator ("visicalc-like")
XX
XX     SYNOPSIS
XX          vc [ _f_i_l_e ]
XX
XX
XX     DESCRIPTION
XX          _V_c is a calculator that is based on rectangular tables, in
XX          much the same style as Visicalc or Lotus 123.  When it is
XX          invoked it presents you with an empty table organised as
XX          rows and columns of cells.  Each cell may have a label
XX          string associated with it and an expression.  The expression
XX          may be a constant or it may compute something based on other
XX          entries.
XX
XX          When _v_c is running, the screen is divided into four regions:
XX          the top line is for entering commands, the second line is
XX          for messages from _v_c, the third line and the first four
XX          columns show the row and column numbers, and the rest of the
XX          screen forms a window looking at the table.  _v_c has two
XX          cursors: a cell cursor (indicated by a '<' on the screen)
XX          and a character cursor (indicated by the terminals hardware
XX          cursor).  The cell and character cursors are often the same.
XX          They will differ when a long command is being typed on the
XX          top line.
XX
XX          Commands which use the terminal's control key will work when
XX          either a long command is being typed or in "normal" mode.
XX
XX          The cursor control commands and the row, column commands can
XX          be prefixed by a numeric argument indicating how many times
XX          the command is to be executed.  "^U" can be used before the
XX          number if the cursor movement is to take place while a
XX          command is being typed into the command line.
XX
XX          Cursor control commands:
XX
XX
XX          ^N   Move the cell cursor to the next row.
XX
XX
XX          ^P   Move the cell cursor to the previous row.
XX
XX
XX          ^F   Move the cell cursor forward one column.
XX
XX
XX          ^B   Move the cell cursor backward one column.
XX
XX
XX          ^H   Backspace one character.
XX
XX
XX
XX     Page 1                                           (printed 1/5/87)
XX
XX
XX
XX
XX
XX
XX     VC(1)                       UNIX 3.0                        VC(1)
XX
XX
XX
XX          h, j, k, l
XX               Alternate cursor controls (left, down, up, right).
XX
XX
XX          0    Move the cell cursor to column 0 of the current row.
XX
XX
XX          $    Move the cell cursor to the last valid column in the
XX               current row.
XX
XX
XX          Cell entry and editing commands:
XX
XX
XX          =    Prompts for an expression which will be evaluated
XX               dynamically to produce a value for the cell pointed at
XX               by the cell cursor.  This may be used in conjunction
XX               with ^V to make one entries value be dependent on
XX               anothers.
XX
XX
XX          "    Enter a label for the current cell.
XX
XX
XX          <    Enter a label that will be flushed left against the
XX               left edge of the cell.
XX
XX
XX          >    Enter a label that will be flushed right against the
XX               right edge of the cell.
XX
XX
XX          x    Clears the current cell.
XX
XX
XX          e    Edit the value associated with the current cell.  This
XX               is identical to '=' except that the command line starts
XX               out containing the old value or expression associated
XX               with the cell.
XX
XX
XX          E    Edit the string associated with the current cell.  This
XX               is the same as either "leftstring", "rightstring", or
XX               "label", with the additional fact that the command line
XX               starts out with the old string.
XX
XX
XX          m    Mark a cell to be used as the source for the copy
XX               command.
XX
XX
XX          c    Copy the last marked cell to the current cell, updating
XX
XX
XX
XX     Page 2                                           (printed 1/5/87)
XX
XX
XX
XX
XX
XX
XX     VC(1)                       UNIX 3.0                        VC(1)
XX
XX
XX
XX               the row and column references.
XX
XX
XX          ^T   Toggle cell display.  The current cell's contents are
XX               displayed in line one when no command being entered or
XX               edited.  ^T turns the display on or off.
XX
XX
XX          File operations
XX
XX
XX          G    Get a new database from a file.
XX
XX
XX          P    Put the current database into a file.
XX
XX
XX          W    Write a listing of the current database in a form that
XX               matches its appearance on the screen.  This differs
XX               from the "put" command in that "put"s files are
XX               intended to be reloaded with "get", while "write"
XX               produces a file for people to look at.
XX
XX
XX          T    Write a listing of the current database to a file, but
XX               put ":"s between each field.  This  is useful for
XX               tables that will be further formatted by the _t_b_l
XX               preprocessor of _n_r_o_f_f.
XX
XX
XX          M    Merges the database from the named file into the
XX               current database.  Values, expressions and names
XX               defined in the named file are written into the current
XX               file, overwriting the existing entries at those
XX               locations.
XX
XX
XX          Row and Column operations.  Members of this class of
XX          commands can be used on either rows or columns.  The second
XX          letter of the command is either a column designator (one of
XX          the characters c, j, k, ^N, ^p) or a row designator (one of
XX          r, l, h, ^B, ^F).  Commands which move or copy cells also
XX          modify the variable references in affected cell expressions.
XX          Variable references may be frozen by using the "fixed"
XX          operator.
XX
XX
XX          ar, ac
XX               Creates a new row (column) immediately following the
XX               current row (column).  It is initialized to be a copy
XX               of the current one.
XX
XX
XX
XX
XX     Page 3                                           (printed 1/5/87)
XX
XX
XX
XX
XX
XX
XX     VC(1)                       UNIX 3.0                        VC(1)
XX
XX
XX
XX          dr, dc
XX               Delete this row (column).
XX
XX
XX          pr, pc, pm
XX               Pull deleted rows (columns) back into the spread sheet.
XX               The last deleted set of cells is put back into the
XX               spread sheet at the current location.  _P_r inserts
XX               enough rows to hold the data.  _P_c inserts enough
XX               columns to hold the data.  _P_m (merge) does not insert
XX               rows or columns, but overwrites the cells beginning at
XX               the current cursor location.
XX
XX
XX          ir, ic
XX               Insert a new row (column) by moving the row (column)
XX               containing the cell cursor, and all following, down
XX               (right) one.  The new position will be empty.
XX
XX
XX          zr, zc
XX               Hide ("zap") the current row (column).  This keeps a
XX               row or column from being displayed but keeps it in the
XX               data base.
XX
XX
XX          vr, vc
XX               Removes expressions from the affected rows (columns),
XX               leaving only the values which were in the cells before
XX               the command was executed.
XX
XX
XX          sr, sc
XX               Show hidden rows (columns).  Type in a range of rows or
XX               columns to be revealed.  The command default is the
XX               first range of rows or columns currently hidden.
XX
XX
XX          f    Sets the output format to be used for printing the
XX               numbers in each cell in the current column.  Type in
XX               two numbers which will be the width in characters of a
XX               column and the number of digits which will follow the
XX               decimal point.  Note that this command has only a
XX               column version and does have a second letter.
XX
XX
XX          Miscellaneous commands:
XX
XX
XX          ^C   Exit from _v_c.  If you were editing a named file, and
XX               you modified it, then it will ask about saving before
XX               exiting.
XX
XX
XX
XX     Page 4                                           (printed 1/5/87)
XX
XX
XX
XX
XX
XX
XX     VC(1)                       UNIX 3.0                        VC(1)
XX
XX
XX
XX          q    Alternate exit command.
XX
XX
XX          ?    Types a brief helpful message.
XX
XX
XX          /    Copy a region to the area specified by the current
XX               cell.
XX
XX
XX          ^G or ESC
XX               Abort the current long command.
XX
XX
XX          ^R   Redraw the screen.
XX
XX
XX          ^V   Types, in the long command line, the name of the cell
XX               being pointed at by the cell cursor.  This is used when
XX               typing in expressions to refer to entries in the table.
XX
XX
XX          ^E   Types, in the long command line, the expression of the
XX               cell being pointed at by the cell cursor.
XX
XX
XX          ^A   Types, in the long command line, the value of the cell
XX               being pointed at by the cell cursor.
XX
XX
XX          Expressions that are used with the '=' and 'e' commands have
XX          a fairly conventional syntax.  Terms may be variable names
XX          (from the ^V command), parenthesised expressions, negated
XX          terms, and constants. Rectangular regions of the screen may
XX          be operated upon with '@' functions such as sum (@sum),
XX          average (@avg) and product (@prod).  Terms may be combined
XX          using many binary operators.  Their precedences (from
XX          highest to lowest) are: *,/; +,-; <,=,>,<=,>=; &; |; ?.
XX
XX
XX          e+e            Addition.
XX
XX
XX          e-e            Subtraction.
XX
XX
XX          e*e            Multiplication.
XX
XX
XX          e/e            Division.
XX
XX
XX
XX
XX
XX     Page 5                                           (printed 1/5/87)
XX
XX
XX
XX
XX
XX
XX     VC(1)                       UNIX 3.0                        VC(1)
XX
XX
XX
XX          @sum(v:v)      Sum all valid (nonblank) entries in the
XX                         region whose two corners are defined by the
XX                         two variable (cell) names given.
XX
XX
XX          @avg(v:v)      Average all valid (nonblank) entries in the
XX                         region whose two corners are defined by the
XX                         two variable (cell) names given.
XX
XX
XX          @prod(v:v)     Multiply together all valid (nonblank)
XX                         entries in the region whose two corners are
XX                         defined by the two variable (cell) names
XX                         given.
XX
XX
XX          e?e:e          Conditional: If the first expression is true
XX                         then the value of the second is returned,
XX                         otherwise the value of the third is.
XX
XX
XX          <,=,>,<=,>=    Relationals: true iff the indicated relation
XX                         holds.
XX
XX
XX          &,|            Boolean connectives.
XX
XX
XX          fixed          To make a variable not change automatically
XX                         when a cell moves, put the word fixed in
XX                         front of the reference.  I.e.  B1*fixed C3
XX
XX
XX
XX     SEE ALSO
XX          bc(1), dc(1)
XX
XX
XX     BUGS
XX          Expression reevaluation is done in the same top-to-bottom,
XX          left-to-right manner as is done in other spread sheet
XX          calculators.  This is silly.  A proper following of the
XX          dependency graph with (perhaps) recourse to relaxation
XX          should be implemented.
XX
XX          At most 200 rows and 40 columns.
XX
XX
XX
XX
XX
XX
XX
XX
XX
XX     Page 6                                           (printed 1/5/87)
XX
XX
XX
SHAR_EOF
if test 11422 -ne "`wc -c vc.man`"
then
echo shar: error transmitting vc.man '(should have been 11422 characters)'
fi
echo shar: extracting makefile.amiga
sed 's/^XX//' << \SHAR_EOF > makefile.amiga
XX#	Make file for AMIAG version of DBW_VC
XX#
XX#	v1.0	870117	DBW
XX#
XX
XX# On U**X systems, compile with:
XX#	% cc -c -DU__X -O file.c
XX#
XX# On VMS system, compile with:
XX#	$ cc/define=VMS file.c
XX#	also.... rename y.tab.h to y_tab.h
XX
XXOBJS	= sc.o lex.o gram.o interp.o cmds.o curses.o
XXINCL	= experres.h sc.h statres.h y.tab.h
XXDOCS	= README vc.man
XX
XXvc :	$(OBJS)
XX	ln -v -o vc $(OBJS) df0:lib/m.lib df0:lib/c.lib
XX
XXlex.o :	lex.c $(INCL)
XX	cc lex.c
XX
XXinterp.o : interp.c $(INCL)
XX	cc interp.c
XX
XXsc.o : sc.c $(INCL)
XX	cc sc.c
XX
XXcmds.o : cmds.c $(INCL)
XX	cc cmds.c
XX
XXcurses.o : curses.c $(INCL)
XX	cc curses.c
XX
XXgram.o : gram.c $(INCL)
XX	cc gram.c
XX
SHAR_EOF
if test 614 -ne "`wc -c makefile.amiga`"
then
echo shar: error transmitting makefile.amiga '(should have been 614 characters)'
fi
echo shar: extracting sc.c
sed 's/^XX//' << \SHAR_EOF > sc.c
XX/*	SC	A Spreadsheet Calculator
XX *		Main driver
XX *
XX *		original by James Gosling, September 1982
XX *		modifications by Mark Weiser and Bruce Israel,
XX *			University of Maryland
XX *
XX *              More mods Robert Bond, 12/86
XX *		Major mods to run on VMS and AMIGA, 1/17/87
XX *
XX */
XX
XX#include "sc.h"
XX
XXextern char *malloc();
XX
XX/* default column width */
XX
XX#define DEFWIDTH 10
XX#define DEFPREC   2
XX
XX#define RESCOL 4  /* columns reserved for row numbers */
XX#define RESROW 3  /* rows reserved for prompt, error, and column numbers */
XX
XXchar curfile[1024];
XX
XXint showme = 1;  /* 1 to display the current cell in the top line */
XXint batch = 0;
XX
XXerror (fmt,a,b,c,d,e) {
XX    if (batch) fprintf(stderr,fmt,a,b,c,d,e);
XX    else {
XX	move (1,0);
XX	clrtoeol ();
XX	printw (fmt,a,b,c,d,e);
XX    }
XX}
XX
XXint seenerr;
XX
XXyyerror (err)
XXchar *err; {
XX    if (seenerr) return;
XX    seenerr++;
XX    move (1,0);
XX    clrtoeol ();
XX    printw ("%s: %.*s <= %s",err,linelim,line,line+linelim);
XX}
XX
XXstruct ent *
XXlookat(row,col){
XX    register struct ent **p;
XX    if (row < 0)
XX	row = 0;
XX    else if (row > MAXROWS-1) 
XX	row = MAXROWS-1;
XX    if (col < 0) 
XX	col = 0;
XX    else if (col > MAXCOLS-1)
XX	col = MAXCOLS-1;
XX    p = &tbl[row][col];
XX    if (*p==0) {
XX	*p = (struct ent *) malloc (sizeof (struct ent));
XX	if (row>maxrow) maxrow = row;
XX	if (col>maxcol) maxcol = col;
XX	(*p)->label = 0;
XX	(*p)->flags = 0;
XX	(*p)->row = row;
XX	(*p)->col = col;
XX	(*p)->expr = 0;
XX	(*p)->v = (double) 0.0;
XX    } else if ((*p)->flags & is_deleted) 
XX	debug("But %s%d has been deleted!", coltoa(col), row);
XX    return *p;
XX}
XX
XX/*
XX * This structure is used to keep ent structs around before they
XX * are deleted to allow the sync_refs routine a chance to fix the
XX * variable references.
XX * We also use it as a last-deleted buffer for the 'p' command.
XX */
XX
XXfree_ent(p)
XXregister struct ent *p;
XX{
XX    p->next = to_fix;
XX    to_fix = p;
XX    p->flags |= is_deleted;
XX}
XX
XXflush_saved()
XX{
XX    register struct ent *p;
XX    register struct ent *q;
XX
XX    if (!(p = to_fix))
XX	return;
XX    while (p) {
XX	clearent(p);
XX	q = p->next;
XX	free(p);
XX	p = q;
XX    }
XX    to_fix = 0;
XX}
XX
XXupdate () {
XX    register    row,
XX                col;
XX    register struct ent **p;
XX    static  lastmx,
XX            lastmy;
XX    static  char *under_cursor = " ";
XX    int     maxcol;
XX    int     maxrow;
XX    int     rows;
XX    int     cols;
XX    register r;
XX
XX    while (hidden_row[currow])   /* You can't hide the last row or col */
XX	currow++;
XX    while (hidden_col[curcol])
XX	curcol++;
XX    if (curcol < stcol)
XX	stcol = curcol, FullUpdate++;
XX    if (currow < strow)
XX	strow = currow, FullUpdate++;
XX    while (1) {
XX	register    i;
XX	for (i = stcol, cols = 0, col = RESCOL;
XX	     (col + fwidth[i]) < COLS-1 && i < MAXCOLS; i++) {
XX	    cols++;
XX	    if (hidden_col[i])
XX		continue;
XX	    col += fwidth[i];
XX	}
XX	if (curcol >= stcol + cols)
XX	    stcol++, FullUpdate++;
XX	else
XX	    break;
XX    }
XX    while (1) {
XX	register    i;
XX	for (i = strow, rows = 0, row = RESROW;
XX	     row < ROWS && i < MAXROWS; i++) {
XX	    rows++;
XX	    if (hidden_row[i])
XX		continue;
XX	    row++;
XX	}
XX	if (currow >= strow + rows)
XX	    strow++, FullUpdate++;
XX	else
XX	    break;
XX    }
XX    maxcol = stcol + cols - 1;
XX    maxrow = strow + rows - 1;
XX    if (FullUpdate) {
XX	register int i;
XX	move (2, 0);
XX	clrtobot ();
XX	standout();
XX	for (row=RESROW, i=strow; i <= maxrow; i++) {
XX	    if (hidden_row[i]) 
XX		continue;
XX	    move(row,0);
XX	    printw("%-*d", RESCOL, i);
XX	    row++;
XX	}
XX	move (2,0);
XX	printw("%*s", RESCOL, " ");
XX	for (col=RESCOL, i = stcol; i <= maxcol; i++) {
XX	    if (hidden_col[i])
XX		continue;
XX	    move(2, col);
XX	    printw("%*s", fwidth[i], coltoa(i));
XX	    col += fwidth[i];
XX	}
XX	standend();
XX    }
XX    for (row = strow, r = RESROW; row <= maxrow; row++) {
XX	register    c = RESCOL;
XX	if (hidden_row[row])
XX	    continue;
XX	for (p = &tbl[row][col = stcol]; col <= maxcol; col++, p++) {
XX	    if (hidden_col[col])
XX		continue;
XX	    if (*p && ((*p) -> flags & is_changed || FullUpdate)) {
XX		char   *s;
XX		move (r, c);
XX		(*p) -> flags &= ~is_changed;
XX		if ((*p) -> flags & is_valid)
XX		    printw ("%*.*f", fwidth[col], precision[col], (*p) -> v);
XX		if (s = (*p) -> label) {
XX		    char field[1024];
XX
XX		    strncpy(field,s,fwidth[col]);
XX		    field[fwidth[col]] = 0;
XX		    move (r,(*p) -> flags & is_leftflush
XX			    ? c : c - strlen (field) + fwidth[col]);
XX		    addstr(field);
XX		}
XX	    }
XX	    c += fwidth[col];
XX	}
XX	r++;
XX    }
XX    
XX    move(lastmy, lastmx);
XX    if (inch() == '<')
XX        addstr (under_cursor);
XX    lastmy =  RESROW;
XX    for (row = strow; row < currow; row++)
XX	if (!hidden_row[row])
XX		lastmy += 1;
XX    lastmx = RESCOL;
XX    for (col = stcol; col <= curcol; col++)
XX	if (!hidden_col[col])
XX		lastmx += fwidth[col];
XX    move(lastmy, lastmx);
XX    *under_cursor = inch();
XX    addstr ("<");
XX    move (0, 0);
XX    clrtoeol ();
XX    if (linelim >= 0) {
XX	addstr (">> ");
XX	addstr (line);
XX    } else {
XX	if (showme) {
XX	    register struct ent *p;
XX	    p = tbl[currow][curcol];
XX	    if (p && ((p->flags & is_valid) || p->label)) {
XX		if (p->expr || !p->label) {
XX		    linelim = 0;
XX		    editexp(currow, curcol);
XX		} else {
XX		    sprintf(line, "%s", p->label);
XX		}
XX		addstr("[");
XX		addstr (line);
XX		addstr("]");
XX		linelim = -1;
XX	    } else {
XX		addstr("[]");
XX	    }
XX	}
XX	move (lastmy, lastmx);
XX    }
XX    FullUpdate = 0;
XX}
XX
XXvoid
XXquit()
XX{
XX    endwin ();
XX    exit();
XX}
XX
XXmain (argc, argv)
XXchar  **argv; {
XX    int     inloop = 1;
XX    register int   c;
XX    int     edistate = -1;
XX    int     arg = 1;
XX    int     narg;
XX    int     nedistate = -1;
XX    int	    running = 1;
XX    {
XX	register    i;
XX	for (i = 0; i < MAXCOLS; i++) {
XX	    fwidth[i] = DEFWIDTH;
XX	    precision[i] = DEFPREC;
XX	}
XX    }
XX    linelim = -1;
XX    curfile[0]=0;
XX    running = 1;
XX
XX    if (argc > 1 && (! strcmp(argv[1],"-b"))) {
XX	argc--, argv++;
XX	batch = 1;
XX    }
XX
XX    if (! batch) {
XX	initscr ();
XX    }
XX    initkbd();
XX    if (argc > 1) {
XX	strcpy(curfile,argv[1]);
XX	readfile (argv[1],0);
XX    }
XX    modflg = 0;
XX    if (batch) exit(0);
XX    error ("VC 2.1  Type '?' for help.");
XX    FullUpdate++;
XX    while (inloop) { running = 1;
XX    while (running) {
XX	nedistate = -1;
XX	narg = 1;
XX	if (edistate < 0 && linelim < 0 && (changed || FullUpdate))
XX	    EvalAll (), changed = 0;
XX	update ();
XX	refresh ();
XX	move (1, 0);
XX	clrtoeol ();
XX	fflush (stdout);
XX	seenerr = 0;
XX	if (((c = nmgetch ()) < ' ') || ( c == 0177 ))
XX	    switch (c) {
XX		case ctl (z):
XX		    quit();
XX		    break;
XX		case ctl (r):
XX		    FullUpdate++;
XX		    touchwin();
XX		    clear();
XX		    break;
XX		default:
XX		    error ("No such command  (^%c)", c + 0100);
XX		    break;
XX		case ctl (b):
XX		    while (--arg>=0) {
XX			if (curcol)
XX			    curcol--;
XX			else
XX			    error ("At column A");
XX			while(hidden_col[curcol] && curcol)
XX			    curcol--;
XX		    }
XX		    break;
XX		case ctl (c):
XX		    running = 0;
XX		    break;
XX		case ctl (f):
XX		    while (--arg>=0) {
XX			if (curcol < MAXCOLS - 1)
XX			    curcol++;
XX			else
XX			    error ("The table can't be any wider");
XX			while(hidden_col[curcol]&&(curcol<MAXCOLS-1))
XX			    curcol++;
XX		    }
XX		    break;
XX		case ctl (g):
XX		case ctl ([):
XX		    linelim = -1;
XX		    move (1, 0);
XX		    clrtoeol ();
XX		    break;
XX		case 0177:
XX		case ctl (h):
XX		    while (--arg>=0) if (linelim > 0)
XX			line[--linelim] = 0;
XX		    break;
XX		case ctl (l):
XX		    FullUpdate++;
XX		    break;
XX		case ctl (m):
XX		    if (linelim < 0)
XX			line[linelim = 0] = 0;
XX		    else {
XX			linelim = 0;
XX			yyparse ();
XX			linelim = -1;
XX		    }
XX		    break;
XX		case ctl (n):
XX		    while (--arg>=0) {
XX			if (currow < MAXROWS - 1)
XX			    currow++;
XX			else
XX			    error ("The table can't be any longer");
XX			while (hidden_row[currow] && (currow < MAXROWS - 1))
XX			    currow++;
XX		    }
XX		    break;
XX		case ctl (p):
XX		    while (--arg>=0) {
XX			if (currow)
XX			    currow--;
XX			else
XX			    error ("At row zero");
XX			while (hidden_row[currow] && currow)
XX			    currow--;
XX		    }
XX		    break;
XX		case ctl (q):
XX		    break;	/* ignore flow control */
XX		case ctl (s):
XX		    break;	/* ignore flow control */
XX		case ctl (t):
XX		    showme ^= 1;
XX		    break;
XX		case ctl (u):
XX		    narg = arg * 4;
XX		    nedistate = 1;
XX		    break;
XX		case ctl (v):	/* insert variable name */
XX		    if (linelim > 0) {
XX			sprintf (line+linelim,"%s%d", coltoa(curcol), currow);
XX			linelim = strlen (line);
XX		    }
XX		    break;
XX		case ctl (e):	/* insert variable expression */
XX		    if (linelim > 0) editexp(currow,curcol);
XX		    break;
XX		case ctl (a):	/* insert variable value */
XX		    if (linelim > 0) {
XX			struct ent *p = tbl[currow][curcol];
XX
XX			if (p && p -> flags & is_valid) {
XX			    sprintf (line + linelim, "%.*f",
XX					precision[curcol],p -> v);
XX			    linelim = strlen (line);
XX			}
XX		    }
XX		    break;
XX		}
XX	else
XX	    if ('0' <= c && c <= '9' && (linelim < 0 || edistate >= 0)) {
XX		if (edistate != 0) {
XX		    if (c == '0')      /* just a '0' goes to left col */
XX			curcol = 0;
XX		    else {
XX		        nedistate = 0;
XX		        narg = c - '0';
XX		    }
XX		} else {
XX		    nedistate = 0;
XX		    narg = arg * 10 + (c - '0');
XX		}
XX	    }
XX	    else
XX		if (linelim >= 0) {
XX		    line[linelim++] = c;
XX		    line[linelim] = 0;
XX		}
XX		else
XX		    switch (c) {
XX			case '.':
XX			    nedistate = 1;
XX			    break;
XX			case ':':
XX			    break;	/* Be nice to vi users */
XX			case '=':
XX			    sprintf(line,"let %s%d = ",coltoa(curcol),currow);
XX			    linelim = strlen (line);
XX			    break;
XX			case '/':
XX			    sprintf(line,"copy [to] %s%d [from] ", 
XX				      coltoa(curcol), currow);
XX			    linelim = strlen (line);
XX			    break;
XX			case '$':
XX			    curcol = MAXCOLS - 1;
XX			    while (!tbl[currow][curcol] && curcol > 0)
XX				curcol--;
XX			    break;
XX			case '?':
XX			    help ();
XX			    break;
XX			case '"':
XX			    sprintf (line, "label %s%d = \"",
XX						coltoa(curcol), currow);
XX			    linelim = strlen (line);
XX			    break;
XX			case '<':
XX			    sprintf (line, "leftstring %s%d = \"",
XX				    coltoa(curcol), currow);
XX			    linelim = strlen (line);
XX			    break;
XX			case '>':
XX			    sprintf (line, "rightstring %s%d = \"",
XX				    coltoa(curcol), currow);
XX			    linelim = strlen (line);
XX			    break;
XX			case 'e':
XX			    editv (currow, curcol);
XX			    break;
XX			case 'E':
XX			    edits (currow, curcol);
XX			    break;
XX			case 'f':
XX			    sprintf (line, "format [for column] %s [is] ",
XX					coltoa(curcol));
XX			    error("Current format is %d %d",
XX					fwidth[curcol],precision[curcol]);
XX			    linelim = strlen (line);
XX			    break;
XX			case 'P':
XX			    sprintf (line, "put [database into] \"");
XX			    if (*curfile)
XX			    error("default file is '%s'",curfile);
XX			    linelim = strlen (line);
XX			    break;
XX			case 'M':
XX			    sprintf (line, "merge [database from] \"");
XX			    linelim = strlen (line);
XX			    break;
XX			case 'G':
XX			    sprintf (line, "get [database from] \"");
XX			    if (*curfile)
XX			    error("default file is '%s'",curfile);
XX			    linelim = strlen (line);
XX			    break;
XX			case 'W':
XX			    sprintf (line, "write [listing to] \"");
XX			    linelim = strlen (line);
XX			    break;
XX			case 'T':	/* tbl output */
XX			    sprintf (line, "tbl [listing to] \"");
XX			    linelim = strlen (line);
XX			    break;
XX			case 'i':
XX			    switch (get_qual()) {
XX			    case 'r':
XX				insertrow(arg);
XX				break;
XX			    case 'c':
XX				insertcol(arg);
XX				break;
XX			    default:
XX				break;
XX			    }
XX			    break;
XX			case 'd':
XX			    switch (get_qual()) {
XX			    case 'r':
XX				deleterow(arg);
XX				break;
XX			    case 'c':
XX				deletecol(arg);
XX				break;
XX			    default:
XX				break;
XX			    }
XX			    break;
XX			case 'v':
XX			    switch (get_qual()) {
XX			    case 'r':
XX				valueizerow(arg);
XX				break;
XX			    case 'c':
XX				valueizecol(arg);
XX				break;
XX			    default:
XX				break;
XX			    }
XX			    break;
XX			case 'p':
XX			    {
XX			    register qual;
XX			    qual = get_qual();
XX			    while (arg--)
XX			        pullcells(qual);
XX			    break;
XX			    }
XX			case 'x':
XX			    {
XX			    register struct ent **p;
XX			    register int c;
XX			    flush_saved();
XX			    for (c = curcol; arg-- && c < MAXCOLS; c++) {
XX				p = &tbl[currow][c];
XX				if (*p) {
XX			            free_ent(*p);
XX			            *p = 0;
XX				}
XX			    }
XX			    sync_refs();
XX			    FullUpdate++;
XX			    }
XX			    break;
XX			case 'Q':
XX			case 'q':
XX			    running = 0;
XX			    break;
XX			case 'h':
XX			    while (--arg>=0) {
XX				if (curcol)
XX				    curcol--;
XX				else
XX				    error ("At column A");
XX				while(hidden_col[curcol] && curcol)
XX				    curcol--;
XX			    }
XX			    break;
XX			case 'j':
XX			    while (--arg>=0) {
XX				if (currow < MAXROWS - 1)
XX				    currow++;
XX				else
XX				    error ("The table can't be any longer");
XX				while (hidden_row[currow]&&(currow<MAXROWS-1))
XX				    currow++;
XX			    }
XX			    break;
XX			case 'k':
XX			    while (--arg>=0) {
XX				if (currow)
XX				    currow--;
XX				else
XX				    error ("At row zero");
XX				while (hidden_row[currow] && currow)
XX				    currow--;
XX			    }
XX			    break;
XX			case 'l':
XX			    while (--arg>=0) {
XX				if (curcol < MAXCOLS - 1)
XX				    curcol++;
XX				else
XX				    error ("The table can't be any wider");
XX				while(hidden_col[curcol]&&(curcol<MAXCOLS-1))
XX				    curcol++;
XX			    }
XX			    break;
XX			case 'm':
XX			    savedrow = currow;
XX			    savedcol = curcol;
XX			    break;
XX			case 'c': {
XX			    register struct ent *p = tbl[savedrow][savedcol];
XX			    register c;
XX			    register struct ent *n;
XX			    if (!p)
XX				break;
XX			    FullUpdate++;
XX			    modflg++;
XX			    for (c = curcol; arg-- && c < MAXCOLS; c++) {
XX				n = lookat (currow, c);
XX				clearent(n);
XX				n -> flags = p -> flags;
XX				n -> v = p -> v;
XX				n -> expr = copye(p->expr,
XX					    currow - savedrow,
XX					    c - savedcol);
XX				n -> label = 0;
XX				if (p -> label) {
XX				    n -> label = (char *)
XX						 malloc(strlen(p->label)+1);
XX				strcpy (n -> label, p -> label);
XX				}
XX			    }
XX			    break;
XX			}
XX			case 'z':
XX			    switch (get_qual()) {
XX			    case 'r':
XX				hiderow(arg);
XX				break;
XX			    case 'c':
XX				hidecol(arg);
XX				break;
XX			    default:
XX				break;
XX			    }
XX			    break;
XX			case 's':
XX			    switch (get_qual()) {
XX			    case 'r':
XX				showrow_op();
XX				break;
XX			    case 'c':
XX				showcol_op();
XX				break;
XX			    default:
XX				break;
XX			    }
XX			    break;
XX			case 'a':
XX			    switch (get_qual()) {
XX			    case 'r':
XX				while (arg--)
XX				    duprow();
XX				break;
XX			    case 'c':
XX				while (arg--)
XX				    dupcol();
XX				break;
XX			    default:
XX				break;
XX			    }
XX			    break;
XX			default:
XX			    if ((c & 0177) != c)
XX				error("Weird character, decimal '%d'.\n",
XX					(int) c);
XX			    else error ("No such command  (%c)", c);
XX			    break;
XX		    }
XX	edistate = nedistate;
XX	arg = narg;
XX    }				/* while (running) */
XX    inloop = modcheck(" before exiting");
XX    }				/*  while (inloop) */
XX    endwin ();
XX}
XX
XXmodcheck(endstr) char *endstr; {
XX    if (modflg && curfile[0]) {
XX	char ch, lin[100];
XX
XX	move (0, 0);
XX	clrtoeol ();
XX	sprintf (lin,"File '%s' is modified, save%s? ",curfile,endstr);
XX	addstr (lin);
XX	refresh();
XX	ch = nmgetch();
XX	if (ch == 'y' || ch == 'Y') writefile(curfile);
XX	else if (ch == ctl (g)) return(1);
XX    }
XX    return(0);
XX}
XX    
XXwritefile (fname)
XXchar *fname; {
XX    register FILE *f;
XX    register struct ent **p;
XX    register r, c;
XX    char save[1024];
XX
XX    if (*fname == 0) fname = &curfile[0];
XX
XX    strcpy(save,fname);
XX
XX    f = fopen (fname, "w");
XX    if (f==0) {
XX	error ("Can't create %s", fname);
XX	return;
XX    }
XX
XX    fprintf (f, "# This data file was generated by the Spreadsheet ");
XX    fprintf (f, "Calculator.\n");
XX    fprintf (f, "# You almost certainly shouldn't edit it.\n\n");
XX    for (c=0; c<MAXCOLS; c++)
XX	if (fwidth[c] != DEFWIDTH || precision[c] != DEFPREC)
XX	    fprintf (f, "format %s %d %d\n",coltoa(c),fwidth[c],precision[c]);
XX    for (r=0; r<=maxrow; r++) {
XX	p = &tbl[r][0];
XX	for (c=0; c<=maxcol; c++, p++)
XX	    if (*p) {
XX		if ((*p)->label)
XX		    fprintf (f, "%sstring %s%d = \"%s\"\n",
XX				(*p)->flags&is_leftflush ? "left" : "right",
XX				coltoa(c),r,(*p)->label);
XX		if ((*p)->flags&is_valid) {
XX		    editv (r, c);
XX		    fprintf (f, "%s\n",line);
XX		}
XX	    }
XX    }
XX    fclose (f);
XX    strcpy(curfile,save);
XX
XX    modflg = 0;
XX    error("File '%s' written.",curfile);
XX}
XX
XXreadfile (fname,eraseflg)
XXchar *fname; int eraseflg; {
XX    register FILE *f;
XX    char save[1024];
XX
XX    if (*fname == 0) fname = &curfile[0];
XX    strcpy(save,fname);
XX
XX    if (eraseflg && strcmp(fname,curfile) && modcheck(" first")) return;
XX
XX    f = fopen (save, "r");
XX    if (f==0) {
XX	error ("Can't read %s", save);
XX	return;
XX    }
XX
XX    if (eraseflg) erasedb ();
XX
XX    while (fgets(line,sizeof line,f)) {
XX	linelim = 0;
XX	if (line[0] != '#') yyparse ();
XX    }
XX    fclose (f);
XX    linelim = -1;
XX    modflg++;
XX    if (eraseflg) {
XX	strcpy(curfile,save);
XX	modflg = 0;
XX    }
XX    EvalAll();
XX}
XX
XXerasedb () {
XX    register r, c;
XX    for (c = 0; c<=maxcol; c++) {
XX	fwidth[c] = DEFWIDTH;
XX	precision[c] = DEFPREC;
XX    }
XX
XX    for (r = 0; r<=maxrow; r++) {
XX	register struct ent **p = &tbl[r][0];
XX	for (c=0; c++<=maxcol; p++)
XX	    if (*p) {
XX		if ((*p)->expr) efree ((*p) -> expr);
XX		if ((*p)->label) free ((*p) -> label);
XX		free (*p);
XX		*p = 0;
XX	    }
XX    }
XX    maxrow = 0;
XX    maxcol = 0;
XX    FullUpdate++;
XX}
XX
SHAR_EOF
if test 16896 -ne "`wc -c sc.c`"
then
echo shar: error transmitting sc.c '(should have been 16896 characters)'
fi
echo shar: extracting lex.c
sed 's/^XX//' << \SHAR_EOF > lex.c
XX/*	SC	A Spreadsheet Calculator
XX *		Lexical analyser
XX *
XX *		original by James Gosling, September 1982
XX *		modifications by Mark Weiser and Bruce Israel,
XX *			University of Maryland
XX *
XX *              More mods Robert Bond, 12/86
XX *		Major mods to run on VMS and AMIGA, 1/17/87
XX *
XX */
XX
XX
XX
XX#include "sc.h"
XX#include <ctype.h>
XX#ifdef VMS
XX#include "y_tab.h"
XX#else
XX#include "y.tab.h"
XX#endif
XX
XXextern char *malloc();
XXchar *strtof();
XX
XXstruct key {
XX    char *key;
XX    int val;
XX};
XX
XXstruct key experres[] = {
XX#include "experres.h"
XX    0, 0};
XX
XXstruct key statres[] = {
XX#include "statres.h"
XX    0, 0};
XX
XX#define ctl(x) ('x'&037)
XX
XXyylex () {
XX    register char *p = line+linelim;
XX    int ret = -1;
XX    while (isspace(*p)) p++;
XX    if (*p==0) ret = -1;
XX    else if (isalpha(*p)) {
XX	char *tokenst = p;
XX	register tokenl;
XX	register struct key *tbl;
XX	while (isalpha(*p)) p++;
XX	if (p-tokenst <= 2) { /* a COL is 1 or 2 char alpha */
XX	    register  col;
XX	    ret = COL;
XX	    col = ((tokenst[0] & 0137) - 'A');
XX	    if (p == tokenst+2)
XX		col = (col + 1)*26 + ((tokenst[1] & 0137) - 'A');
XX	    yylval.ival =  col;
XX	} else {
XX	    ret = WORD;
XX	    tokenl = p-tokenst;
XX	    for (tbl = linelim ? experres : statres; tbl->key; tbl++)
XX		    if (((tbl->key[0]^tokenst[0])&0137)==0
XX		     && tbl->key[tokenl]==0) {
XX			register i = 1;
XX			while (i<tokenl && ((tokenst[i]^tbl->key[i])&0137)==0)
XX			    i++;
XX			if (i>=tokenl) {
XX			    ret = tbl->val;
XX			    break;
XX			}
XX		    }
XX	    if (ret==WORD) { 
XX		linelim = p-line;
XX		yyerror ("Unintelligible word");
XX	    }
XX	}
XX    } else if ((*p == '.') || isdigit(*p)) {
XX	register long v = 0;
XX	char *nstart = p;
XX	if (*p != '.') {
XX	    do v = v*10 + (*p-'0');
XX	    while (isdigit(*++p));
XX	}
XX	if (*p=='.' || *p == 'e' || *p == 'E') {
XX	    ret = FNUMBER;
XX	    p = strtof(nstart, &yylval.fval);
XX	} else {
XX            if((int)v != v)
XX            {
XX                ret = FNUMBER;
XX                yylval.fval = v;
XX            }
XX            else
XX            {
XX 
XX                ret = NUMBER;
XX                yylval.ival = v;
XX            }
XX	}
XX    } else if (*p=='"') {
XX	/* This storage is never freed.  Oh well.  -MDW */
XX	char *ptr;
XX        ptr = p+1;
XX        while(*ptr && *ptr++ != '"');
XX        ptr = (char *)malloc((unsigned)(ptr-p));
XX	yylval.sval = ptr;
XX	p += 1;
XX	while (*p && *p!='"') *ptr++ = *p++;
XX	*ptr = 0;
XX	if (*p) p += 1;
XX	ret = STRING;
XX    } else if (*p=='[') {
XX	while (*p && *p!=']') p++;
XX	if (*p) p++;
XX	linelim = p-line;
XX	return yylex();
XX    } else ret = *p++;
XX    linelim = p-line;
XX    return ret;
XX}
XX
XX#define N_KEY 26
XX
XXstruct key_map {
XX    char *k_str;
XX    char k_val;
XX    char k_index;
XX}; 
XX
XXstruct key_map km[N_KEY];
XX
XXinitkbd()
XX{
XX    int i;
XX
XX    /* cursor set mode */
XX    km[0].k_str  = "\033OD"; km[0].k_val  = ctl(b);
XX    km[1].k_str  = "\033OC"; km[1].k_val  = ctl(f);
XX    km[2].k_str  = "\033OA"; km[2].k_val  = ctl(p);
XX    km[3].k_str  = "\033OB"; km[3].k_val  = ctl(n);
XX    /* cursor reset mode */
XX    km[4].k_str  = "\033[D"; km[4].k_val  = ctl(b);
XX    km[5].k_str  = "\033[C"; km[5].k_val  = ctl(f);
XX    km[6].k_str  = "\033[A"; km[6].k_val  = ctl(p);
XX    km[7].k_str  = "\033[B"; km[7].k_val  = ctl(n);
XX    /* CSI arrows */
XX    km[8].k_str  = "\233D";  km[8].k_val  = ctl(b);
XX    km[9].k_str  = "\233C";  km[9].k_val  = ctl(f);
XX    km[10].k_str = "\233A";  km[10].k_val = ctl(p);
XX    km[11].k_str = "\233B";  km[11].k_val = ctl(n);
XX    /* application keypad mode */
XX    km[12].k_str = "\033Op"; km[12].k_val = '0';
XX    km[13].k_str = "\033Oq"; km[13].k_val = '1';
XX    km[14].k_str = "\033Or"; km[14].k_val = '2';
XX    km[15].k_str = "\033Os"; km[15].k_val = '3';
XX    km[16].k_str = "\033Ot"; km[16].k_val = '4';
XX    km[17].k_str = "\033Ou"; km[17].k_val = '5';
XX    km[18].k_str = "\033Ov"; km[18].k_val = '6';
XX    km[19].k_str = "\033Ow"; km[19].k_val = '7';
XX    km[20].k_str = "\033Ox"; km[20].k_val = '8';
XX    km[21].k_str = "\033Oy"; km[21].k_val = '9';
XX    km[22].k_str = "\033Om"; km[22].k_val = '-';
XX    km[23].k_str = "\033Ol"; km[23].k_val = ',';
XX    km[24].k_str = "\033On"; km[24].k_val = '.';
XX    km[25].k_str = "\033OM"; km[25].k_val = ctl(m);
XX}
XX
XXnmgetch() 
XX{
XX    register int c;
XX    register struct key_map *kp;
XX    register struct key_map *biggest;
XX    register int i;
XX    int almost;
XX    int maybe;
XX
XX    static char dumpbuf[10];
XX    static char *dumpindex;
XX
XX    void timeout();
XX
XX    if (dumpindex && *dumpindex)
XX	    return (*dumpindex++);
XX
XX    c = ttgetc();
XX    biggest = 0;
XX    almost = 0;
XX
XX    for (kp = &km[0]; kp < &km[N_KEY]; kp++) {
XX	if (!kp->k_str)
XX	    continue;
XX	if (c == (kp->k_str[kp->k_index] & 0xFF)) {
XX	    almost = 1;
XX	    kp->k_index++;
XX	    if (kp->k_str[kp->k_index] == 0) {
XX		c = kp->k_val;
XX       	        for (kp = &km[0]; kp < &km[N_KEY]; kp++)
XX	            kp->k_index = 0;
XX	        return(c);
XX	    }
XX	}
XX	if (!biggest && kp->k_index)
XX	    biggest = kp;
XX        else if (kp->k_index && biggest->k_index < kp->k_index)
XX	    biggest = kp;
XX    }
XX
XX    if (almost) return(nmgetch());
XX
XX    if (biggest) {
XX	for (i = 0; i<biggest->k_index; i++) 
XX	    dumpbuf[i] = biggest->k_str[i];
XX	dumpbuf[i++] = c;
XX	dumpbuf[i] = 0;
XX	dumpindex = &dumpbuf[1];
XX       	for (kp = &km[0]; kp < &km[N_KEY]; kp++)
XX	    kp->k_index = 0;
XX	return (dumpbuf[0]);
XX    }
XX
XX    return(c);
XX}
XX
XX
XXint dbline;
XX
XXdebug (fmt, a, b, c) {
XX	move(2+(dbline++%22),80-60);
XX	printw(fmt,a,b,c);
XX	clrtoeol();
XX}
XX
XX/*
XX * This converts a floating point number of the form
XX * [s]ddd[.d*][esd*]  where s can be a + or - and e is E or e.
XX * to floating point. 
XX * p is advanced.
XX */
XX
XXchar *
XXstrtof(p, res)
XXregister char *p;
XXdouble *res;
XX{
XX    double acc;
XX    int sign;
XX    double fpos;
XX    int exp;
XX    int exps;
XX
XX    acc = 0.0;
XX    sign = 1;
XX    exp = 0;
XX    exps = 1;
XX    if (*p == '+')
XX        p++;
XX    else if (*p == '-') {
XX        p++;
XX        sign = -1;
XX    }
XX    while (isdigit(*p)) {
XX        acc = acc * 10.0 + (double)(*p - '0');
XX        p++;
XX    }
XX    if (*p == 'e' || *p == 'E') {
XX	    p++;
XX        if (*p == '+')
XX	    p++;
XX        else if (*p == '-') {
XX	    p++;
XX	    exps = -1;
XX        }
XX        while(isdigit(*p)) {
XX	    exp = exp * 10 + (*p - '0');
XX	    p++;
XX        }
XX    }
XX    if (*p == '.') {
XX	fpos = 1.0/10.0;
XX	p++;
XX	while(isdigit(*p)) {
XX	    acc += (*p - '0') * fpos;
XX	    fpos *= 1.0/10.0;
XX	    p++;
XX	}
XX    }
XX    if (*p == 'e' || *p == 'E') {
XX	exp = 0;
XX	exps = 1;
XX        p++;
XX	if (*p == '+')
XX	    p++;
XX	else if (*p == '-') {
XX	    p++;
XX	    exps = -1;
XX	}
XX	while(isdigit(*p)) {
XX	    exp = exp * 10 + (*p - '0');
XX	    p++;
XX	}
XX    }
XX    if (exp) {
XX	if (exps > 0)
XX	    while (exp--)
XX		acc *= 10.0;
XX	else
XX	    while (exp--)
XX		acc *= 1.0/10.0;
XX    }
XX    if (sign > 0)
XX        *res = acc;
XX    else
XX	*res = -acc;
XX
XX    return(p);
XX}
XX
XXhelp () {
XX    move(2,0);
XX    clrtobot();
XX    dbline = 0;
XX    debug ("                 Cursor cmds:");
XX    debug ("  ^n j next row       ^p k prev. row      ^g erase cmd");
XX    debug ("  ^f l fwd col        ^b h back col       ^r redraw screen");
XX    debug ("   0 $ first, end col");
XX    debug ("                 Cell cmds:");
XX    debug (" \" < > enter label       = enter value     x clear cell");
XX    debug ("     c copy cell         m mark cell      ^t line 1 on/off");  
XX    debug ("    ^a type value       ^e type expr.     ^v type vbl name");
XX    debug ("                 Row, Column cmds:");
XX    debug (" ar ac dup           ir ic insert      sr sc show");
XX    debug (" dr dc delete        zr zc hide        pr pc pull");
XX    debug (" vr vc value only        f format");
XX    debug ("                 File cmds:");
XX    debug ("     G get database      M merge database  T write tbl fmt");
XX    debug ("     P put database      W write listing");
XX    debug ("                 Misc. cmds:");
XX    debug (" ^c, q quit              / copy region    pm pull (merge)");
XX    debug ("                 Expression Operators");
XX    debug ("  +-*/ arithmetic     ?e:e conditional   & | booleans");
XX    debug (" < = > relations     <= >= relations      != relations");
XX    debug ("       @sum(v1:v2)         @avg(v1:v2)       @prod(v1:v2)");
XX}
SHAR_EOF
if test 7972 -ne "`wc -c lex.c`"
then
echo shar: error transmitting lex.c '(should have been 7972 characters)'
fi
echo shar: extracting gram.c
sed 's/^XX//' << \SHAR_EOF > gram.c
XX
XX# line 15 "gram.y"
XX#include "sc.h"
XX
XX# line 18 "gram.y"
XXtypedef union  {
XX    int ival;
XX    double fval;
XX    struct ent *ent;
XX    struct enode *enode;
XX    char *sval;
XX} YYSTYPE;
XX# define STRING 257
XX# define NUMBER 258
XX# define FNUMBER 259
XX# define WORD 260
XX# define COL 261
XX# define S_FORMAT 262
XX# define S_LABEL 263
XX# define S_LEFTSTRING 264
XX# define S_RIGHTSTRING 265
XX# define S_GET 266
XX# define S_PUT 267
XX# define S_MERGE 268
XX# define S_LET 269
XX# define S_WRITE 270
XX# define S_TBL 271
XX# define S_PROGLET 272
XX# define S_COPY 273
XX# define S_SHOW 274
XX# define K_FIXED 275
XX# define K_SUM 276
XX# define K_PROD 277
XX# define K_AVE 278
XX#define yyclearin yychar = -1
XX#define yyerrok yyerrflag = 0
XXextern int yychar;
XXextern short yyerrflag;
XX#ifndef YYMAXDEPTH
XX#define YYMAXDEPTH 150
XX#endif
XXYYSTYPE yylval, yyval;
XX# define YYERRCODE 256
XXshort yyexca[] ={
XX-1, 1,
XX	0, -1,
XX	-2, 0,
XX-1, 83,
XX	60, 0,
XX	61, 0,
XX	62, 0,
XX	-2, 34,
XX-1, 85,
XX	60, 0,
XX	61, 0,
XX	62, 0,
XX	-2, 35,
XX-1, 86,
XX	60, 0,
XX	61, 0,
XX	62, 0,
XX	-2, 36,
XX-1, 96,
XX	60, 0,
XX	61, 0,
XX	62, 0,
XX	-2, 39,
XX-1, 97,
XX	60, 0,
XX	61, 0,
XX	62, 0,
XX	-2, 41,
XX-1, 98,
XX	60, 0,
XX	61, 0,
XX	62, 0,
XX	-2, 40,
XX	};
XX# define YYNPROD 43
XX# define YYLAST 267
XXshort yyact[]={
XX
XX  14,  69,  70,  71,  16,  55,   6,   3,   4,   5,
XX   7,   9,   8,   2,  10,  11,  49,  13,  12,  27,
XX  49,  54,  26,  43,  49,  20,  44,  43,  45,  53,
XX  44,  43,  45,  34,  44,  30,  45,  52,  51,  50,
XX  25,  24,  23,  22,  87,  21,  90,  42,  84,  67,
XX  33,  42, 105,  32,  65,  42,  31,  67,  59,  57,
XX  29,  58,  65,  60, 104,  94,  59,  57, 103,  58,
XX  56,  60,  36,  35,  95, 111,  62,  63,  64,  61,
XX 110, 109,  93,  67,  62,  63,  64,  61,  65,  39,
XX  67,  67,  59,  57,  92,  58,  65,  60,  38,  59,
XX  59,  57,  91,  58,  60,  60,  67,   1,   0,  48,
XX  62,  63,  64,  48,   0,   0,   0,  48,  62,  63,
XX  64,  61,  40,   0,   0,  15,  17,  18,  19,   0,
XX   0,  68,   0,   0,  73,  74,  28,   0,  75,  76,
XX  66,   0,  72,   0,   0,   0,   0,   0,  66,   0,
XX   0,  37,   0,   0,   0,   0,  78,  79,  80,  81,
XX  82,  83,  85,  86,  88,  89,  67,   0,   0,   0,
XX   0,   0,   0,   0,  66,  59,  57,   0,  58,  77,
XX  60,   0,  66,  96,   0,   0,  97,   0,   0,  98,
XX  67,   0,   0,   0, 102,  65,  67,   0,   0,  59,
XX  57,   0,  58,   0,  60,  59,  57,   0,  58,   0,
XX  60,   0,   0,   0,  99, 100, 101,  62,  63,  64,
XX   0,   0,   0,  62,  63,  64, 106, 107, 108,   0,
XX   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
XX   0,  46,  47,   0,  16,  46,  47,   0,  16,  46,
XX  47,   0,  16,   0,   0,   0,   0,   0,  41,   0,
XX   0,   0,  41,   0,   0,   0,  41 };
XXshort yypact[]={
XX
XX-256,-1000,-257,-257,-257,-257,-236,-212,-214,-215,
XX-216,-217,-239,-257,-1000,  -1,-223,  -5,  -8, -11,
XX-225,-1000,-1000,-1000,-1000,-1000,  15,  14,-257,  -9,
XX-1000,-218,-219,-220,-229,-240,-253,  12,  58,-1000,
XX-1000,  -9,-275,  -9,  -9,  -9,-1000,-1000,  -9,  -9,
XX-1000,-1000,-1000,-1000,-1000,-1000,-257,  -9,  -9,  -9,
XX  -9,  -9, -13,  -9, -17,  -9,  -9, -15,-1000,  62,
XX  54,  42,  24,-1000,-1000,-1000,-1000,-1000,  57,  57,
XX  73,  73,  16, 133,  -9, 133, 133,  -9, 163, 157,
XX  -9,-257,-257,-257,-1000,  -9, 133, 133, 133,  10,
XX   6,  -6,  50,-257,-257,-257,  40,  39,  34,-1000,
XX-1000,-1000 };
XXshort yypgo[]={
XX
XX   0, 122,  98,  89, 107 };
XXshort yyr1[]={
XX
XX   0,   4,   4,   4,   4,   4,   4,   4,   4,   4,
XX   4,   4,   4,   4,   4,   4,   3,   3,   3,   3,
XX   3,   3,   3,   3,   3,   3,   3,   3,   2,   2,
XX   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
XX   2,   2,   1 };
XXshort yyr2[]={
XX
XX   0,   4,   4,   4,   4,   4,   2,   2,   2,   2,
XX   2,   4,   4,   5,   0,   1,   1,   2,   7,   7,
XX   7,   3,   2,   2,   1,   1,   2,   2,   3,   3,
XX   3,   3,   1,   5,   3,   3,   3,   3,   3,   4,
XX   4,   4,   2 };
XXshort yychk[]={
XX
XX-1000,  -4, 269, 263, 264, 265, 262, 266, 268, 267,
XX 270, 271, 274, 273, 256,  -1, 261,  -1,  -1,  -1,
XX 261, 257, 257, 257, 257, 257, 261, 258,  -1,  61,
XX 258,  61,  61,  61, 258,  58,  58,  -1,  -2,  -3,
XX  -1, 275,  64,  40,  43,  45, 258, 259, 126,  33,
XX 257, 257, 257, 258, 261, 258,  58,  43,  45,  42,
XX  47,  63,  60,  61,  62,  38, 124,  33,  -3, 276,
XX 277, 278,  -2,  -3,  -3,  -3,  -3,  -1,  -2,  -2,
XX  -2,  -2,  -2,  -2,  61,  -2,  -2,  61,  -2,  -2,
XX  61,  40,  40,  40,  41,  58,  -2,  -2,  -2,  -1,
XX  -1,  -1,  -2,  58,  58,  58,  -1,  -1,  -1,  41,
XX  41,  41 };
XXshort yydef[]={
XX
XX  14,  -2,   0,   0,   0,   0,   0,   0,   0,   0,
XX   0,   0,   0,   0,  15,   0,   0,   0,   0,   0,
XX   0,   6,   7,   8,   9,  10,   0,   0,   0,   0,
XX  42,   0,   0,   0,   0,   0,   0,   0,   1,  32,
XX  16,   0,   0,   0,   0,   0,  24,  25,   0,   0,
XX   2,   3,   4,   5,  11,  12,   0,   0,   0,   0,
XX   0,   0,   0,   0,   0,   0,   0,   0,  17,   0,
XX   0,   0,   0,  22,  23,  26,  27,  13,  28,  29,
XX  30,  31,   0,  -2,   0,  -2,  -2,   0,  37,  38,
XX   0,   0,   0,   0,  21,   0,  -2,  -2,  -2,   0,
XX   0,   0,  33,   0,   0,   0,   0,   0,   0,  18,
XX  19,  20 };
XX#ifndef lint
XXstatic char yaccpar_sccsid[] = "@(#)yaccpar	4.1	(Berkeley)	2/11/83";
XX#endif not lint
XX
XX#
XX# define YYFLAG -1000
XX# define YYERROR goto yyerrlab
XX# define YYACCEPT return(0)
XX# define YYABORT return(1)
XX
XX/*	parser for yacc output	*/
XX
XX#ifdef YYDEBUG
XXint yydebug = 0; /* 1 for debugging */
XX#endif
XXYYSTYPE yyv[YYMAXDEPTH]; /* where the values are stored */
XXint yychar = -1; /* current input token number */
XXint yynerrs = 0;  /* number of errors */
XXshort yyerrflag = 0;  /* error recovery flag */
XX
XXyyparse() {
XX
XX	short yys[YYMAXDEPTH];
XX	short yyj, yym;
XX	register YYSTYPE *yypvt;
XX	register short yystate, *yyps, yyn;
XX	register YYSTYPE *yypv;
XX	register short *yyxi;
XX
XX	yystate = 0;
XX	yychar = -1;
XX	yynerrs = 0;
XX	yyerrflag = 0;
XX	yyps= &yys[-1];
XX	yypv= &yyv[-1];
XX
XX yystack:    /* put a state and value onto the stack */
XX
XX#ifdef YYDEBUG
XX	if( yydebug  ) printf( "state %d, char 0%o\n", yystate, yychar );
XX#endif
XX		if( ++yyps> &yys[YYMAXDEPTH] ) { yyerror( "yacc stack overflow" ); return(1); }
XX		*yyps = yystate;
XX		++yypv;
XX		*yypv = yyval;
XX
XX yynewstate:
XX
XX	yyn = yypact[yystate];
XX
XX	if( yyn<= YYFLAG ) goto yydefault; /* simple state */
XX
XX	if( yychar<0 ) if( (yychar=yylex())<0 ) yychar=0;
XX	if( (yyn += yychar)<0 || yyn >= YYLAST ) goto yydefault;
XX
XX	if( yychk[ yyn=yyact[ yyn ] ] == yychar ){ /* valid shift */
XX		yychar = -1;
XX		yyval = yylval;
XX		yystate = yyn;
XX		if( yyerrflag > 0 ) --yyerrflag;
XX		goto yystack;
XX		}
XX
XX yydefault:
XX	/* default state action */
XX
XX	if( (yyn=yydef[yystate]) == -2 ) {
XX		if( yychar<0 ) if( (yychar=yylex())<0 ) yychar = 0;
XX		/* look through exception table */
XX
XX		for( yyxi=yyexca; (*yyxi!= (-1)) || (yyxi[1]!=yystate) ; yyxi += 2 ) ; /* VOID */
XX
XX		while( *(yyxi+=2) >= 0 ){
XX			if( *yyxi == yychar ) break;
XX			}
XX		if( (yyn = yyxi[1]) < 0 ) return(0);   /* accept */
XX		}
XX
XX	if( yyn == 0 ){ /* error */
XX		/* error ... attempt to resume parsing */
XX
XX		switch( yyerrflag ){
XX
XX		case 0:   /* brand new error */
XX
XX			yyerror( "syntax error" );
XX		yyerrlab:
XX			++yynerrs;
XX
XX		case 1:
XX		case 2: /* incompletely recovered error ... try again */
XX
XX			yyerrflag = 3;
XX
XX			/* find a state where "error" is a legal shift action */
XX
XX			while ( yyps >= yys ) {
XX			   yyn = yypact[*yyps] + YYERRCODE;
XX			   if( yyn>= 0 && yyn < YYLAST && yychk[yyact[yyn]] == YYERRCODE ){
XX			      yystate = yyact[yyn];  /* simulate a shift of "error" */
XX			      goto yystack;
XX			      }
XX			   yyn = yypact[*yyps];
XX
XX			   /* the current yyps has no shift onn "error", pop stack */
XX
XX#ifdef YYDEBUG
XX			   if( yydebug ) printf( "error recovery pops state %d, uncovers %d\n", *yyps, yyps[-1] );
XX#endif
XX			   --yyps;
XX			   --yypv;
XX			   }
XX
XX			/* there is no state on the stack with an error shift ... abort */
XX
XX	yyabort:
XX			return(1);
XX
XX
XX		case 3:  /* no shift yet; clobber input char */
XX
XX#ifdef YYDEBUG
XX			if( yydebug ) printf( "error recovery discards char %d\n", yychar );
XX#endif
XX
XX			if( yychar == 0 ) goto yyabort; /* don't discard EOF, quit */
XX			yychar = -1;
XX			goto yynewstate;   /* try again in the same state */
XX
XX			}
XX
XX		}
XX
XX	/* reduction by production yyn */
XX
XX#ifdef YYDEBUG
XX		if( yydebug ) printf("reduce %d\n",yyn);
XX#endif
XX		yyps -= yyr2[yyn];
XX		yypvt = yypv;
XX		yypv -= yyr2[yyn];
XX		yyval = yypv[1];
XX		yym=yyn;
XX			/* consult goto table to find next state */
XX		yyn = yyr1[yyn];
XX		yyj = yypgo[yyn] + *yyps + 1;
XX		if( yyj>=YYLAST || yychk[ yystate = yyact[yyj] ] != -yyn ) yystate = yyact[yypgo[yyn]];
XX		switch(yym){
XX			
XXcase 1:
XX# line 59 "gram.y"
XX{ let (yypvt[-2].ent, yypvt[-0].enode); } break;
XXcase 2:
XX# line 61 "gram.y"
XX{ label (yypvt[-2].ent, yypvt[-0].sval, 0); } break;
XXcase 3:
XX# line 63 "gram.y"
XX{ label (yypvt[-2].ent, yypvt[-0].sval, -1); } break;
XXcase 4:
XX# line 65 "gram.y"
XX{ label (yypvt[-2].ent, yypvt[-0].sval, 1); } break;
XXcase 5:
XX# line 67 "gram.y"
XX{ fwidth[yypvt[-2].ival] = yypvt[-1].ival;
XX				  FullUpdate++;
XX				  modflg++;
XX				  precision[yypvt[-2].ival] = yypvt[-0].ival; } break;
XXcase 6:
XX# line 71 "gram.y"
XX{ readfile (yypvt[-0].sval,1); } break;
XXcase 7:
XX# line 72 "gram.y"
XX{ readfile (yypvt[-0].sval,0); } break;
XXcase 8:
XX# line 73 "gram.y"
XX{ writefile (yypvt[-0].sval); } break;
XXcase 9:
XX# line 74 "gram.y"
XX{ printfile (yypvt[-0].sval); } break;
XXcase 10:
XX# line 75 "gram.y"
XX{ tblprintfile (yypvt[-0].sval); } break;
XXcase 11:
XX# line 76 "gram.y"
XX{ showcol( yypvt[-2].ival, yypvt[-0].ival); } break;
XXcase 12:
XX# line 77 "gram.y"
XX{ showrow( yypvt[-2].ival, yypvt[-0].ival); } break;
XXcase 13:
XX# line 79 "gram.y"
XX{ copy(yypvt[-3].ent, yypvt[-2].ent, yypvt[-0].ent); } break;
XXcase 16:
XX# line 83 "gram.y"
XX{ yyval.enode = new ('v', yypvt[-0].ent); } break;
XXcase 17:
XX# line 84 "gram.y"
XX{ yyval.enode = new ('f', 0L, yypvt[-0].enode); } break;
XXcase 18:
XX# line 86 "gram.y"
XX{ yyval.enode = new (O_REDUCE('+'), yypvt[-3].ent, yypvt[-1].ent); } break;
XXcase 19:
XX# line 88 "gram.y"
XX{ yyval.enode = new (O_REDUCE('*'), yypvt[-3].ent, yypvt[-1].ent); } break;
XXcase 20:
XX# line 90 "gram.y"
XX{ yyval.enode = new (O_REDUCE('a'), yypvt[-3].ent, yypvt[-1].ent); } break;
XXcase 21:
XX# line 91 "gram.y"
XX{ yyval.enode = yypvt[-1].enode; } break;
XXcase 22:
XX# line 92 "gram.y"
XX{ yyval.enode = yypvt[-0].enode; } break;
XXcase 23:
XX# line 93 "gram.y"
XX{ yyval.enode = new ('m', 0L, yypvt[-0].enode); } break;
XXcase 24:
XX# line 94 "gram.y"
XX{ yyval.enode = new ('k', (double) yypvt[-0].ival); } break;
XXcase 25:
XX# line 95 "gram.y"
XX{ yyval.enode = new ('k', yypvt[-0].fval); } break;
XXcase 26:
XX# line 96 "gram.y"
XX{ yyval.enode = new ('~', 0L, yypvt[-0].enode); } break;
XXcase 27:
XX# line 97 "gram.y"
XX{ yyval.enode = new ('~', 0L, yypvt[-0].enode); } break;
XXcase 28:
XX# line 100 "gram.y"
XX{ yyval.enode = new ('+', yypvt[-2].enode, yypvt[-0].enode); } break;
XXcase 29:
XX# line 101 "gram.y"
XX{ yyval.enode = new ('-', yypvt[-2].enode, yypvt[-0].enode); } break;
XXcase 30:
XX# line 102 "gram.y"
XX{ yyval.enode = new ('*', yypvt[-2].enode, yypvt[-0].enode); } break;
XXcase 31:
XX# line 103 "gram.y"
XX{ yyval.enode = new ('/', yypvt[-2].enode, yypvt[-0].enode); } break;
XXcase 33:
XX# line 105 "gram.y"
XX{ yyval.enode = new ('?', yypvt[-4].enode, new(':', yypvt[-2].enode, yypvt[-0].enode)); } break;
XXcase 34:
XX# line 106 "gram.y"
XX{ yyval.enode = new ('<', yypvt[-2].enode, yypvt[-0].enode); } break;
XXcase 35:
XX# line 107 "gram.y"
XX{ yyval.enode = new ('=', yypvt[-2].enode, yypvt[-0].enode); } break;
XXcase 36:
XX# line 108 "gram.y"
XX{ yyval.enode = new ('>', yypvt[-2].enode, yypvt[-0].enode); } break;
XXcase 37:
XX# line 109 "gram.y"
XX{ yyval.enode = new ('&', yypvt[-2].enode, yypvt[-0].enode); } break;
XXcase 38:
XX# line 110 "gram.y"
XX{ yyval.enode = new ('|', yypvt[-2].enode, yypvt[-0].enode); } break;
XXcase 39:
XX# line 111 "gram.y"
XX{ yyval.enode = new ('~', 0L, new ('>', yypvt[-3].enode, yypvt[-0].enode)); } break;
XXcase 40:
XX# line 112 "gram.y"
XX{ yyval.enode = new ('~', 0L, new ('=', yypvt[-3].enode, yypvt[-0].enode)); } break;
XXcase 41:
XX# line 113 "gram.y"
XX{ yyval.enode = new ('~', 0L, new ('<', yypvt[-3].enode, yypvt[-0].enode)); } break;
XXcase 42:
XX# line 116 "gram.y"
XX{ yyval.ent = lookat(yypvt[-0].ival , yypvt[-1].ival); } break; 
XX		}
XX		goto yystack;  /* stack new state and value */
XX
XX	}
SHAR_EOF
if test 11880 -ne "`wc -c gram.c`"
then
echo shar: error transmitting gram.c '(should have been 11880 characters)'
fi
echo shar: extracting interp.c
sed 's/^XX//' << \SHAR_EOF > interp.c
XX/*	SC	A Spreadsheet Calculator
XX *		Expression interpreter and assorted support routines.
XX *
XX *		original by James Gosling, September 1982
XX *		modified by Mark Weiser and Bruce Israel, 
XX *			University of Maryland
XX *
XX *              More mods Robert Bond, 12/86
XX *		Major mods to run on VMS and AMIGA, 1/17/87
XX */
XX
XX#include "sc.h"
XX#define DEFCOLDELIM ':'
XX
XXchar *malloc();
XX
XXdouble dosum(minr, minc, maxr, maxc)
XXint minr, minc, maxr, maxc;
XX{
XX    double v;
XX    register r,c;
XX    register struct ent *p;
XX
XX    v = 0;
XX    for (r = minr; r<=maxr; r++)
XX	for (c = minc; c<=maxc; c++)
XX	    if ((p = tbl[r][c]) && p->flags&is_valid)
XX		v += p->v;
XX    return v;
XX}
XX
XXdouble doprod(minr, minc, maxr, maxc)
XXint minr, minc, maxr, maxc;
XX{
XX    double v;
XX    register r,c;
XX    register struct ent *p;
XX
XX    v = 1;
XX    for (r = minr; r<=maxr; r++)
XX	for (c = minc; c<=maxc; c++)
XX	    if ((p = tbl[r][c]) && p->flags&is_valid)
XX		v *= p->v;
XX    return v;
XX}
XX
XXdouble doavg(minr, minc, maxr, maxc)
XXint minr, minc, maxr, maxc;
XX{
XX    double v;
XX    register r,c,count;
XX    register struct ent *p;
XX
XX    v = 0;
XX    count = 0;
XX    for (r = minr; r<=maxr; r++)
XX	for (c = minc; c<=maxc; c++)
XX	    if ((p = tbl[r][c]) && p->flags&is_valid) {
XX		v += p->v;
XX		count++;
XX	    }
XX
XX    return (v / (double)count);
XX}
XX
XXdouble eval(e)
XXregister struct enode *e; {
XX    if (e==0) return 0;
XX    switch (e->op) {
XX	case '+':	return (eval(e->e.o.left) + eval(e->e.o.right));
XX	case '-':	return (eval(e->e.o.left) - eval(e->e.o.right));
XX	case '*':	return (eval(e->e.o.left) * eval(e->e.o.right));
XX	case '/':     {	double denom = eval (e->e.o.right);
XX			return denom ? eval(e->e.o.left) / denom : 0; }
XX	case '<':	return (eval(e->e.o.left) < eval(e->e.o.right));
XX	case '=':	return (eval(e->e.o.left) == eval(e->e.o.right));
XX	case '>':	return (eval(e->e.o.left) > eval(e->e.o.right));
XX	case '&':	return (eval(e->e.o.left) != 0.0 &&
XX			       eval(e->e.o.right) != 0.0) ? 1.0 : 0.0;
XX	case '|':	return (eval(e->e.o.left) != 0.0 ||
XX			       eval(e->e.o.right) != 0.0) ? 1.0 : 0.0;
XX	case '?':	return eval(e->e.o.left) ? eval(e->e.o.right->e.o.left)
XX						 : eval(e->e.o.right->e.o.right);
XX	case 'm':	return (-eval(e->e.o.right));
XX	case 'f':	return (eval(e->e.o.right));
XX	case '~':	return (!eval(e->e.o.right));
XX	case 'k':	return (e->e.k);
XX	case 'v':	return (e->e.v->v);
XX	case O_REDUCE('+'):
XX 	case O_REDUCE('*'):
XX 	case O_REDUCE('a'):
XX	    {	register r,c;
XX		register maxr, maxc;
XX		register minr, minc;
XX		maxr = ((struct ent *) e->e.o.right) -> row;
XX		maxc = ((struct ent *) e->e.o.right) -> col;
XX		minr = ((struct ent *) e->e.o.left) -> row;
XX		minc = ((struct ent *) e->e.o.left) -> col;
XX		if (minr>maxr) r = maxr, maxr = minr, minr = r;
XX		if (minc>maxc) c = maxc, maxc = minc, minc = c;
XX	        switch (e->op) {
XX	            case O_REDUCE('+'): return dosum(minr, minc, maxr, maxc);
XX 	            case O_REDUCE('*'): return doprod(minr, minc, maxr, maxc);
XX 	            case O_REDUCE('a'): return doavg(minr, minc, maxr, maxc);
XX		}
XX	    }
XX    }
XX}
XX
XX#define MAXPROP 7
XX
XXEvalAll () {
XX    int lastct,repct = 0;
XX
XX    while ((lastct = RealEvalAll()) && (repct++ <= MAXPROP));
XX
XX    repct--;
XX}
XX
XXint RealEvalAll () {
XX    register i,j;
XX    int chgct = 0;
XX    register struct ent *p;
XX    for (i=0; i<=maxrow; i++)
XX	for (j=0; j<=maxcol; j++)
XX	    if ((p=tbl[i][j]) && p->expr) {
XX		double v = eval (p->expr);
XX		if (v != p->v) {
XX		    p->v = v; chgct++;
XX		    p->flags |= (is_changed|is_valid);
XX		}
XX	    }
XX    return(chgct);
XX}
XX
XXstruct enode *new(op,a1,a2)
XXstruct enode *a1, *a2; {
XX    register struct enode *p = (struct enode *) malloc (sizeof (struct enode));
XX    p->op = op;
XX    switch (op) {
XX    case O_VAR: p->e.v = (struct ent *) a1; break;
XX    case O_CONST: p->e.k = *(double *)&a1; break;
XX    default: p->e.o.left = a1; p->e.o.right = a2;
XX    }
XX    return p;
XX}
XX
XXcopy (dv, v1, v2)
XXstruct ent *dv, *v1, *v2;
XX{
XX    register r,c;
XX    register struct ent *p;
XX    register struct ent *n;
XX    register deltar, deltac;
XX    int maxr, maxc;
XX    int minr, minc;
XX    int dr, dc;
XX
XX    dr = dv->row;
XX    dc = dv->col;
XX    maxr = v2->row;
XX    maxc = v2->col;
XX    minr = v1->row;
XX    minc = v1->col;
XX    if (minr>maxr) r = maxr, maxr = minr, minr = r;
XX    if (minc>maxc) c = maxc, maxc = minc, minc = c;
XX    if (dr+maxr-minr >= MAXROWS  || 
XX           dc+maxc-minc >= MAXCOLS) {
XX	error ("The table can't be any bigger");
XX	return;
XX    }
XX    deltar = dr-minr;
XX    deltac = dc-minc;
XX    FullUpdate++;
XX    for (r = minr; r<=maxr; r++)
XX	for (c = minc; c<=maxc; c++) {
XX	    n = lookat (r+deltar, c+deltac);
XX	    clearent(n);
XX	    if (p = tbl[r][c]) {
XX		n -> v = p -> v;
XX		n -> flags = p -> flags;
XX		n -> expr = copye(p->expr, deltar, deltac);
XX		n -> label = 0;
XX		if (p -> label) {
XX		    n -> label = (char *)
XX				 malloc (strlen (p -> label) + 1);
XX		    strcpy (n -> label, p -> label);
XX		}
XX	    }
XX	}
XX}
XX
XXlet (v, e)
XXstruct ent *v;
XXstruct enode *e; {
XX    efree (v->expr);
XX    if (constant(e)) {
XX	v->v = eval(e);
XX	v->expr = 0;
XX	efree(e);
XX    } else
XX	v->expr = e;
XX    v->flags |= (is_changed|is_valid);
XX    changed++;
XX    modflg++;
XX}
XX
XXclearent (v)
XXstruct ent *v; {
XX    if (!v)
XX	return;
XX    label(v,"",-1);
XX    v->v = 0;
XX    if (v->expr)
XX	efree(v->expr);
XX    v->expr = 0;
XX    v->flags |= (is_changed);
XX    v->flags &= ~(is_valid);
XX    changed++;
XX    modflg++;
XX}
XX
XXconstant(e)
XXregister struct enode *e; {
XX    return e==0 || e->op == O_CONST 
XX	|| (e->op != O_VAR
XX	 && (e->op&~0177) != O_REDUCE(0)
XX	 && constant (e->e.o.left)
XX	 && constant(e->e.o.right));
XX}
XX
XXefree (e)
XXregister struct enode *e; {
XX    if (e) {
XX	if (e->op != O_VAR && e->op !=O_CONST && (e->op&~0177) != O_REDUCE(0)) {
XX	    efree (e->e.o.left);
XX	    efree (e->e.o.right);
XX	}
XX	free (e);
XX    }
XX}
XX
XXlabel (v, s, flushdir)
XXregister struct ent *v;
XXregister char *s; {
XX    if (v) {
XX	if (flushdir==0 && v->flags&is_valid) {
XX	    register struct ent *tv;
XX	    if (v->col>0 && ((tv=lookat(v->row,v->col-1))->flags&is_valid)==0)
XX		v = tv, flushdir = 1;
XX	    else if (((tv=lookat (v->row,v->col+1))->flags&is_valid)==0)
XX		v = tv, flushdir = -1;
XX	    else flushdir = -1;
XX	}
XX	if (v->label) free(v->label);
XX	if (s && s[0]) {
XX	    v->label = (char *) malloc (strlen(s)+1);
XX	    strcpy (v->label, s);
XX	} else v->label = 0;
XX	v->flags |= is_lchanged;
XX	if (flushdir<0) v->flags |= is_leftflush;
XX	else v->flags &= ~is_leftflush;
XX	FullUpdate++;
XX	modflg++;
XX    }
XX}
XX
XXdecodev (v)
XXregister struct ent *v; {
XX	if (v) sprintf (line+linelim, "%s%d", coltoa(v->col), v->row);
XX	else sprintf (line+linelim,"VAR?");
XX	linelim += strlen (line+linelim);
XX}
XX
XXchar *
XXcoltoa(col)
XXint col;
XX{
XX    static char rname[3];
XX    register char *p = rname;
XX
XX    if (col < 0 || col > 25*26) 
XX	debug("coltoa: invalid col: %d", col);
XX
XX    if (col > 25) {
XX	*p++ = col/26 + 'A' - 1;
XX	col %= 26;
XX    }
XX    *p++ = col+'A';
XX    *p = 0;
XX    return(rname);
XX}
XX
XXdecompile(e, priority)
XXregister struct enode *e; {
XX    register char *s;
XX    if (e) {
XX	int mypriority;
XX	switch (e->op) {
XX	default: mypriority = 99; break;
XX	case '?': mypriority = 1; break;
XX	case ':': mypriority = 2; break;
XX	case '|': mypriority = 3; break;
XX	case '&': mypriority = 4; break;
XX	case '<': case '=': case '>': mypriority = 6; break;
XX	case '+': case '-': mypriority = 8; break;
XX	case '*': case '/': mypriority = 10; break;
XX	}
XX	if (mypriority<priority) line[linelim++] = '(';
XX	switch (e->op) {
XX	case 'f':	{ 
XX			    for (s="fixed "; line[linelim++] = *s++;);
XX			    linelim--;
XX			    decompile (e->e.o.right, 30);
XX			    break;
XX			}
XX	case 'm':	line[linelim++] = '-';
XX			decompile (e->e.o.right, 30);
XX			break;
XX	case '~':	line[linelim++] = '~';
XX			decompile (e->e.o.right, 30);
XX			break;
XX	case 'v':	decodev (e->e.v);
XX			break;
XX	case 'k':	sprintf (line+linelim,"%.8g",e->e.k);
XX			linelim += strlen (line+linelim);
XX			break;
XX	case O_REDUCE('+'):
XX			for (s="@sum("; line[linelim++] = *s++;);
XX			goto more;
XX	case O_REDUCE('*'):
XX			for (s="@prod("; line[linelim++] = *s++;);
XX			goto more;
XX	case O_REDUCE('a'):
XX			for (s="@avg("; line[linelim++] = *s++;);
XX	more:		linelim--;
XX			decodev (e->e.o.left);
XX			line[linelim++] = ':';
XX			decodev (e->e.o.right);
XX			line[linelim++] = ')';
XX			break;
XX
XX	default:	decompile (e->e.o.left, mypriority);
XX			line[linelim++] = e->op;
XX			decompile (e->e.o.right, mypriority+1);
XX			break;
XX	}
XX	if (mypriority<priority) line[linelim++] = ')';
XX    } else line[linelim++] = '?';
XX}
XX
XXeditv (row, col) {
XX    sprintf (line, "let %s%d = ", coltoa(col), row);
XX    linelim = strlen(line);
XX    editexp(row,col);
XX}
XX
XXeditexp(row,col) {
XX    register struct ent *p;
XX    p = lookat (row, col);
XX    if (p->flags&is_valid)
XX	if (p->expr) {
XX	    decompile (p->expr);
XX	    line[linelim] = 0;
XX	} else {
XX	    sprintf (line+linelim, "%.8g", p->v);
XX	    linelim += strlen (line+linelim);
XX	}
XX}
XX
XXedits (row, col) {
XX    register struct ent *p = lookat (row, col);
XX    sprintf (line, "%sstring %s%d = \"",
XX			((p->flags&is_leftflush) ? "left" : "right"),
XX			coltoa(col), row);
XX    linelim = strlen(line);
XX    sprintf (line+linelim, "%s", p->label);
XX    linelim += strlen (line+linelim);
XX}
XX
XXprintfile (fname) {
XX    FILE *f = fopen(fname, "w");
XX    char pline[1000];
XX    int plinelim;
XX    register row, col;
XX    register struct ent **p;
XX    if (f==0) {
XX	error ("Can't create %s", fname);
XX	return;
XX    }
XX    for (row=0;row<=maxrow; row++) {
XX	register c = 0;
XX	plinelim = 0;
XX	for (p = &tbl[row][col=0]; col<=maxcol; col++, p++) {
XX	    if (*p) {
XX		char *s;
XX		while (plinelim<c) pline[plinelim++] = ' ';
XX		plinelim = c;
XX		if ((*p)->flags&is_valid) {
XX		    sprintf (pline+plinelim,"%*.*f",fwidth[col],precision[col],
XX				(*p)->v);
XX		    plinelim += strlen (pline+plinelim);
XX		}
XX		if (s = (*p)->label) {
XX		    register char *d;
XX		    d = pline+((*p)->flags&is_leftflush
XX			? c : c-strlen(s)+fwidth[col]);
XX		    while (d>pline+plinelim) pline[plinelim++] = ' ';
XX		    if (d<pline) d = pline;
XX		    while (*s) *d++ = *s++;
XX		    if (d-pline>plinelim) plinelim = d-pline;
XX		}
XX	    }
XX	    c += fwidth [col];
XX	}
XX	fprintf (f,"%.*s\n",plinelim,pline);
XX    }
XX    fclose (f);
XX}
XX
XXtblprintfile (fname) {
XX    FILE *f = fopen(fname, "w");
XX    char pline[1000];
XX    int plinelim;
XX    register row, col;
XX    register struct ent **p;
XX    char coldelim = DEFCOLDELIM;
XX
XX    if (f==0) {
XX	error ("Can't create %s", fname);
XX	return;
XX    }
XX    for (row=0;row<=maxrow; row++) {
XX	register c = 0;
XX	plinelim = 0;
XX	for (p = &tbl[row][col=0]; col<=maxcol; col++, p++) {
XX	    if (*p) {
XX		char *s;
XX		if ((*p)->flags&is_valid) {
XX		    fprintf (f,"%.*f",precision[col],
XX				(*p)->v);
XX		}
XX		if (s = (*p)->label) {
XX	            fprintf (f,"%s",s);
XX		}
XX	    }
XX	    fprintf(f,"%c",coldelim);
XX	}
XX	fprintf (f,"\n",pline);
XX    }
XX    fclose (f);
XX}
XX
XXstruct enode *copye (e, Rdelta, Cdelta)
XXregister struct enode *e; {
XX    register struct enode *ret;
XX    if (e==0) ret = 0;
XX    else {
XX	ret = (struct enode *) malloc (sizeof (struct enode));
XX	ret->op = e->op;
XX	switch (ret->op) {
XX	case 'v':
XX		ret->e.v = lookat (e->e.v->row+Rdelta, e->e.v->col+Cdelta);
XX		break;
XX	case 'k':
XX		ret->e.k = e->e.k;
XX		break;
XX	case 'f':
XX		ret->e.o.right = copye (e->e.o.right,0,0);
XX		ret->e.o.left = 0;
XX 		break;
XX 	case O_REDUCE('+'):
XX 	case O_REDUCE('*'):
XX 	case O_REDUCE('a'):
XX 		ret->e.o.right = (struct enode *) lookat (
XX 		          ((struct ent *)e->e.o.right)->row+Rdelta,
XX 		          ((struct ent *)e->e.o.right)->col+Cdelta
XX 		   );
XX 		ret->e.o.left = (struct enode *) lookat (
XX 		          ((struct ent *)e->e.o.left)->row+Rdelta,
XX 		          ((struct ent *)e->e.o.left)->col+Cdelta
XX 		   );
XX		break;
XX	default:
XX		ret->e.o.right = copye (e->e.o.right,Rdelta,Cdelta);
XX		ret->e.o.left = copye (e->e.o.left,Rdelta,Cdelta);
XX		break;
XX	}
XX    }
XX    return ret;
XX}
XX
XX/*
XX * sync_refs and sync_ref are used to remove references to
XX * deleted struct ents.  Note that the deleted structure must still
XX * be hanging around before the call, but not referenced by an entry
XX * in tbl.  Thus the free_ent, fix_ent calls in sc.c
XX */
XX
XXsync_refs () {
XX    register i,j;
XX    register struct ent *p;
XX    for (i=0; i<=maxrow; i++)
XX	for (j=0; j<=maxcol; j++)
XX	    if ((p=tbl[i][j]) && p->expr)
XX		sync_ref(p->expr);
XX}
XX
XX
XXsync_ref(e)
XXregister struct enode *e;
XX{
XX    if (e==0)
XX	return;
XX    else {
XX	switch (e->op) {
XX	case 'v':
XX		e->e.v = lookat(e->e.v->row, e->e.v->col);
XX		break;
XX	case 'k':
XX		break;
XX 	case O_REDUCE('+'):
XX 	case O_REDUCE('*'):
XX 	case O_REDUCE('a'):
XX 		e->e.o.right = (struct enode *) lookat (
XX 		          ((struct ent *)e->e.o.right)->row,
XX 		          ((struct ent *)e->e.o.right)->col
XX 		   );
XX 		e->e.o.left = (struct enode *) lookat (
XX 		          ((struct ent *)e->e.o.left)->row,
XX 		          ((struct ent *)e->e.o.left)->col
XX 		   );
XX		break;
XX	default:
XX		sync_ref(e->e.o.right);
XX		sync_ref(e->e.o.left);
XX		break;
XX	}
XX    }
XX}
XX
XXhiderow(arg)
XX{
XX    register int r1;
XX    register int r2;
XX
XX    r1 = currow;
XX    r2 = r1 + arg - 1;
XX    if (r1 < 0 || r1 > r2) {
XX	error("Invalid Range");
XX	return;
XX    }
XX    if (r2 > MAXROWS-2) {
XX	error("You can't hide the last row");
XX	return;
XX    }
XX    FullUpdate++;
XX    while (r1 <= r2)
XX	hidden_row[r1++] = 1;
XX}
XX
XXhidecol(arg)
XX{
XX    register int c1;
XX    register int c2;
XX
XX    c1 = curcol;
XX    c2 = c1 + arg - 1;
XX    if (c1 < 0 || c1 > c2) {
XX	error("Invalid Range");
XX	return;
XX    }
XX    if (c2 > MAXCOLS-2) {
XX	error("You can't hide the last col");
XX	return;
XX    }
XX    FullUpdate++;
XX    while (c1 <= c2)
XX	hidden_col[c1++] = 1;
XX}
XX
XXshowrow(r1, r2)
XX{
XX    if (r1 < 0 || r1 > r2) {
XX	error("Invalid Range");
XX	return;
XX    }
XX    if (r2 > MAXROWS-1) {
XX	r2 = MAXROWS-1;
XX    }
XX    FullUpdate++;
XX    while (r1 <= r2)
XX	hidden_row[r1++] = 0;
XX}
XX
XXshowcol(c1, c2)
XX{
XX    if (c1 < 0 || c1 > c2) {
XX	error("Invalid Range");
XX	return;
XX    }
XX    if (c2 > MAXCOLS-1) {
XX	c2 = MAXCOLS-1;
XX    }
XX    FullUpdate++;
XX    while (c1 <= c2)
XX	hidden_col[c1++] = 0;
XX}
SHAR_EOF
if test 13644 -ne "`wc -c interp.c`"
then
echo shar: error transmitting interp.c '(should have been 13644 characters)'
fi
echo shar: extracting cmds.c
sed 's/^XX//' << \SHAR_EOF > cmds.c
XX/*	SC	A Spreadsheet Calculator
XX *		Main driver
XX *
XX *		original by James Gosling, September 1982
XX *		modifications by Mark Weiser and Bruce Israel,
XX *			University of Maryland
XX *
XX *              More mods Robert Bond, 12/86
XX *		Major mods to run on VMS and AMIGA, 1/17/87
XX *
XX */
XX
XX#include "sc.h"
XX
XXextern char *malloc();
XX
XXduprow()
XX{
XX    if (currow >= MAXROWS - 1 || maxrow >= MAXROWS - 1) {
XX	error ("The table can't be any bigger");
XX	return;
XX    }
XX    modflg++;
XX    currow++;
XX    openrow (currow);
XX    for (curcol = 0; curcol <= maxcol; curcol++) {
XX	register struct ent *p = tbl[currow - 1][curcol];
XX	if (p) {
XX	    register struct ent *n;
XX	    n = lookat (currow, curcol);
XX	    n -> v = p -> v;
XX	    n -> flags = p -> flags;
XX	    n -> expr = copye (p -> expr, 1, 0);
XX	    n -> label = 0;
XX	    if (p -> label) {
XX		n -> label = (char *)
XX			     malloc (strlen (p -> label) + 1);
XX		strcpy (n -> label, p -> label);
XX	    }
XX	}
XX    }
XX    for (curcol = 0; curcol <= maxcol; curcol++) {
XX	register struct ent *p = tbl[currow][curcol];
XX	if (p && (p -> flags & is_valid) && !p -> expr)
XX	    break;
XX    }
XX    if (curcol > maxcol)
XX	curcol = 0;
XX}
XX
XXdupcol() 
XX{
XX    if (curcol >= MAXCOLS - 1 || maxcol >= MAXCOLS - 1) {
XX	error ("The table can't be any wider");
XX	return;
XX    }
XX    modflg++;
XX    curcol++;
XX    opencol (curcol);
XX    for (currow = 0; currow <= maxrow; currow++) {
XX	register struct ent *p = tbl[currow][curcol - 1];
XX	if (p) {
XX	    register struct ent *n;
XX	    n = lookat (currow, curcol);
XX	    n -> v = p -> v;
XX	    n -> flags = p -> flags;
XX	    n -> expr = copye (p -> expr, 0, 1);
XX	    n -> label = 0;
XX	    if (p -> label) {
XX		n -> label = (char *)
XX			     malloc (strlen (p -> label) + 1);
XX		strcpy (n -> label, p -> label);
XX	    }
XX	}
XX    }
XX    for (currow = 0; currow <= maxrow; currow++) {
XX	register struct ent *p = tbl[currow][curcol];
XX	if (p && (p -> flags & is_valid) && !p -> expr)
XX	    break;
XX    }
XX    if (currow > maxrow)
XX	currow = 0;
XX}
XX
XXinsertrow(arg)
XX{
XX    while (--arg>=0) openrow (currow);
XX}
XX
XXdeleterow(arg)
XX{
XX    flush_saved();
XX    erase_area(currow, 0, currow + arg - 1, maxcol);
XX    currow += arg;
XX    while (--arg>=0) closerow (--currow);
XX    sync_refs();
XX}
XX
XXinsertcol(arg)
XX{
XX    while (--arg>=0) opencol(curcol);
XX}
XX
XXdeletecol(arg)
XX{
XX    flush_saved();
XX    erase_area(0, curcol, maxrow, curcol + arg - 1);
XX    curcol += arg;
XX    while (--arg>=0) closecol (--curcol);
XX    sync_refs();
XX}
XX
XXvalueizerow(arg)
XX{
XX    valueize_area(currow, 0, currow + arg - 1, maxcol);
XX}
XX
XXvalueizecol(arg)
XX{
XX    valueize_area(0, curcol, maxrow, curcol + arg - 1);
XX}
XX
XXerase_area(sr, sc, er, ec)
XXint sr, sc, er, ec;
XX{
XX    register int r, c;
XX    register struct ent **p;
XX
XX    if (sr > er) {
XX	r = sr; sr = er; er= r;	
XX    }
XX
XX    if (sc > ec) {
XX	c = sc; sc = ec; ec= c;	
XX    }
XX
XX    if (sr < 0)
XX	sr = 0; 
XX    if (sc < 0)
XX	sc = 0;
XX    if (er >= MAXROWS)
XX	er = MAXROWS-1;
XX    if (ec >= MAXCOLS)
XX	ec = MAXCOLS-1;
XX
XX    for (r = sr; r <= er; r++) {
XX	for (c = sc; c <= ec; c++) {
XX	    p = &tbl[r][c];
XX	    if (*p) {
XX		free_ent(*p);
XX		*p = 0;
XX	    }
XX	}
XX    }
XX
XX}
XX
XXvalueize_area(sr, sc, er, ec)
XXint sr, sc, er, ec;
XX{
XX    register int r, c;
XX    register struct ent *p;
XX
XX    if (sr > er) {
XX	r = sr; sr = er; er= r;	
XX    }
XX
XX    if (sc > ec) {
XX	c = sc; sc = ec; ec= c;	
XX    }
XX
XX    if (sr < 0)
XX	sr = 0; 
XX    if (sc < 0)
XX	sc = 0;
XX    if (er >= MAXROWS)
XX	er = MAXROWS-1;
XX    if (ec >= MAXCOLS)
XX	ec = MAXCOLS-1;
XX
XX    for (r = sr; r <= er; r++) {
XX	for (c = sc; c <= ec; c++) {
XX	    p = tbl[r][c];
XX	    if (p && p->expr) {
XX		efree(p->expr);
XX		p->expr = 0;
XX	    }
XX	}
XX    }
XX
XX}
XX
XXpullcells(to_insert)
XX{
XX    register struct ent *p, *n;
XX    register int deltar, deltac;
XX    int minrow, mincol;
XX    int maxrow, maxcol;
XX    int numrows, numcols;
XX
XX    if (!to_fix)
XX	return;
XX
XX    switch (to_insert) {
XX    case 'm':
XX    case 'r':
XX    case 'c':
XX	break;
XX    default:
XX	return;
XX    }
XX
XX    minrow = MAXROWS; 
XX    mincol = MAXCOLS;
XX    maxrow = 0;
XX    maxcol = 0;
XX
XX    for (p = to_fix; p; p = p->next) {
XX	if (p->row < minrow)
XX	    minrow = p->row;
XX	if (p->row > maxrow)
XX	    maxrow = p->row;
XX	if (p->col < mincol)
XX	    mincol = p->col;
XX	if (p->col > maxcol)
XX	    maxcol = p->col;
XX    }
XX
XX    numrows = maxrow - minrow + 1;
XX    numcols = maxcol - mincol + 1;
XX    deltar = currow - minrow;
XX    deltac = curcol - mincol;
XX
XX    if (to_insert == 'r') {
XX	insertrow(numrows);
XX	deltac = 0;
XX    } else if (to_insert == 'c') {
XX	insertcol(numcols);
XX	deltar = 0;
XX    }
XX
XX    FullUpdate++;
XX    modflg++;
XX
XX    for (p = to_fix; p; p = p->next) {
XX	n = lookat (p->row + deltar, p->col + deltac);
XX	clearent(n);
XX	n -> flags = p -> flags & ~is_deleted;
XX	n -> v = p -> v;
XX	n -> expr = copye(p->expr, deltar, deltac);
XX	n -> label = 0;
XX	if (p -> label) {
XX	    n -> label = (char *)
XX			 malloc(strlen(p->label)+1);
XX	    strcpy (n -> label, p -> label);
XX	}
XX    }
XX}
XX
XXshowcol_op()
XX{
XX    register int i,j;
XX    for (i=0; i<MAXCOLS; i++)
XX	if (hidden_col[i]) 
XX	    break;
XX    for(j=i; j<MAXCOLS; j++)
XX	if (!hidden_col[j])
XX	    break;
XX    j--;
XX    if (i<MAXCOLS) {
XX	sprintf(line,"show %s:", coltoa(i));
XX	sprintf(line + strlen(line),"%s",coltoa(j));
XX	linelim = strlen (line);
XX    }
XX}
XX
XXshowrow_op()
XX{
XX    register int i,j;
XX    for (i=0; i<MAXROWS; i++)
XX	if (hidden_row[i]) 
XX	    break;
XX    for(j=i; j<MAXROWS; j++)
XX	if (!hidden_row[j]) {
XX	    break;
XX	}
XX    j--;
XX    if (i<MAXROWS) {
XX	sprintf(line,"show %d:%d", i, j);
XX        linelim = strlen (line);
XX    }
XX}
XX
XXget_qual()
XX{
XX    register int c;
XX
XX    c = nmgetch();
XX    switch (c) {
XX    case 'c':
XX    case 'j':
XX    case 'k':
XX    case ctl(p):
XX    case ctl(n):
XX	return('c');
XX	break;
XX    case 'r':
XX    case 'l':
XX    case 'h':
XX    case ctl(f):
XX    case ctl(b):
XX	return('r');
XX	break;
XX    default:
XX	return(c);
XX    	break;
XX    }
XX}
XX
XXopenrow (rs) {
XX    register    r;
XX    register struct ent **p;
XX    register    c;
XX    register	i;
XX
XX    if (rs > maxrow) maxrow = rs;
XX    if (maxrow >= MAXROWS - 1 || rs > MAXROWS - 1) {
XX	error ("The table can't be any longer");
XX	return;
XX    }
XX    for (i = maxrow+1; i > rs; i--) {
XX	hidden_row[i] = hidden_row[i-1];
XX    }
XX    for (r = ++maxrow; r > rs; r--)
XX	for (c = maxcol + 1, p = &tbl[r][0]; --c >= 0; p++)
XX	    if (p[0] = p[-MAXCOLS])
XX		p[0] -> row++;
XX    p = &tbl[rs][0];
XX    for (c = maxcol + 1; --c >= 0;)
XX	*p++ = 0;
XX    FullUpdate++;
XX    modflg++;
XX}
XX
XXcloserow (r)
XXregister r; {
XX    register struct ent **p;
XX    register c;
XX    register int i;
XX
XX    if (r > maxrow) return;
XX
XX    p = &tbl[r][0];
XX    for (c=maxcol+1; --c>=0; ) {
XX	if (*p)
XX	    free_ent(*p);
XX	*p++ = 0;
XX    }
XX
XX    for (i = r; i < MAXROWS - 1; i++) {
XX	hidden_row[i] = hidden_row[i+1];
XX    }
XX
XX    while (r<maxrow) {
XX	for (c = maxcol+1, p = &tbl[r][0]; --c>=0; p++)
XX	    if (p[0] = p[MAXCOLS])
XX		p[0]->row--;
XX	r++;
XX    }
XX
XX    p = &tbl[maxrow][0];
XX    for (c=maxcol+1; --c>=0; ) *p++ = 0;
XX    maxrow--;
XX    FullUpdate++;
XX    modflg++;
XX}
XX
XXopencol (cs) {
XX    register r;
XX    register struct ent **p;
XX    register c;
XX    register lim = maxcol-cs+1;
XX    int i;
XX
XX    if (cs > maxcol) maxcol = cs;
XX    if (maxcol >= MAXCOLS - 1 || cs > MAXCOLS - 1) {
XX	error ("The table can't be any wider");
XX	return;
XX    }
XX    for (i = maxcol+1; i > cs; i--) {
XX	fwidth[i] = fwidth[i-1];
XX	precision[i] = precision[i-1];
XX	hidden_col[i] = hidden_col[i-1];
XX    }
XX    /* fwidth[cs] = DEFWIDTH;
XX    precision[i] =  DEFPREC;  */
XX
XX    for (r=0; r<=maxrow; r++) {
XX	p = &tbl[r][maxcol+1];
XX	for (c=lim; --c>=0; p--)
XX	    if (p[0] = p[-1])
XX		p[0]->col++;
XX	p[0] = 0;
XX    }
XX    maxcol++;
XX    FullUpdate++;
XX    modflg++;
XX}
XX
XXclosecol (cs) {
XX    register r;
XX    register struct ent **p;
XX    register struct ent *q;
XX    register c;
XX    register lim = maxcol-cs;
XX    int i;
XX
XX    if (lim < 0) return;
XX
XX    for (r=0; r<=maxrow; r++)
XX	if (q = tbl[r][cs]) {
XX	    free_ent(q);
XX	}
XX
XX    for (r=0; r<=maxrow; r++) {
XX	p = &tbl[r][cs];
XX	for (c=lim; --c>=0; p++)
XX	    if (p[0] = p[1])
XX		p[0]->col--;
XX	p[0] = 0;
XX    }
XX
XX    for (i = cs; i < MAXCOLS - 1; i++) {
XX	fwidth[i] = fwidth[i+1];
XX	precision[i] = precision[i+1];
XX	hidden_col[i] = hidden_col[i+1];
XX    }
XX
XX    maxcol--;
XX    FullUpdate++;
XX    modflg++;
XX}
XX
SHAR_EOF
if test 8004 -ne "`wc -c cmds.c`"
then
echo shar: error transmitting cmds.c '(should have been 8004 characters)'
fi
echo shar: extracting curses.c
sed 's/^XX//' << \SHAR_EOF > curses.c
XX/**********************************************************************
XX *
XX * Tiny pseudo "curses" package (runs on U__X, VMS, or MCH_AMIGA)
XX *
XX *	v1.0	870117	DBW - D. Wecker, initial hack
XX *
XX **********************************************************************/
XX
XX#ifdef VMS
XX#include <stsdef.h>
XX#include <ssdef.h>
XX#include <descrip.h>
XX#include <iodef.h>
XX#include <ttdef.h>
XX
XX#define NIBUF   128		/* Input buffer size */
XX#define NOBUF   1024		/* MM says bug buffers win! */
XX#define EFN     0		/* Event flag */
XX
XXchar obuf[NOBUF];		/* Output buffer */
XXint nobuf;			/* # of bytes in above */
XXchar ibuf[NIBUF];		/* Input buffer */
XXint nibuf;			/* # of bytes in above */
XXint ibufi;			/* Read index */
XXint oldmode[2];			/* Old TTY mode bits */
XXint newmode[2];			/* New TTY mode bits */
XXshort iochan;			/* TTY I/O channel */
XXstruct dsc$descriptor  idsc;
XXstruct dsc$descriptor  odsc;
XXchar oname[40];
XXint iosb[2];
XXint term[2];
XXint status;
XX#endif
XX
XX#ifdef MCH_AMIGA
XXextern	char		*Open();
XXextern	long		Read(),Write();
XXextern	void		Close();
XX#define NEW		1006L
XX#define AMG_MAXBUF	1024
XXstatic char		*terminal = 0L;
XXstatic char		scrn_tmp[AMG_MAXBUF+1];
XXstatic long		scrn_tmp_p = 0L;
XX#endif
XX
XX#ifdef U__X
XX#include <sys/ioctl.h>
XX#include <sgtty.h>
XX#include <stdio.h>
XXstruct sgttyb old_tty,new_tty;
XX#endif
XX
XX#ifdef MCH_AMIGA
XX#define	COLS	79
XX#define ROWS	23
XX#else
XX#define	COLS	80
XX#define ROWS	24
XX#endif
XX
XX#define NORMAL	0x00
XX#define BOLD	0x80
XX
XXchar	nscrn[ROWS][COLS],
XX	cscrn[ROWS][COLS],
XX	row,
XX	col,
XX	mode;
XXchar	str[256];
XX
XXmove(y,x)
XXint y,x;
XX    {
XX    row = y;
XX    col = x;
XX    }
XX
XXclrtoeol() {
XX    int i;
XX
XX    for (i = col; i < COLS; i++) nscrn[row][i] = ' ' | mode;
XX    }
XX
XXprintw(fmt,a1,a2,a3,a4,a5)
XXchar	*fmt,*a1,*a2,*a3,*a4,*a5;
XX    {
XX    int i,j;
XX
XX    sprintf(str,fmt,a1,a2,a3,a4,a5);
XX    j = 0;
XX    for (i = col; i < COLS && str[j] != '\000'; i++)
XX	nscrn[row][i] = str[j++] | mode;
XX    col = i;
XX    }
XX
XXclrtobot() {
XX    int i,j;
XX
XX    clrtoeol();
XX    for (i = row+1; i < ROWS; i++)
XX	for (j = 0; j < COLS; j++)
XX	    nscrn[i][j] = ' ' | mode;
XX    }
XX
XXstandout() {
XX    mode = BOLD;
XX    }
XX
XXstandend() {
XX    mode = NORMAL;
XX    }
XX
XXaddstr(s)
XXchar	*s;
XX    {
XX    printw("%s",s);
XX    }
XX
XXinitscr() {
XX    int	    i,j;
XX
XX#ifdef MCH_AMIGA
XX    terminal = Open("RAW:1/1/639/199/DBW_VC (v1.0 870117)",(long)NEW);
XX#endif
XX#ifdef VMS
XX    odsc.dsc$a_pointer = "TT";
XX    odsc.dsc$w_length = strlen(odsc.dsc$a_pointer);
XX    odsc.dsc$b_dtype = DSC$K_DTYPE_T;
XX    odsc.dsc$b_class = DSC$K_CLASS_S;
XX    idsc.dsc$b_dtype = DSC$K_DTYPE_T;
XX    idsc.dsc$b_class = DSC$K_CLASS_S;
XX    do {
XX	idsc.dsc$a_pointer = odsc.dsc$a_pointer;
XX	idsc.dsc$w_length = odsc.dsc$w_length;
XX	odsc.dsc$a_pointer = &oname[0];
XX	odsc.dsc$w_length = sizeof(oname);
XX	status = LIB$SYS_TRNLOG(&idsc, &odsc.dsc$w_length, &odsc);
XX	if (status!=SS$_NORMAL && status!=SS$_NOTRAN) exit(status);
XX	if (oname[0] == 0x1B) {
XX	    odsc.dsc$a_pointer += 4;
XX	    odsc.dsc$w_length -= 4;
XX	    }
XX	}
XX    while (status == SS$_NORMAL);
XX    status = SYS$ASSIGN(&odsc, &iochan, 0, 0);
XX    if (status != SS$_NORMAL) exit(status);
XX    status = SYS$QIOW(EFN, iochan, IO$_SENSEMODE, iosb, 0, 0,
XX	    oldmode, sizeof(oldmode), 0, 0, 0, 0);
XX    if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL) exit(status);
XX    newmode[0] = oldmode[0];
XX    newmode[1] = oldmode[1] | TT$M_PASSALL | TT$M_NOECHO;
XX    status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
XX	    newmode, sizeof(newmode), 0, 0, 0, 0);
XX    if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL) exit(status);
XX#endif
XX
XX#ifdef U__X
XX    ioctl(0,TIOCGETP,&old_tty);
XX    ioctl(0,TIOCGETP,&new_tty);
XX    new_tty.sg_flags |= RAW;
XX    new_tty.sg_flags &= ~ECHO;
XX    ioctl(0,TIOCSETP,&new_tty);
XX#endif
XX
XX    row	    = 0;
XX    col	    = 0;
XX    mode    = NORMAL;
XX    for (i = 0; i < ROWS; i++)
XX	for (j = 0; j < COLS; j++)
XX	    nscrn[i][j] = cscrn[i][j] = ' ';
XX    ttputs("\033[2J");
XX    }
XX
XXclear() {
XX    row = 0;
XX    col = 0;
XX    clrtobot();
XX    }
XX
XXendwin() {
XX    move(ROWS-1,0);
XX    refresh();
XX
XX#ifdef MCH_AMIGA
XX    amg_flush();
XX    Close(terminal);
XX#endif
XX
XX#ifdef VMS
XX    status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
XX		oldmode, sizeof(oldmode), 0, 0, 0, 0);
XX    if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL) exit(status);
XX    status = SYS$DASSGN(iochan);
XX    if (status != SS$_NORMAL) exit(status);
XX#endif
XX
XX#ifdef U__X
XX    ioctl(0,TIOCSETP,&old_tty);
XX#endif
XX
XX    }
XX
XXchar inch() {
XX    return(nscrn[row][col] & 0x7F);
XX    }
XX
XXtouchwin() {
XX    int i,j;
XX
XX    for (i=0; i<ROWS; i++)
XX	for (j=0; j<COLS; j++)
XX	    cscrn[i][j] = ' ';
XX    ttputs("\033[2J");
XX    }
XX
XXrefresh() {
XX    int	i,j,mode,curpos;
XX
XX    mode = NORMAL;
XX    for (i=0; i < ROWS; i++) {
XX	curpos = -1;
XX	for (j = 0; j < COLS; j++) {
XX	    if (nscrn[i][j] != cscrn[i][j]) {
XX		if (curpos == -1) {
XX		    sprintf(str,"\033[%d;%dH",i+1,j+1);
XX		    ttputs(str);
XX		    curpos = j;
XX		    }
XX		else {
XX		    sprintf(str,"\033[%dC",j-curpos);
XX		    ttputs(str);
XX		    curpos = j;
XX		    }
XX		while (nscrn[i][j] != cscrn[i][j]) {
XX		    if (mode == NORMAL && (nscrn[i][j] & BOLD) == BOLD) {
XX			ttputs("\033[7m");
XX			mode = BOLD;
XX			}
XX		    else if (mode == BOLD && (nscrn[i][j] & BOLD) == NORMAL) {
XX			ttputs("\033[0m");
XX			mode = NORMAL;
XX			}
XX		    cscrn[i][j] = nscrn[i][j];
XX		    ttputc(nscrn[i][j] & 0x7F);
XX		    curpos++;
XX		    j++;
XX		    }
XX		}
XX	    }
XX	}
XX    sprintf(str,"\033[%d;%dH",row+1,col+1);
XX    ttputs(str);
XX    if (mode) ttputs("\033[0m");
XX    ttflush();
XX    }
XX
XXttgetc() {
XX#ifdef MCH_AMIGA
XX    unsigned char ch[2];
XX
XX    Read(terminal, ch, 1L);
XX    return (ch[0] & 0xFF);
XX#endif
XX
XX#ifdef VMS
XX    while (ibufi >= nibuf) {
XX	ibufi = 0;
XX	term[0] = 0;
XX	term[1] = 0;
XX	status = SYS$QIOW(EFN, iochan, IO$_READLBLK|IO$M_TIMED,
XX	iosb, 0, 0, ibuf, NIBUF, 0, term, 0, 0);
XX	if (status != SS$_NORMAL) exit(status);
XX	status = iosb[0] & 0xFFFF;
XX	if (status!=SS$_NORMAL && status!=SS$_TIMEOUT) exit(status);
XX	nibuf = (iosb[0]>>16) + (iosb[1]>>16);
XX	if (nibuf == 0) {
XX	    status = SYS$QIOW(EFN, iochan, IO$_READLBLK,
XX	    iosb, 0, 0, ibuf, 1, 0, term, 0, 0);
XX	    if (status != SS$_NORMAL || (status = (iosb[0]&0xFFFF)) != SS$_NORMAL)
XX	    exit(status);
XX	    nibuf = (iosb[0]>>16) + (iosb[1]>>16);
XX	    }
XX	}
XX    return (ibuf[ibufi++] & 0x7F);
XX#endif
XX
XX#ifdef U__X
XX    return(getchar() & 0x7F);
XX#endif
XX    }
XX
XXttputc(c)
XX#ifdef MCH_AMIGA
XXchar c;
XX#endif
XX    {
XX#ifdef MCH_AMIGA
XX    scrn_tmp[scrn_tmp_p++] = c;
XX    if(scrn_tmp_p>=AMG_MAXBUF) amg_flush();
XX#endif
XX
XX#ifdef VMS
XX    if (nobuf >= NOBUF) ttflush();
XX    obuf[nobuf++] = c;
XX#endif
XX
XX#ifdef U__X
XX    fputc(c, stdout);
XX#endif
XX    }
XX
XX#ifdef MCH_AMIGA
XXamg_flush()
XX    {
XX    if(scrn_tmp_p) Write(terminal,scrn_tmp,(long)scrn_tmp_p);
XX    scrn_tmp_p = 0;
XX    }
XX#endif
XX
XXttputs(s)
XXchar	*s;
XX    {
XX    while (*s) ttputc(*s++);
XX    }
XX
XXttflush()
XX    {
XX#ifdef MCH_AMIGA
XX    amg_flush();
XX#endif
XX
XX#ifdef VMS
XX    status = SS$_NORMAL;
XX    if (nobuf != 0) {
XX	status = SYS$QIOW(EFN, iochan, IO$_WRITELBLK|IO$M_NOFORMAT,
XX	iosb, 0, 0, obuf, nobuf, 0, 0, 0, 0);
XX	if (status == SS$_NORMAL) status = iosb[0] & 0xFFFF;
XX	nobuf = 0;
XX	}
XX    return (status);
XX#endif
XX
XX#ifdef U__X
XX    fflush(stdout);
XX#endif
XX    }
XX
SHAR_EOF
if test 7037 -ne "`wc -c curses.c`"
then
echo shar: error transmitting curses.c '(should have been 7037 characters)'
fi
echo shar: extracting experres.h
sed 's/^XX//' << \SHAR_EOF > experres.h
XX	"FIXED",	K_FIXED,
XX	"SUM",	K_SUM,
XX	"PROD",	K_PROD,
XX	"AVE",	K_AVE,
SHAR_EOF
if test 66 -ne "`wc -c experres.h`"
then
echo shar: error transmitting experres.h '(should have been 66 characters)'
fi
echo shar: extracting sc.h
sed 's/^XX//' << \SHAR_EOF > sc.h
XX/*	VC	A Table Calculator
XX *		Common definitions
XX *
XX *		original by James Gosling, September 1982
XX *		modified by Mark Weiser and Bruce Israel,
XX *			University of Maryland
XX *
XX */
XX
XX#include<stdio.h>
XX
XX#ifdef MCH_AMIGA
XX#define ROWS	23
XX#define COLS	79
XX#else
XX#define ROWS	24
XX#define COLS	80
XX#endif
XX
XX#define MAXROWS 200
XX#define MAXCOLS 40
XX
XXstruct ent {
XX    double v;
XX    char *label;
XX    struct enode *expr;
XX    short flags;
XX    short row, col;
XX    struct ent *next;
XX};
XX
XX
XXstruct enode {
XX    int op;
XX    union {
XX	double k;
XX	struct ent *v;
XX	struct {
XX	    struct enode *left, *right;
XX	} o;
XX    } e;
XX};
XX
XX/* op values */
XX#define O_VAR 'v'
XX#define O_CONST 'k'
XX#define O_REDUCE(c) (c+0200)
XX
XX/* flag values */
XX#define is_valid     0001
XX#define is_changed   0002
XX#define is_lchanged  0004
XX#define is_leftflush 0010
XX#define is_deleted   0020
XX
XX#define ctl(c) ('c'&037)
XX
XXstruct ent *tbl[MAXROWS][MAXCOLS];
XX
XXint strow, stcol;
XXint currow, curcol;
XXint savedrow, savedcol;
XXint FullUpdate;
XXint maxrow, maxcol;
XXint fwidth[MAXCOLS];
XXint precision[MAXCOLS];
XXchar hidden_col[MAXCOLS];
XXchar hidden_row[MAXROWS];
XXchar line[1000];
XXint linelim;
XXint changed;
XXstruct ent *to_fix;
XXstruct enode *new();
XXstruct ent *lookat();
XXstruct enode *copye();
XXchar *coltoa();
XX
XXint modflg;
SHAR_EOF
if test 1241 -ne "`wc -c sc.h`"
then
echo shar: error transmitting sc.h '(should have been 1241 characters)'
fi
echo shar: extracting statres.h
sed 's/^XX//' << \SHAR_EOF > statres.h
XX	"FORMAT",	S_FORMAT,
XX	"LABEL",	S_LABEL,
XX	"LEFTSTRING",	S_LEFTSTRING,
XX	"RIGHTSTRING",	S_RIGHTSTRING,
XX	"GET",	S_GET,
XX	"PUT",	S_PUT,
XX	"MERGE",	S_MERGE,
XX	"LET",	S_LET,
XX	"WRITE",	S_WRITE,
XX	"TBL",	S_TBL,
XX	"PROGLET",	S_PROGLET,
XX	"COPY",	S_COPY,
XX	"SHOW",	S_SHOW,
SHAR_EOF
if test 255 -ne "`wc -c statres.h`"
then
echo shar: error transmitting statres.h '(should have been 255 characters)'
fi
echo shar: extracting y.tab.h
sed 's/^XX//' << \SHAR_EOF > y.tab.h
XX
XXtypedef union  {
XX    int ival;
XX    double fval;
XX    struct ent *ent;
XX    struct enode *enode;
XX    char *sval;
XX} YYSTYPE;
XXextern YYSTYPE yylval;
XX# define STRING 257
XX# define NUMBER 258
XX# define FNUMBER 259
XX# define WORD 260
XX# define COL 261
XX# define S_FORMAT 262
XX# define S_LABEL 263
XX# define S_LEFTSTRING 264
XX# define S_RIGHTSTRING 265
XX# define S_GET 266
XX# define S_PUT 267
XX# define S_MERGE 268
XX# define S_LET 269
XX# define S_WRITE 270
XX# define S_TBL 271
XX# define S_PROGLET 272
XX# define S_COPY 273
XX# define S_SHOW 274
XX# define K_FIXED 275
XX# define K_SUM 276
XX# define K_PROD 277
XX# define K_AVE 278
SHAR_EOF
if test 597 -ne "`wc -c y.tab.h`"
then
echo shar: error transmitting y.tab.h '(should have been 597 characters)'
fi
#	End of shell archive
exit 0