home *** CD-ROM | disk | FTP | other *** search
- Path: uunet!rs
- From: rs@uunet.UU.NET (Rich Salz)
- Newsgroups: comp.sources.unix
- Subject: v11i018: Spread sheet program, sc 4.1, Part02/03
- Message-ID: <998@uunet.UU.NET>
- Date: 18 Aug 87 22:52:43 GMT
- Organization: UUNET Communications Services, Arlington, VA
- Lines: 2178
- Approved: rs@uunet.UU.NET
-
- Submitted-by: Robert Bond <rgb@nscpdc.nsc.com>
- Posting-number: Volume 11, Issue 18
- Archive-name: sc4.1/Part02
-
- # This is a shell archive. Remove anything before this line
- # then unpack it by saving it in a file and typing "sh file"
- # (Files unpacked will be owned by you and have default permissions).
- # This archive contains the following files:
- # ./sc.doc
- # ./sc.h
- # ./sc.c
- # ./lex.c
- #
- if `test ! -s ./sc.doc`
- then
- echo "writing ./sc.doc"
- cat > ./sc.doc << '\SHAR\EOF\'
- .TH PNAME 1
- .SH NAME
- pname \- spread sheet calculator
- .SH SYNOPSIS
- .B pname
- [
- .I -x
- ]
- [
- .I file
- ]
-
- .SH DESCRIPTION
- The spread sheet calculator
- .I pname
- is based on rectangular tables much like a financial spread sheet.
- When it is invoked it presents you with an empty
- table organized as rows and columns of cells. Each cell may have a label
- string associated with it and an expression. The expression may be a
- constant or it may compute something based on other entries.
-
- The single option
- .I -x
- causes the
- .I put
- and
- .I get
- commands to encrypt and decrypt the data files.
-
- When \fIpname\fR is running, the screen is divided into four regions. The top
- line is for entering commands. The second line is for messages from
- \fIpname\fR.
- The third line and the first four columns show the row and column numbers.
- The rest of the screen forms a window looking at the table.
- The screen has two
- cursors: a cell cursor (indicated by a '<' on the screen) and a character
- cursor (indicated by the terminal's hardware cursor). The cell and
- character cursors are often the same. They will differ when a command
- is being typed on the top line.
-
- Commands which use the terminal's control key
- such as ^N will work both when a
- command is being typed and when in normal mode.
-
- The cursor control commands and the row, column commands can be
- prefixed by a numeric argument indicating how many times the command
- is to be executed. "^U" can be used before the number if
- the number is to be entered while a command is being typed
- into the command line.
-
- Cursor control commands:
-
- .IP ^N
- Move the cell cursor to the next row.
-
- .IP ^P
- Move the cell cursor to the previous row.
-
- .IP ^F
- Move the cell cursor forward one column.
-
- .IP ^B
- Move the cell cursor backward one column.
-
- .IP ^H
- Backspace one character.
-
- .IP "h, j, k, l"
- Alternate cursor controls (left, down, up, right).
-
- .IP "Arrow Keys"
- The terminal's arrow keys provide another alternate set of cell
- cursor controls if they exist and are supported in the
- .I termcap
- entry.
- Some terminals have arrow keys which conflict
- with other control key codes. For example, a terminal could send ^H when the
- back arrow key is depressed. In these cases, the conflicting arrow key
- performs the same function as the key combination it mimics.
-
- .IP 0
- Move the cell cursor to column 0 of the current row.
-
- .IP $
- Move the cell cursor to the last valid column in the current row.
-
- .IP ^
- Move the cell cursor to row 0 of the current column.
-
- .IP #
- Move the cell cursor to the last valid row in the current column.
-
- .IP g
- Go to a cell. The program will prompt for the name of a cell.
- Enter a cell number such as "a0" or "ae122".
-
- .PP
- Cell entry and editing commands:
-
- .IP =
- Prompts for an expression which will be evaluated dynamically to produce a
- value for the cell pointed at by the cell cursor. This may be used in
- conjunction with ^V to make one entries value be dependent on anothers.
-
- .IP """
- Enter a label for the current cell.
-
- .IP <
- Enter a label that will be flushed left against the
- left edge of the cell.
-
- .IP >
- Enter a label that will be flushed right against the
- right edge of the cell.
-
- .IP x
- Clears the current cell. You may prefix this command with a count of
- the number of cells on the current row to clear. Cells cleared with
- this command may be recalled with any of the variations of the pull
- command.
-
- .IP e
- Edit the value associated with the current cell. This is identical to '='
- except that the command line starts out containing the old value or
- expression associated with the cell.
-
- .IP E
- Edit the string associated with the current cell. This is the same as
- either "leftstring", "rightstring", or "label", with the additional
- fact that the command line starts out with the old string.
-
- .IP m
- Mark a cell to be used as the source for the copy command.
-
- .IP c
- Copy the last marked cell to the current cell, updating the row and
- column references.
-
- .IP ^T
- Toggle cell display. The current cell's contents are displayed in line
- one when no command being entered or edited. ^T turns the
- display on or off.
-
- .PP
- File operations
-
- .IP G
- Get a new database from a file. If the encryption option
- .I -x
- was specified, the file is decrypted before it is loaded into the
- spread sheet.
-
- .IP P
- Put the current database into a file. If the encryption option
- .I -x
- was specified, the file is encrypted before it is saved.
-
- .IP W
- Write a listing of the current database in a form that matches its
- appearance on the screen. This differs from the "put" command in that
- "put"s files are intended to be reloaded with "get", while "write" produces
- a file for people to look at.
-
- .IP T
- Write a listing of the current database to a file, but put ":"s between
- each field. This is useful for tables that will be further formatted
- by the
- .I tbl
- preprocessor of
- .I nroff.
-
- .IP M
- Merges the database from the named file into the current database. Values,
- expressions and names defined in the named file are written into the current
- file, overwriting the existing entries at those locations.
-
- .PP
- The three output operators,
- .I put, write
- and
- .I tbl
- can pipe their output to a program. To use this option, enter "| program" to
- the prompt asking for a file name. For example, to redirect the output
- of the write command to the printer, you could enter "| lpr -p".
-
- .PP
- Row and Column operations. Members of this class of commands can be used
- on either rows or columns. The second letter of the command is either
- a column designator (one of the characters c, j, k, ^N, ^p) or a
- row designator (one of r, l, h, ^B, ^F).
- Commands which move or copy cells also modify the variable references
- in affected cell expressions.
- Variable references may be frozen by using the "fixed" operator.
-
- .IP "ar, ac"
- Creates a new row (column) immediately following the current row (column).
- It is initialized
- to be a copy of the current one.
-
- .IP "dr, dc"
- Delete this row (column).
-
- .IP "pr, pc, pm"
- Pull deleted rows (columns) back into the spread sheet. The last deleted
- set of cells is put back into the spread sheet at the current location.
- .I Pr
- inserts enough rows to hold the data.
- .I Pc
- inserts enough columns to hold the data.
- .I Pm
- (merge) does not insert rows or columns. It overwrites the cells
- beginning at the current cursor location.
-
- .IP "ir, ic"
- Insert a new row (column) by moving the row (column) containing the cell
- cursor, and all
- following, down (right) one. The new position will be empty.
-
- .IP "zr, zc"
- Hide ("zap") the current row (column). This keeps a row or column from being
- displayed but keeps it in the data base.
-
- .IP "vr, vc"
- Removes expressions from the affected rows (columns), leaving only
- the values which were in the cells before the command
- was executed.
-
- .IP "sr, sc"
- Show hidden rows (columns). Type in a range of rows or columns
- to be revealed. The command default is the first range of rows or
- columns currently hidden.
-
- .IP f
- Sets the output format to be used for printing the numbers in each cell in
- the current column. Type in two numbers which will be the width in
- characters of a column and the number of digits which will follow the
- decimal point. Note that this command has only a column version and
- does not have a second letter. A preceeding count can be used to
- specify that more than one column be formatted.
-
- .PP
- Range Operations:
- Range operations
- affect a rectangular region on the screen.
- All of the commands in this class start with a slash; the second
- letter of the command indicates which command.
- The program will prompt for needed parameters. Phrases surrounded by
- square brackets in the prompt are informational only and may be erased with
- the backspace key.
-
- Prompts requesting variable names
- may be satisfied with either an explicit variable name, such as "A10"
- or with a variable name previously defined in a
- .I /d
- command. Range name prompts require either an explicit range such
- as "A10:B20" or a range name previously defined with a
- .I /d
- command.
-
- .IP "/x"
- Clear a region. Cells cleared with this command may be recalled
- via any of the pull row or column commands.
-
- .IP "/c"
- Copy a region to the area starting at the current cell.
-
- .IP "/f"
- Fill a region with constant values. The start and increment numbers
- may be positive or negative.
-
- .IP "/d"
- This command is used to assign a symbolic name to a single cell or
- a rectangular range of cells on the screen. The parameters are the
- name, surrounded by quotation marks, and either a single cell name
- such as "A10" or a range such as "A10:B20". Names defined in this
- fashion will be used by the program in future prompts, may be
- entered in response to prompts requesting a cell or range name,
- and will be saved when the spread sheet is saved with a
- .I Put
- command. Names defined must be more than two alpha
- characters long to differentiate them from a column names, and must not have
- embedded special characters. Names may include the character "_" or numerals
- as long as they occur after the first three alpha characters.
-
- .IP "/s"
- This command will list the defined range names.
-
- .IP "/u"
- This command is used to undefine a range name. The range must have
- been previously defined.
-
- .PP
- Miscellaneous commands:
-
- .IP q
- Exit from \fIpname\fR. If you were editing a file, and you modified
- it, then
- \fIpname\fR will ask about saving before exiting.
- If you aren't editing a file and haven't saved the data you
- entered, you will get a chance to save the data
- before you exit.
-
- .IP ^C
- Alternate exit command.
-
- .IP ?
- Types a brief helpful message.
-
- .IP "^G or ESC"
- Abort entry of the current command.
-
- .IP "^R or ^L"
- Redraw the screen.
-
- .IP ^V
- Types, in the command line, the name of the cell referenced by
- the cell cursor. This is used when typing in expressions which refer to
- entries in the table.
-
- .IP ^E
- Types, in the command line, the expression of the cell referenced
- by the cell cursor.
-
- .IP ^A
- Types, in the command line, the value of the cell referenced
- by the cell cursor.
-
- .PP
- Expressions that are used with the '=' and 'e' commands have a fairly
- conventional syntax. Terms may be variable names (from the ^V command),
- parenthesised expressions, negated terms, and constants.
- Rectangular regions of the screen may be operated upon with '@' functions
- such as sum (@sum), average (@avg) and product (@prod).
- Terms may be combined using many binary
- operators. Their precedences (from highest to lowest) are: ^; *,/; +,-;
- <,=,>,<=,>=; &; |; ?.
-
- .TP 15
- e+e
- Addition.
-
- .TP 15
- e-e
- Subtraction.
-
- .TP 15
- e*e
- Multiplication.
-
- .TP 15
- e/e
- Division.
-
- .TP 15
- e^e
- Exponentiation.
-
- .TP 15
- @sum(v:v)
- Sum all valid (nonblank) entries in the region whose two corners are defined
- by the two variable (cell) names given.
-
- .TP 15
- @avg(v:v)
- Average all valid (nonblank) entries in the region whose two corners are defined
- by the two variable (cell) names given.
-
- .TP 15
- @prod(v:v)
- Multiply together all valid (nonblank) entries in the region whose two
- corners are defined by the two variable (cell) names given.
-
- .TP 15
- @max(v:v)
- Return the maximum value in specified region.
-
- .TP 15
- @min(v:v)
- Return the minimum value in the specified region.
-
- .TP 15
- @stddev(v:v)
- Return the sample standard deviation of the specified region.
-
- .TP 15
- e?e:e
- Conditional: If the first expression is true then the value of the second is
- returned, otherwise the value of the third is.
-
- .TP 15
- <,=,>,<=,>=
- Relationals: true iff the indicated relation holds.
-
- .TP 15
- &,|
- Boolean connectives.
-
- .TP 15
- fixed
- To make a variable not change automatically when a cell moves,
- put the word \*(lqfixed\*(rq in front of the reference. I.e.
- B1*fixed C3
-
- .PP
- Assorted math functions. Most of these are standard system functions
- more fully described in
- .I math(3).
- All of them operate on floating point numbers (doubles);
- the trig functions operate with angles in radians.
-
- .TP 15
- @exp(expr)
- Returns exponential function of <expr>.
-
- .TP 15
- @ln(expr)
- Returns the natural logarithm of <expr>.
-
- .TP 15
- @log(expr)
- Returns the base 10 logarithm of <expr>.
-
- .TP 15
- @pow(expr1,expr2)
- Returns <expr1> raised to the power of <expr2>.
-
- .TP 15
- @floor(expr)
- Returns returns the largest integer not greater than <expr>.
-
- .TP 15
- @ceil(expr)
- Returns the smallest integer not less than <expr>.
-
- .TP 15
- @rnd(expr)
- Rounds <expr> to the nearest integer.
-
- .TP 15
- @hypot(x,y)
- Returns SQRT(x*x+y*y), taking precautions against unwarranted overflows.
-
- .TP 15
- @fabs(expr)
- Returns the absolute value |expr|.
-
- .TP 15
- @sin(expr), @cos(expr), @tan(expr)
- Return trigonometric functions of radian arguments. The magnitude of the
- arguments are not checked to assure meaningful results.
-
- .TP 15
- @asin(expr)
- Returns the arc sin in the range -pi/2 to pi/2
-
- .TP 15
- @acos(expr)
- Returns the arc cosine in the range 0 to pi.
- }i(<|J
- .TP 15
- @atan(expr)
- Returns the arc tangent of <expr> in the range -pi/2 to pi/2.
-
- .TP 15
- @dtr(expr)
- Converts <expr> in degrees to radians.
-
- .TP 15
- @rtd(expr)
- Converts <expr> in radians to degrees.
-
- .TP 15
- pi
- A constant quite close to pi.
-
- .TP 15
- @gamma(expr1)
- Returns the natural log of the gamma function.
-
- .SH SEE ALSO
- bc(1), dc(1), crypt(1)
-
- .SH BUGS
-
- Expression reevaluation is done in the same top-to-bottom, left-to-right
- manner as is done in other spread sheet calculators. This is silly. A
- proper following of the dependency graph with (perhaps) recourse to
- relaxation should be implemented.
-
- At most 200 rows and 40 columns.
- \SHAR\EOF\
- else
- echo "will not over write ./sc.doc"
- fi
- if [ `wc -c ./sc.doc | awk '{printf $1}'` -ne 13353 ]
- then
- echo `wc -c ./sc.doc | awk '{print "Got " $1 ", Expected " 13353}'`
- fi
- if `test ! -s ./sc.h`
- then
- echo "writing ./sc.h"
- cat > ./sc.h << '\SHAR\EOF\'
- /* 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
-
- typedef struct range_s {
- struct ent *left, *right;
- } RANGE_S;
-
- /*
- * If you want to save room, make row and col below into unsigned
- * chars and make sure MAXROWS and MAXCOLS above are both less
- * than 256. (128 if your compiler doesn't support unsigned char).
- */
-
- struct ent {
- double v;
- char *label;
- struct enode *expr;
- short flags;
- short row, col;
- struct ent *next;
- };
-
- struct range {
- struct ent *r_left, *r_right;
- char *r_name;
- struct range *r_next, *r_prev;
- };
-
- 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
- #define RND 19
-
- /* 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)
-
- extern struct ent *tbl[MAXROWS][MAXCOLS];
-
- extern int strow, stcol;
- extern int currow, curcol;
- extern int savedrow, savedcol;
- extern int FullUpdate;
- extern int maxrow, maxcol;
- extern int fwidth[MAXCOLS];
- extern int precision[MAXCOLS];
- extern char col_hidden[MAXCOLS];
- extern char row_hidden[MAXROWS];
- extern char line[1000];
- extern int linelim;
- extern int changed;
- extern struct ent *to_fix;
- extern struct enode *new();
- extern struct enode *new_const();
- extern struct enode *new_var();
- extern struct ent *lookat();
- extern struct enode *copye();
- extern char *coltoa();
- extern FILE *openout();
- extern struct range *find_range();
- extern char *v_name();
- extern int modflg;
- extern int Crypt;
-
- #if BSD42 || SYSIII
- #define cbreak crmode
- #define nocbreak nocrmode
- #endif
-
- \SHAR\EOF\
- else
- echo "will not over write ./sc.h"
- fi
- if [ `wc -c ./sc.h | awk '{printf $1}'` -ne 2228 ]
- then
- echo `wc -c ./sc.h | awk '{print "Got " $1 ", Expected " 2228}'`
- fi
- if `test ! -s ./sc.c`
- then
- echo "writing ./sc.c"
- cat > ./sc.c << '\SHAR\EOF\'
- /* SC A Spreadsheet Calculator
- * Main driver
- *
- * original by James Gosling, September 1982
- * modifications by Mark Weiser and Bruce Israel,
- * University of Maryland
- *
- * More mods Robert Bond, 12/86
- *
- */
-
-
- #include <signal.h>
- #include <curses.h>
-
- #ifdef BSD42
- #include <strings.h>
- #else
- #ifndef SYSIII
- #include <string.h>
- #endif
- #endif
-
- #include <stdio.h>
- #include "sc.h"
-
- char *xmalloc();
-
- /* 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 */
-
- /* Globals defined in sc.h */
-
- 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 col_hidden[MAXCOLS];
- char row_hidden[MAXROWS];
- char line[1000];
- int changed;
- struct ent *to_fix;
- int modflg;
-
- char curfile[1024];
-
- int linelim = -1;
- int showme = 1; /* 1 to display the current cell in the top line */
- char *rev = "$Revision: 4.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 *) xmalloc ((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;
- xfree((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 (row_hidden[currow]) /* You can't hide the last row or col */
- currow++;
- while (col_hidden[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 (col_hidden[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 (row_hidden[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 (row_hidden[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 (col_hidden[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 (row_hidden[row])
- continue;
- for (p = &tbl[row][col = stcol]; col <= maxcol; col++, p++) {
- if (col_hidden[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 (!row_hidden[row])
- lastmy += 1;
- lastmx = RESCOL;
- for (col = stcol; col <= curcol; col++)
- if (!col_hidden[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;
- char *pname;
-
- pname = argv[0];
-
- {
- register i;
- for (i = 0; i < MAXCOLS; i++) {
- fwidth[i] = DEFWIDTH;
- precision[i] = DEFPREC;
- }
- }
- curfile[0]=0;
- running = 1;
-
- signals();
- initscr ();
- goraw();
- initkbd();
- if (argc > 1 && !strcmp(argv[1], "-x")) {
- Crypt++;
- argv++;
- argc--;
- }
- if (argc > 1) {
- strcpy(curfile,argv[1]);
- readfile (argv[1],0);
- }
- modflg = 0;
- strcpy(revmsg, pname);
- for (revi=rev; *revi++ != ':';);
- strcat(revmsg, revi);
- revi = revmsg+strlen(revmsg);
- *--revi = 0;
- strcat(revmsg,"Type '?' for help.");
- error (revmsg);
- #ifdef VENIX
- setbuf (stdin, NULL);
- #endif
- FullUpdate++;
- while (inloop) { running = 1;
- while (running) {
- nedistate = -1;
- narg = 1;
- if (edistate < 0 && linelim < 0 && (changed || FullUpdate))
- EvalAll (), changed = 0;
- update();
- #ifndef SYSV3
- refresh(); /* 5.3 does a refresh in getch */
- #endif
- c = nmgetch();
- move (1, 0);
- clrtoeol ();
- fflush (stdout);
- seenerr = 0;
- if ((c < ' ') || ( c == 0177 ))
- switch (c) {
- #if defined(BSD42) || defined (BSD43)
- case ctl (z):
- deraw();
- #ifndef V7
- kill(getpid(),SIGTSTP);
- #endif
-
- /* the pc stops here */
-
- goraw();
- 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(col_hidden[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(col_hidden[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 (row_hidden[currow] && (currow < MAXROWS - 1))
- currow++;
- }
- break;
- case ctl (p):
- while (--arg>=0) {
- if (currow)
- currow--;
- else
- error ("At row zero");
- while (row_hidden[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", v_name(currow, curcol));
- 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
- #ifdef QUICK
- if ('0' <= c && c <= '9' && edistate >= 0) {
- #else
- if ('0' <= c && c <= '9' && (linelim < 0 || edistate >= 0)) {
- #endif /* QUICK */
- 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 */
- #ifdef QUICK
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case '-':
- sprintf(line,"let %s = %c",
- v_name(currow, curcol), c);
- linelim = strlen (line);
- break;
- #endif /* QUICK */
- case '=':
- sprintf(line,"let %s = ",v_name(currow, curcol));
- linelim = strlen (line);
- break;
- case '/':
- error("c:copy x:erase f:fill d:define u:undefine s:show");
- refresh();
- switch (nmgetch()) {
- case 'c':
- sprintf(line,"copy [to] %s [from range] ",
- v_name(currow, curcol));
- linelim = strlen(line);
- break;
- case 'x':
- sprintf(line,"erase [range] ");
- linelim = strlen(line);
- break;
- case 'f':
- sprintf(line,"fill [range start inc] ");
- linelim = strlen(line);
- break;
- case 'd':
- sprintf(line,"define [string range] \"");
- linelim = strlen(line);
- modflg++;
- break;
- case 'u':
- sprintf(line,"undefine [range] ");
- linelim = strlen(line);
- modflg++;
- break;
- case 's':
- {
- FILE *f;
- int pid;
- f = openout("| sort | less", &pid);
- if (!f) {
- error("Cant open pipe to sort");
- break;
- }
- list_range(f);
- closeout(f, pid);
- 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 = \"",
- v_name(currow, curcol));
- linelim = strlen (line);
- break;
- case '<':
- sprintf (line, "leftstring %s = \"",
- v_name(currow, curcol));
- linelim = strlen (line);
- break;
- case '>':
- sprintf (line, "rightstring %s = \"",
- v_name(currow, curcol));
- linelim = strlen (line);
- break;
- case 'e':
- editv (currow, curcol);
- break;
- case 'E':
- edits (currow, curcol);
- break;
- case 'f':
- if (arg == 1)
- sprintf (line, "format [for column] %s ",
- coltoa(curcol));
- else {
- sprintf(line, "format [for columns] %s:",
- coltoa(curcol));
- sprintf(line+strlen(line), "%s ",
- coltoa(curcol+arg-1));
- }
- 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 path 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(col_hidden[curcol] && curcol)
- curcol--;
- }
- break;
- case 'j':
- while (--arg>=0) {
- if (currow < MAXROWS - 1)
- currow++;
- else
- error ("The table can't be any longer");
- while (row_hidden[currow]&&(currow<MAXROWS-1))
- currow++;
- }
- break;
- case 'k':
- while (--arg>=0) {
- if (currow)
- currow--;
- else
- error ("At row zero");
- while (row_hidden[currow] && currow)
- currow--;
- }
- break;
- case 'l':
- while (--arg>=0) {
- if (curcol < MAXCOLS - 1)
- curcol++;
- else
- error ("The table can't be any wider");
- while(col_hidden[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 = (char *)
- xmalloc((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) */
- deraw();
- resetkbd();
- endwin ();
- }
-
- goraw()
- {
- clear();
- cbreak();
- nonl();
- noecho ();
- FullUpdate++;
- }
-
- deraw()
- {
- move (LINES - 1, 0);
- clrtoeol();
- refresh();
- nocbreak();
- nl();
- echo();
- }
-
- 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()
- {
- deraw();
- 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];
- int pid;
-
- if (Crypt) {
- return (cwritefile(fname));
- }
-
- if (*fname == 0) fname = &curfile[0];
-
- strcpy(save,fname);
-
- f = openout(fname, &pid);
- 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]);
- write_range(f);
- 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);
- }
- }
- }
-
- closeout(f, pid);
-
- if (!pid) {
- 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 (Crypt) {
- creadfile(fname, eraseflg);
- return;
- }
-
- 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) xfree ((char *)((*p) -> label));
- xfree ((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\
- else
- echo "will not over write ./sc.c"
- fi
- if [ `wc -c ./sc.c | awk '{printf $1}'` -ne 20711 ]
- then
- echo `wc -c ./sc.c | awk '{print "Got " $1 ", Expected " 20711}'`
- fi
- if `test ! -s ./lex.c`
- then
- echo "writing ./lex.c"
- cat > ./lex.c << '\SHAR\EOF\'
- /* 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 *xmalloc();
-
- 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;
- tokenl = 0;
- /*
- * This picks up either 1 or 2 alpha characters (a column) or
- * tokens with at least three leading alphas and '_' or digits
- * (a function or token or command or a range name)
- */
- while (isalpha(*p) || ((*p == '_') || isdigit(*p)) && (tokenl > 2)) {
- p++;
- tokenl++;
- }
- if (tokenl <= 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;
- 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) {
- struct range *r;
- if (r = find_range(tokenst, tokenl,
- (struct ent *)0, (struct ent *)0)) {
- yylval.rval.left = r->r_left;
- yylval.rval.right = r->r_right;
- ret = RANGE;
- } else {
- linelim = p-line;
- yyerror ("Unintelligible word");
- }
- }
- }
- } else if ((*p == '.') || isdigit(*p)) {
- double v = 0;
- long temp;
- char *nstart = p;
- if (*p != '.') {
- do v = v*10 + (double)(*p-'0');
- while (isdigit(*++p));
- }
- if (*p=='.' || *p == 'e' || *p == 'E') {
- ret = FNUMBER;
- p = strtof(nstart, &yylval.fval);
- } else {
- temp = (int)v;
- if((double)temp != 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 = xmalloc((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
-
- #if defined(SYSV2) || defined(SYSV3)
-
- 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 /* SYSV2 || SYSV3 */
-
- #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 (" /u undefine range /s show ranges /d define range");
- 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(range) @avg(range) @prod(range)");
- debug (" @func(e) - lots of other math functions");
- }
- \SHAR\EOF\
- else
- echo "will not over write ./lex.c"
- fi
- if [ `wc -c ./lex.c | awk '{printf $1}'` -ne 9916 ]
- then
- echo `wc -c ./lex.c | awk '{print "Got " $1 ", Expected " 9916}'`
- fi
- echo "Finished archive 2 of 3"
- # if you want to concatenate archives, remove anything after this line
- exit
-
- --
-
- Rich $alz
- Cronus Project, BBN Labs rsalz@bbn.com
- Moderator, comp.sources.unix sources@uunet.uu.net
-