buhrt@cs.indiana.edu (Jeff Buhrt) (06/06/91)
Submitted-by: Jeff Buhrt <prslnk!buhrt@cs.indiana.edu> Posting-number: Volume 20, Issue 40 Archive-name: sc/part06 #! /bin/sh # into a shell via "sh file" or similar. To overwrite existing files, # type "sh file -c". # The tool that generated this appeared in the comp.sources.unix newsgroup; # send mail to comp-sources-unix@uunet.uu.net if you want that tool. # Contents: Makefile TODO gram.y lex.c vi.c # Wrapped by kent@sparky on Wed Jun 5 09:22:20 1991 PATH=/bin:/usr/bin:/usr/ucb ; export PATH echo If this archive is complete, you will see the following message: echo ' "shar: End of archive 6 (of 7)."' if test -f 'Makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Makefile'\" else echo shar: Extracting \"'Makefile'\" \(10303 characters\) sed "s/^X//" >'Makefile' <<'END_OF_FILE' X# Makefile $Revision: 6.16 $ X# X# 1) Select the proper EXDIR (path), MANDIR, MANEXT, LIBDIR, SIGVOID, X# RE_COMP/REGCMP, and DFLT_PAGER. Most of the other things aren't X# normally changed (see the comments with each) X# 2) Select the proper machine/compiler/OS section of code X# 3) make install X# 4) If you have the command 'file' that uses /etc/magic add the line: X# 38 string Spreadsheet sc file X X X# Specify the name of the program. X# All documentation and installation keys on this value. X# Xname=sc XNAME=SC X X# This is where the install step puts it. X#EXDIR=/site/bin XEXDIR=/usr/local/bin X X# This is where the man page goes. X#MANDIR=/usr/local/src/man/man1 # reno X#MANEXT=1 # reno XMANDIR=/usr/man/manl XMANEXT=l X X# This is where the library file (tutorial) goes. X#LIBDIR=/usr/local/share/$(name) # reno XLIBDIR=/usr/local/lib/$(name) X X# Set SIMPLE for lex.c if you don't want arrow keys or lex.c blows up XSIMPLE= X#SIMPLE=-DSIMPLE X X# Set BROKENCURSES if your curses has the nl/nonl bug X# if it does and you don't set BROKENCURSES, the display will X# be staggered across the screen. Also try IDLOKBAD below. XBROKENCURSES= X#BROKENCURSES=-DBROKENCURSES X X# Set DOBACKUPS if you would like a backup copy of a source file on a save X#DOBACKUPS= XDOBACKUPS=-DDOBACKUPS X X# Set INTERNATIONAL if you need 8 bit characters. You should X# not set this if you are running 5.3.0. I think it is OK in 5.3.1. X#INTERNATIONAL=-DINTERNATIONAL XINTERNATIONAL= X X# Set SIGVOID if signal routines are type void. X# use: SIGVOID=-DSIGVOID for: X# System 5.3, SunOS 4.X, VMS, BSD4.4 (reno), and ANSI C Compliant systems X# use: SIGVOID= for: X# BSD systems (excluding reno, BSD4.4), and the UNIXPC 'cc' XSIGVOID=-DSIGVOID X#SIGVOID= X X# Set IEEE_MATH if you need setsticky() calls in your signal handlers X# X#IEEE_MATH=-DIEEE_MATH XIEEE_MATH= X X# Set RINT=-DRINT if you do not have rint() in math.h X# Set RINT= on/with (they have rint): X# SunOS 4.0.3c compiler X# BSD4.4 (reno) X#RINT= XRINT=-DRINT X X# Set RE_COMP if you have the re_comp/re_exec regular expression routines X# (most BSD based systems do). X#RE_COMP=-DRE_COMP XRE_COMP= X X# Set REGCMP if you have the regcmp/regex regular expression routines X# (most System V based systems do) XREGCMP=-DREGCMP X#REGCMP= X X# This is the name of a pager like "more". X# "pg" may be appropriate for SYSV. XDFLT_PAGER=-DDFLT_PAGER=\"less\" X#DFLT_PAGER=-DDFLT_PAGER=\"more\" # generic && reno X X# this is the name to save back ups in XSAVE=-DSAVENAME=\"$(NAME).SAVE\" X X# path to crypt XCRYPT=-DCRYPT_PATH=\"/bin/crypt\" X#CRYPT=CRYPT_PATH=\"/usr/local/bin/crypt\" X X# flags for lint XLINTFLAGS=-abchxv X X# *** SPECIAL NOTES *** X# For ULTRIX: define the BSD4.2 section and SIGVOID above X# tdw@cl.cam.ac.uk tested on Ultrix 3.1C-0 X# HP-UX 7.0: Do NOT use -O X# (known broken, try sc's boolean operators if you wish) X# X# **** SYSV curses bugs... **** X# Try setting IDLOKBAD to fix (with an empty spreadsheet): X# a) Redrawing the bottom half of the screen when you X# move between row 9 <-> 10 X# b) the highlighted row labels being trash when you X# move between row 9 <-> 10 X# c) On an xterm on Esix Rev. D+ from eating lines X# -goto (or move) a few lines (or more) past the bottom X# of the screen, goto (or move) to the top line on the X# screen, move upward and the current line is deleted, the X# others move up even when they should not, check by X# noticing the rows become 2, 3, 40, 41, 42... (etc). X# Known systems/terminfos w/ curses problems: X# {Esix Rev. D+, AT&T SysV3.2.1}:at386-m,xterm, HP-UX7.0:(not sure) XIDLOKBAD=-DIDLOKBAD X#IDLOKBAD= X X# IF you have problems w/ your yacc and don't have, say, bison... X# look just below for '### YACC PROBLEMS ###' and reverse the define to X# use the included, pre-yacc'd copy. First try below. X#YACC=yacc XYACC=bison -y X X#### SYSTEM DEFINES #### X X# Use this for system AIX V3.1 X#CFLAGS= -O -DSYSV2 -DCHTYPE=int -DNLS X#LDFLAGS= X#LIB=-lm -lPW -lcurses X X# Use this for system V.2 X#CFLAGS= -O -DSYSV2 X#LDFLAGS= X#LIB=-lm -lPW -lcurses X# with gcc on a Sequent also use: X#CC=att gcc X#CFLAGS= -DSYSV2 -g -pipe -traditional X X# Use this for system V.3 XCFLAGS= -DSYSV3 -O XLDFLAGS= -s XLIB=-lm -lcurses -lPW X# with gcc also use: X#CC=gcc X#CFLAGS= -DSYSV3 -O -pipe XYACC=bison -y X X# Use this for system V.4 X#CFLAGS= -DSYSV4 -DSYSV3 -O X#LDFLAGS= -s X#LIB=-lm -lcurses -lgen X# with gcc also use: X#CC=gcc X#CFLAGS= -DSYSV3 -O -pipe X X# Microport X#CFLAGS= -DSYSV2 -O -DUPORT -Ml X#LDFLAGS=-Ml X#LIB=-lm -lcurses -lPW X X# Use this for BSD 4.2 X#CFLAGS= -O -DBSD42 X#LDFLAGS= X#LIB=-lm -lcurses -ltermcap X X# Use this for Sequent boxes X#CC=atscc X#CFLAGS=-O -DBSD42 X#LDFLAGS= X#LIB=-lm -lcurses -ltermcap X#PSCLIB=-lseq X# with gcc also use: X#CC=gcc X#CFLAGS= -O -DBSD42 -pipe X X# Use this for BSD 4.3 X#CFLAGS= -O -DBSD43 X#LDFLAGS= X#LIB=-lm -lcurses -ltermcap X X# Use this for SunOS 4.X if you have the System V package installed. X# This will link with the System V curses which is preferable to the X# BSD curses (especially helps scrolling on slow (9600bps or less) X# serial lines). X# X# Be sure to define SIGVOID and RE_COMP above. X# X#CC=/usr/5bin/cc X#CFLAGS= -O -DSYSV3 X#LDFLAGS= X#LIB=-lm -lcurses X X# Use this for system III (XENIX) X#CFLAGS= -O -DSYSIII X#LDFLAGS= -i X#LIB=-lm -lcurses -ltermcap X X# Use this for XENIX Version 2.3 X#CFLAGS= -O -SSYSIII -DXENIX2_3 X#LDFLAGS= -i X#LIB=-lm -lcurses -ltermcap X X# Use this for VENIX X#CFLAGS= -DVENIX -DBSD42 -DV7 X#LDFLAGS= -z -i X#LIB=-lm -lcurses -ltermcap X X# For SCO Unix V rel. 3.2.0 X# -compile using rcc, cc does not cope with gram.c X# -edit /usr/include/curses.h, rcc does not understand #error X# -link: make CC=cc, rcc's loader gets unresolved __cclass, __range X# (rather strange,?) X#CC=rcc X#CC=cc X#CC=gcc -fstrength-reduce X#SIGVOID=-DSIGVOID X#CFLAGS= -O -DSYSV3 X#LDFLAGS= X#LIB=-lm -lcurses -ltinfo -lPW X#YACC=yacc -Sm10000 X X# Use this for SCO Unix 3.2.2 and ODT 1.1 X#CC=cc X#CFLAGS= -O -DSYSV3 X#LDFLAGS= X#LIB=-lm -lcurses -lPW -lmalloc -lc_s X#YACC=yacc -Sm10000 X X# All of the source files XSRC=Makefile cmds.c crypt.c eres.sed format.c gram.y help.c interp.c \ X lex.c psc.c range.c sc.c sc.h screen.c sres.sed version.c \ X vi.c vmtbl.c xmalloc.c X X# The objects XOBJS=cmds.o crypt.o format.o gram.o help.o interp.o lex.o range.o sc.o \ X screen.o version.o vi.o vmtbl.o xmalloc.o X X# The documents in the Archive XDOCS=README CHANGES sc.doc psc.doc tutorial.sc VMS_NOTES X Xall: $(name) p$(name) $(name)qref X X$(name):$(PAR) $(OBJS) X $(CC) ${LDFLAGS} ${OBJS} ${LIB} -o $(name) X X### YACC PROBLEMS ### X# IF you have problems w/ your yacc and don't have, say, bison... X# for systems that don't allow you to increase the number of terminals X# (mostly AT&T) (this will include a Berkeley yacc built gram.c and X# y.tab.h) use: X#gram.c: mygram.c X# cp mygram.c gram.c X#y.tab.h: X# cp myy.tab.h y.tab.h X# X# Otherwise (most systems) Xgram.c: gram.y X $(YACC) -d gram.y; mv y.tab.c gram.c Xy.tab.h: gram.y X X Xp$(name): psc.c pvmtbl.o pxmalloc.o X $(CC) ${LDFLAGS} -o p$(name) psc.c pvmtbl.o pxmalloc.o ${PSCLIB} X Xqhelp.c: help.c X -rm -f qhelp.c X ln help.c qhelp.c X X$(name)qref: qhelp.c X $(CC) $(LDFLAGS) -DQREF -DSCNAME=\"$(name)\" -o $(name)qref qhelp.c X Xpvmtbl.c: vmtbl.c X -rm -f pvmtbl.c X ln vmtbl.c pvmtbl.c X Xpvmtbl.o: sc.h pvmtbl.c X $(CC) ${CFLAGS} -c -DPSC pvmtbl.c X Xpxmalloc.c: xmalloc.c X -rm -f pxmalloc.c X ln xmalloc.c pxmalloc.c X Xpxmalloc.o: sc.h pxmalloc.c X $(CC) ${CFLAGS} -c -DPSC pxmalloc.c X Xlex.o: sc.h y.tab.h gram.o lex.c X $(CC) ${CFLAGS} ${SIMPLE} ${IEEE_MATH} ${SIGVOID} -c lex.c X Xsc.o: sc.h sc.c X $(CC) ${CFLAGS} ${DFLT_PAGER} ${SIGVOID} ${SAVE} -c sc.c X Xscreen.o: sc.h screen.c X $(CC) ${CFLAGS} ${BROKENCURSES} ${INTERNATIONAL} ${SIGVOID} -c screen.c X Xinterp.o: interp.c sc.h X $(CC) ${CFLAGS} ${IEEE_MATH} ${SIGVOID} ${RINT} ${RE_COMP} ${REGCMP} -c interp.c X Xgram.o: sc.h y.tab.h X Xcmds.o: cmds.c sc.h X $(CC) ${CFLAGS} ${DOBACKUPS} -c cmds.c X Xcrypt.o: crypt.c sc.h X $(CC) ${CFLAGS} ${CRYPT} ${DOBACKUPS} -c crypt.c X Xrange.o: range.c sc.h X Xhelp.o: help.c sc.h X Xformat.o: format.c X Xvi.o: vi.c sc.h X Xgram.o: sc.h y.tab.h gram.c X $(CC) ${CFLAGS} -c gram.c X sed<gram.y >experres.h -f eres.sed;sed < gram.y > statres.h -f sres.sed X Xclean: X rm -f *.o *res.h y.tab.h $(name) p$(name) debug core gram.c $(name).1 \ X $(name).man p$(name).man p$(name).1 y.output $(name)qref X Xshar: ${SRC} ${DOCS} X shar -c -m 64000 -f shar ${DOCS} ${SRC} X Xsshar: ${SRC} X shar -c -m 1000000 -f shar ${SRC} X Xlint: sc.h sc.c lex.c gram.c interp.c cmds.c crypt.c range.c help.c \ X vi.c version.c xmalloc.c format.c vmtbl.c X lint ${LINTFLAGS} ${CFLAGS} ${SIMPLE} sc.c lex.c gram.c interp.c \ X cmds.c crypt.c range.c help.c vi.c version.c xmalloc.c format.c \ X vmtbl.c -lcurses -lm X make lintqref X Xlintqref: help.c X lint ${LINTFLAGS} ${CFLAGS} ${SIMPLE} -DQREF help.c X Xlintpsc: psc.c vmtbl.c X lint ${LINTFLAGS} ${CFLAGS} ${SIMPLE} -DPSC psc.c vmtbl.c X Xinspect: sc.h sc.c lex.c gram.c interp.c cmds.c crypt.c X /bruces/ianj/bin/i386/inspect -abv -t 8 sc.c lex.c gram.c interp.c \ X cmds.c crypt.c range.c xmalloc.c help.c vi.c X Xprint: sc.h gram.y sc.c lex.c interp.c cmds.c crypt.c X prc sc.h gram.y sc.c lex.c interp.c cmds.c crypt.c | lpr X X$(name).1: sc.doc X sed -e s/pname/$(name)/g -e s/PNAME/$(NAME)/g \ X -e s%#LIBDIR#%$(LIBDIR)%g sc.doc > $(name).1 X X$(name).man: $(name).1 X nroff -man $(name).1 > $(name).man X Xlaser: $(name).1 X itpf -x -Pim2 -man $(name).1 X Xp$(name).1: psc.doc X sed -e s/pname/$(name)/g -e s/PNAME/$(NAME)/g psc.doc > p$(name).1 X Xp$(name).man: p$(name).1 X nroff -man p$(name).1 > p$(name).man X Xinstall: $(EXDIR)/$(name) $(EXDIR)/$(name)qref $(EXDIR)/p$(name) \ X $(LIBDIR)/tutorial $(MANDIR)/$(name).$(MANEXT) X X$(EXDIR)/$(name): $(name) X cp $(name) $(EXDIR) X strip $(EXDIR)/$(name) X X$(EXDIR)/$(name)qref: $(name)qref X cp $(name)qref $(EXDIR) X strip $(EXDIR)/$(name)qref X X$(EXDIR)/p$(name): p$(name) X cp p$(name) $(EXDIR) X strip $(EXDIR)/p$(name) X X$(LIBDIR)/tutorial: tutorial.sc $(LIBDIR) X cp tutorial.sc $(LIBDIR)/tutorial.$(name) X X$(LIBDIR): X mkdir $(LIBDIR) X X$(MANDIR)/$(name).$(MANEXT): $(name).1 X cp $(name).1 $(MANDIR)/$(name).$(MANEXT) X Xdiffs: ${SRC} X for i in ${SRC} ${DOCS} ;\ X do \ X rcsdiff -c -r6.11 $$i ;\ X done X X# THA 10/14/90 Added code to make a patchfile Xpatchfile: ${SRC} ${DOCS} X rm -f patchfile X for i in ${SRC} ${DOCS} ;\ X do \ X diffc $$i /users/toma/sc/sc6.12/$$i >> patchfile ;\ X done END_OF_FILE if test 10303 -ne `wc -c <'Makefile'`; then echo shar: \"'Makefile'\" unpacked with wrong size! fi # end of 'Makefile' fi if test -f 'TODO' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'TODO'\" else echo shar: Extracting \"'TODO'\" \(1297 characters\) sed "s/^X//" >'TODO' <<'END_OF_FILE' X Xtodo: X1) autobackup of things typed in. X idea: each cell change output to a stdio open file X in the save format, fflush() every so often... X (diffs w/r to the original file) X2) lock/freeze (glue down) a section of the screen (the rest of the screen X scrolls but a row/column/block stays fixed on the screen) X3) (seems ok, but check) FIX the insert/delete row functions. X a) column of equations (EX: E50 = E49+D50) X b) insert a few rows, look at the equations below the insert point X c) delete the inserted rows X d) The equations should now be the same as in (a), but they are not... X4) make sure ISVALID should <not> be used in place of checkbounds X in interp.c X5) hide range X6) block moving into range X7) chain cells w/ equations into a linked list or dependency tree X -have a top level eval, eval and UPDATE all lower nodes X8) an option to go into a ^R like <mode> X ++data entry fields (highlight entry cells).... X ++only allow entry in these cells.... X10) don't redraw the whole screen all the time X (only cells that change, (in addition to what is in 'fixed #9')) X11) add uemacs keybinding stuff X12) add uemacs macro language X13) add uemacs command completion X14) insertrow should be openrow w/ a count arg (limits looping) X15) on a Get if the buffer hasn't been written, ask to overwrite END_OF_FILE if test 1297 -ne `wc -c <'TODO'`; then echo shar: \"'TODO'\" unpacked with wrong size! fi # end of 'TODO' fi if test -f 'gram.y' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'gram.y'\" else echo shar: Extracting \"'gram.y'\" \(13277 characters\) sed "s/^X//" >'gram.y' <<'END_OF_FILE' X/* SC A Spreadsheet Calculator X * Command and expression parser X * X * original by James Gosling, September 1982 X * modified by Mark Weiser and Bruce Israel, X * University of Maryland X * X * more mods Robert Bond 12/86 X * X * More mods by Alan Silverstein, 3/88, see list of changes. X * X * $Revision: 6.16 $ X */ X X X X%{ X#include <curses.h> X#include "sc.h" X X#define ENULL (struct enode *)0 X Xchar *strcpy(); X%} X X%union { X int ival; X double fval; X struct ent_ptr ent; X struct enode *enode; X char *sval; X struct range_s rval; X} X X%type <ent> var X%type <fval> num X%type <rval> range X%type <rval> var_or_range X%type <sval> strarg X%type <enode> e term expr_list X%token <sval> STRING X%token <ival> NUMBER X%token <fval> FNUMBER X%token <rval> RANGE X%token <rval> VAR X%token <sval> WORD X%token <ival> COL X%token S_FORMAT X%token S_FMT X%token S_LABEL X%token S_LEFTSTRING X%token S_RIGHTSTRING X%token S_GET X%token S_PUT X%token S_MERGE X%token S_LET X%token S_WRITE X%token S_TBL X%token S_COPY X%token S_SHOW X%token S_ERASE X%token S_FILL X%token S_GOTO X%token S_DEFINE X%token S_UNDEFINE X%token S_VALUE X%token S_MDIR X%token S_HIDE X%token S_SET X X%token K_ERROR X%token K_INVALID X%token K_FIXED X%token K_SUM X%token K_PROD X%token K_AVG X%token K_STDDEV X%token K_COUNT X%token K_ABS X%token K_ACOS X%token K_ASIN X%token K_ATAN X%token K_ATAN2 X%token K_CEIL X%token K_COS X%token K_EXP X%token K_FABS X%token K_FLOOR X%token K_HYPOT X%token K_LN X%token K_LOG X%token K_PI X%token K_POW X%token K_SIN X%token K_SQRT X%token K_TAN X%token K_DTR X%token K_RTD X%token K_MAX X%token K_MIN X%token K_RND X%token K_ROUND X%token K_IF X X%token K_PV X%token K_FV X%token K_PMT X X%token K_HOUR X%token K_MINUTE X%token K_SECOND X%token K_MONTH X%token K_DAY X%token K_YEAR X%token K_NOW X%token K_DATE X%token K_DTS X%token K_TTS X%token K_FMT X%token K_SUBSTR X%token K_STON X%token K_EQS X%token K_EXT X%token K_NVAL X%token K_SVAL X%token K_LOOKUP X%token K_HLOOKUP X%token K_VLOOKUP X%token K_INDEX X%token K_STINDEX X%token K_AUTO X%token K_AUTOCALC X%token K_BYROWS X%token K_BYCOLS X%token K_ITERATIONS X%token K_NUMERIC X%token K_PRESCALE X%token K_EXTFUN X%token K_CELLCUR X%token K_TOPROW X%token K_TBLSTYLE X%token K_TBL X%token K_LATEX X%token K_SLATEX X%token K_TEX X%token K_RNDINFINITY X%token K_MYROW X%token K_MYCOL X%token K_COLTOA X X%left '?' ':' X%left '|' X%left '&' X%nonassoc '<' '=' '>' '!' X%left '+' '-' '#' X%left '*' '/' '%' X%left '^' X X%% Xcommand: S_LET var_or_range '=' e X { let($2.left.vp, $4); } X | S_LABEL var_or_range '=' e X { slet($2.left.vp, $4, 0); } X | S_LEFTSTRING var_or_range '=' e X { slet($2.left.vp, $4, -1); } X | S_RIGHTSTRING var_or_range '=' e X { slet($2.left.vp, $4, 1); } X | S_FORMAT COL ':' COL NUMBER NUMBER NUMBER X { doformat($2,$4,$5,$6,$7); } X | S_FORMAT COL NUMBER NUMBER NUMBER X { doformat($2,$2,$3,$4,$5); } X | S_FORMAT COL ':' COL NUMBER NUMBER X { doformat($2,$4,$5,$6, 0); } X | S_FORMAT COL NUMBER NUMBER X { doformat($2,$2,$3,$4, 0); } X | S_GET strarg { /* This tmp hack is because readfile X * recurses back through yyparse. */ X char *tmp; X tmp = $2; X readfile (tmp, 1); X xfree(tmp); X } X | S_MERGE strarg { X char *tmp; X tmp = $2; X readfile (tmp, 0); X xfree(tmp); X } X | S_MDIR strarg X { if (mdir) xfree(mdir); mdir = $2; } X | S_PUT strarg range X { (void) writefile($2, ($3.left.vp)->row, X ($3.left.vp)->col, ($3.right.vp)->row, X ($3.right.vp)->col); X xfree($2); } X | S_PUT strarg X { (void) writefile ($2, 0, 0, maxrow, maxcol); X xfree($2); } X | S_WRITE strarg range { (void) printfile($2, ($3.left.vp)->row, X ($3.left.vp)->col, ($3.right.vp)->row, X ($3.right.vp)->col); X xfree($2); } X | S_WRITE strarg { (void) printfile ($2, 0, 0, maxrow, maxcol); X xfree($2); } X | S_TBL strarg range { (void) tblprintfile($2, ($3.left.vp)->row, X ($3.left.vp)->col, ($3.right.vp)->row, X ($3.right.vp)->col); X xfree($2); } X | S_TBL strarg { (void)tblprintfile ($2, 0, 0, maxrow, maxcol); X xfree($2); } X | S_SHOW COL ':' COL X { showcol( $2, $4); } X | S_SHOW NUMBER ':' NUMBER X { showrow( $2, $4); } X | S_HIDE COL X { hide_col( $2 ); } X | S_HIDE NUMBER X { hide_row( $2 ); } X | S_COPY range var_or_range X { copy($2.left.vp,$2.right.vp, X $3.left.vp,$3.right.vp); } X | S_ERASE X { eraser(lookat(showsr, showsc), X lookat(currow, curcol)); } X | S_ERASE var_or_range X { eraser($2.left.vp, $2.right.vp); } X | S_VALUE { valueize_area(showsr, showsc, currow, curcol); X modflg++; } X | S_VALUE var_or_range { valueize_area(($2.left.vp)->row, X ($2.left.vp)->col, X ($2.right.vp)->row, X ($2.right.vp)->col); modflg++; } X | S_FILL num num { fill(lookat(showsr, showsc), X lookat(currow, curcol), $2, $3); } X | S_FILL var_or_range num num X { fill($2.left.vp, $2.right.vp, $3, $4); } X | S_FMT var_or_range STRING X { format_cell($2.left.vp, $2.right.vp, $3); } X | S_GOTO var_or_range {moveto($2.left.vp->row, $2.left.vp->col);} X | S_GOTO num { num_search($2, 0); } X | S_GOTO errlist X | S_GOTO STRING { str_search($2); } X | S_GOTO { go_last(); } X | S_DEFINE strarg { struct ent_ptr arg1, arg2; X arg1.vp = lookat(showsr, showsc); X arg1.vf = 0; X arg2.vp = lookat(currow, curcol); X arg2.vf = 0; X if (arg1.vp == arg2.vp) X add_range($2, arg2, arg2, 0); X else X add_range($2, arg1, arg2, 1); } X X | S_DEFINE strarg range { add_range($2, $3.left, $3.right, 1); } X | S_DEFINE strarg var { add_range($2, $3, $3, 0); } X | S_UNDEFINE var_or_range { del_range($2.left.vp, $2.right.vp); } X | S_SET setlist X | /* nothing */ X | error; X Xterm: var { $$ = new_var(O_VAR, $1); } X | K_FIXED term { $$ = new ('f', ENULL, $2); } X | '@' K_SUM '(' var_or_range ')' X { $$ = new_range(REDUCE | '+', $4); } X | '@' K_PROD '(' var_or_range ')' X { $$ = new_range (REDUCE | '*', $4); } X | '@' K_AVG '(' var_or_range ')' X { $$ = new_range (REDUCE | 'a', $4); } X | '@' K_STDDEV '(' var_or_range ')' X { $$ = new_range (REDUCE | 's', $4); } X | '@' K_COUNT '(' var_or_range ')' X { $$ = new_range (REDUCE | 'c', $4); } X | '@' K_MAX '(' var_or_range ')' X { $$ = new_range (REDUCE | MAX, $4); } X | '@' K_MAX '(' e ',' expr_list ')' X { $$ = new(LMAX, $6, $4); } X | '@' K_MIN '(' var_or_range ')' X { $$ = new_range (REDUCE | MIN, $4); } X | '@' K_MIN '(' e ',' expr_list ')' X { $$ = new(LMIN, $6, $4); } X | '@' K_ABS '(' e ')' { $$ = new(ABS, ENULL, $4); } X | '@' K_ACOS '(' e ')' { $$ = new(ACOS, ENULL, $4); } X | '@' K_ASIN '(' e ')' { $$ = new(ASIN, ENULL, $4); } X | '@' K_ATAN '(' e ')' { $$ = new(ATAN, ENULL, $4); } X | '@' K_ATAN2 '(' e ',' e ')' { $$ = new(ATAN2, $4, $6); } X | '@' K_CEIL '(' e ')' { $$ = new(CEIL, ENULL, $4); } X | '@' K_COS '(' e ')' { $$ = new(COS, ENULL, $4); } X | '@' K_EXP '(' e ')' { $$ = new(EXP, ENULL, $4); } X | '@' K_FABS '(' e ')' { $$ = new(FABS, ENULL, $4); } X | '@' K_FLOOR '(' e ')' { $$ = new(FLOOR, ENULL, $4); } X | '@' K_HYPOT '(' e ',' e ')' { $$ = new(HYPOT, $4, $6); } X | '@' K_LN '(' e ')' { $$ = new(LOG, ENULL, $4); } X | '@' K_LOG '(' e ')' { $$ = new(LOG10, ENULL, $4); } X | '@' K_POW '(' e ',' e ')' { $$ = new(POW, $4, $6); } X | '@' K_SIN '(' e ')' { $$ = new(SIN, ENULL, $4); } X | '@' K_SQRT '(' e ')' { $$ = new(SQRT, ENULL, $4); } X | '@' K_TAN '(' e ')' { $$ = new(TAN, ENULL, $4); } X | '@' K_DTR '(' e ')' { $$ = new(DTR, ENULL, $4); } X | '@' K_RTD '(' e ')' { $$ = new(RTD, ENULL, $4); } X | '@' K_RND '(' e ')' { $$ = new(RND, ENULL, $4); } X | '@' K_ROUND '(' e ',' e ')' { $$ = new(ROUND, $4, $6); } X | '@' K_IF '(' e ',' e ',' e ')' { $$ = new(IF, $4,new(',',$6,$8)); } X X | '@' K_PV '(' e ',' e ',' e ')' { $$ = new(PV, $4,new(':',$6,$8)); } X | '@' K_FV '(' e ',' e ',' e ')' { $$ = new(FV, $4,new(':',$6,$8)); } X | '@' K_PMT '(' e ',' e ',' e ')' { $$ = new(PMT, $4,new(':',$6,$8)); } X X | '@' K_HOUR '(' e ')' { $$ = new(HOUR,ENULL, $4); } X | '@' K_MINUTE '(' e ')' { $$ = new(MINUTE,ENULL, $4); } X | '@' K_SECOND '(' e ')' { $$ = new(SECOND,ENULL, $4); } X | '@' K_MONTH '(' e ')' { $$ = new(MONTH,ENULL,$4); } X | '@' K_DAY '(' e ')' { $$ = new(DAY, ENULL, $4); } X | '@' K_YEAR '(' e ')' { $$ = new(YEAR, ENULL, $4); } X | '@' K_NOW { $$ = new(NOW, ENULL, ENULL);} X | '@' K_DTS '(' e ',' e ',' e ')' X { $$ = new(DTS, $4, new(',', $6, $8));} X | '@' K_TTS '(' e ',' e ',' e ')' X { $$ = new(TTS, $4, new(',', $6, $8));} X | '@' K_STON '(' e ')' { $$ = new(STON, ENULL, $4); } X | '@' K_EQS '(' e ',' e ')' { $$ = new (EQS, $4, $6); } X | '@' K_DATE '(' e ')' { $$ = new(DATE, ENULL, $4); } X | '@' K_FMT '(' e ',' e ')' { $$ = new(FMT, $4, $6); } X | '@' K_INDEX '(' e ',' var_or_range ')' X { $$ = new(INDEX, $4, new_range(REDUCE | INDEX, $6)); } X | '@' K_LOOKUP '(' e ',' var_or_range ')' X { $$ = new(LOOKUP, $4, new_range(REDUCE | LOOKUP, $6)); } X | '@' K_HLOOKUP '(' e ',' var_or_range ',' e ')' X { $$ = new(HLOOKUP, new(',', $4, $8), X new_range(REDUCE | HLOOKUP, $6)); } X | '@' K_VLOOKUP '(' e ',' var_or_range ',' e ')' X { $$ = new(VLOOKUP, new(',', $4, $8), X new_range(REDUCE | VLOOKUP, $6)); } X | '@' K_STINDEX '(' e ',' var_or_range ')' X { $$ = new(STINDEX, $4, new_range(REDUCE | STINDEX, $6)); } X | '@' K_EXT '(' e ',' e ')' { $$ = new(EXT, $4, $6); } X | '@' K_NVAL '(' e ',' e ')' { $$ = new(NVAL, $4, $6); } X | '@' K_SVAL '(' e ',' e ')' { $$ = new(SVAL, $4, $6); } X | '@' K_SUBSTR '(' e ',' e ',' e ')' X { $$ = new(SUBSTR, $4, new(',', $6, $8)); } X | '(' e ')' { $$ = $2; } X | '+' term { $$ = $2; } X | '-' term { $$ = new ('m', ENULL, $2); } X | NUMBER { $$ = new_const(O_CONST, (double) $1); } X | FNUMBER { $$ = new_const(O_CONST, $1); } X | K_PI { $$ = new_const(O_CONST, (double)3.14159265358979323846); } X | STRING { $$ = new_str($1); } X | '~' term { $$ = new ('~', ENULL, $2); } X | '!' term { $$ = new ('~', ENULL, $2); } X | '@' K_MYROW { $$ = new(MYROW, ENULL, ENULL);} X | '@' K_MYCOL { $$ = new(MYCOL, ENULL, ENULL);} X | '@' K_COLTOA '(' e ')' { $$ = new(COLTOA, ENULL, $4);} X ; X X/* expressions */ Xe: e '+' e { $$ = new ('+', $1, $3); } X | e '-' e { $$ = new ('-', $1, $3); } X | e '*' e { $$ = new ('*', $1, $3); } X | e '/' e { $$ = new ('/', $1, $3); } X | e '%' e { $$ = new ('%', $1, $3); } X | e '^' e { $$ = new ('^', $1, $3); } X | term X | e '?' e ':' e { $$ = new ('?', $1, new(':', $3, $5)); } X | e '<' e { $$ = new ('<', $1, $3); } X | e '=' e { $$ = new ('=', $1, $3); } X | e '>' e { $$ = new ('>', $1, $3); } X | e '&' e { $$ = new ('&', $1, $3); } X | e '|' e { $$ = new ('|', $1, $3); } X | e '<' '=' e { $$ = new ('~', ENULL, new ('>', $1, $4)); } X | e '!' '=' e { $$ = new ('~', ENULL, new ('=', $1, $4)); } X | e '>' '=' e { $$ = new ('~', ENULL, new ('<', $1, $4)); } X | e '#' e { $$ = new ('#', $1, $3); } X ; X Xexpr_list: e { $$ = new(ELIST, ENULL, $1); } X | expr_list ',' e { $$ = new(ELIST, $1, $3); } X ; X Xrange: var ':' var { $$.left = $1; $$.right = $3; } X | RANGE { $$ = $1; } X ; X Xvar: COL NUMBER { $$.vp = lookat($2 , $1); $$.vf = 0; } X | '$' COL NUMBER { $$.vp = lookat($3 , $2); X $$.vf = FIX_COL; } X | COL '$' NUMBER { $$.vp = lookat($3 , $1); X $$.vf = FIX_ROW; } X | '$' COL '$' NUMBER { $$.vp = lookat($4 , $2); X $$.vf = FIX_ROW | FIX_COL; } X | VAR { $$ = $1.left; } X ; X Xvar_or_range: range { $$ = $1; } X | var { $$.left = $1; $$.right = $1; } X ; X Xnum: NUMBER { $$ = (double) $1; } X | FNUMBER { $$ = $1; } X | '-' num { $$ = -$2; } X | '+' num { $$ = $2; } X ; X Xstrarg: STRING { $$ = $1; } X | var { X char *s, *s1; X s1 = $1.vp->label; X if (!s1) X s1 = "NULL_STRING"; X s = xmalloc((unsigned)strlen(s1)+1); X (void) strcpy(s, s1); X $$ = s; X } X ; X X/* allows >=1 'setitem's to be listed in the same 'set' command */ Xsetlist : X | setlist setitem X ; X X/* things that you can 'set' */ Xsetitem : K_AUTO { setauto(1); } X | K_AUTOCALC { setauto(1); } X | '~' K_AUTO { setauto(0); } X | '~' K_AUTOCALC { setauto(0); } X | '!' K_AUTO { setauto(0); } X | '!' K_AUTOCALC { setauto(0); } X | K_BYCOLS { setorder(BYCOLS); } X | K_BYROWS { setorder(BYROWS); } X | K_NUMERIC { numeric = 1; } X | '!' K_NUMERIC { numeric = 0; } X | K_PRESCALE { prescale = 0.01; } X | '!' K_PRESCALE { prescale = 1.0; } X | K_EXTFUN { extfunc = 1; } X | '!' K_EXTFUN { extfunc = 0; } X | K_CELLCUR { showcell = 1; } X | '!' K_CELLCUR { showcell = 0; } X | K_TOPROW { showtop = 1; } X | '!' K_TOPROW { showtop = 0; } X | K_ITERATIONS '=' NUMBER { setiterations($3); } X | K_TBLSTYLE '=' NUMBER { tbl_style = $3; } X | K_TBLSTYLE '=' K_TBL { tbl_style = TBL; } X | K_TBLSTYLE '=' K_LATEX { tbl_style = LATEX; } X | K_TBLSTYLE '=' K_SLATEX { tbl_style = SLATEX; } X | K_TBLSTYLE '=' K_TEX { tbl_style = TEX; } X | K_RNDINFINITY { rndinfinity = 1; FullUpdate++; } X | '!' K_RNDINFINITY { rndinfinity = 0; FullUpdate++; } X ; X X/* types of errors, to 'goto' */ Xerrlist : K_ERROR { num_search((double)0, CELLERROR); } X | K_INVALID { num_search((double)0, CELLINVALID); } X ; END_OF_FILE if test 13277 -ne `wc -c <'gram.y'`; then echo shar: \"'gram.y'\" unpacked with wrong size! fi # end of 'gram.y' fi if test -f 'lex.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'lex.c'\" else echo shar: Extracting \"'lex.c'\" \(13772 characters\) sed "s/^X//" >'lex.c' <<'END_OF_FILE' X/* SC A Spreadsheet Calculator X * Lexical analyser X * X * original by James Gosling, September 1982 X * modifications by Mark Weiser and Bruce Israel, X * University of Maryland X * X * More mods Robert Bond, 12/86 X * More mods by Alan Silverstein, 3/88, see list of changes. X * $Revision: 6.16 $ X * X */ X X X#include <sys/types.h> X#ifdef BSD42 X#include <strings.h> X#else X#ifndef SYSIII X#include <string.h> X#endif X#endif X X#if defined(BSD42) || defined(BSD43) X#include <sys/ioctl.h> X#endif X X#ifdef IEEE_MATH X#include <ieeefp.h> X#endif /* IEEE_MATH */ X X#include <curses.h> X#include <signal.h> X#include <setjmp.h> X#include "sc.h" X#include <ctype.h> X X#ifdef VMS X#include "gram_tab.h" Xtypedef union { X int ival; X double fval; X struct ent *ent; X struct enode *enode; X char *sval; X struct range_s rval; X} YYSTYPE; Xextern YYSTYPE yylval; Xextern int VMS_read_raw; /*sigh*/ X#else /* VMS */ X#include "y.tab.h" X#endif /* VMS */ X Xchar *strtof(); X Xjmp_buf wakeup; Xjmp_buf fpe_buf; X X#ifdef SIGVOID Xvoid X#endif Xfpe_trap(signo) Xint signo; X{ X#if defined(i386) && !defined(M_XENIX) X asm(" fnclex"); X asm(" fwait"); X#else X#ifdef IEEE_MATH X (void)fpsetsticky((fp_except)0); /* Clear exception */ X#endif /* IEEE_MATH */ X#ifdef PC X _fpreset(); X#endif X#endif X longjmp(fpe_buf, 1); X} X Xstruct key { X char *key; X int val; X}; X Xstruct key experres[] = { X#include "experres.h" X 0, 0}; X Xstruct key statres[] = { X#include "statres.h" X 0, 0}; X Xint Xyylex () X{ X register char *p = line+linelim; X int ret; X while (isspace(*p)) p++; X if (*p == '\0') ret = -1; X else if (isalpha(*p)) { X char *tokenst = p; X register tokenl; X register struct key *tblp; X tokenl = 0; X /* X * This picks up either 1 or 2 alpha characters (a column) or X * tokens with at least three leading alphas and '_' or digits X * (a function or token or command or a range name) X */ X while (isalpha(*p) || ((*p == '_') || isdigit(*p)) && (tokenl > 2)) { X p++; X tokenl++; X } X if (tokenl <= 2) { /* a COL is 1 or 2 char alpha X (but not pi, ln, fv, pv, if -- this should be fixed!) */ X if (tokenl == 2 && tokenst[0] == 'p' && tokenst[1] == 'i') { X ret = K_PI; X } else if (tokenl == 2 && tokenst[0] == 'l' && tokenst[1] == 'n') { X ret = K_LN; X } else if (tokenl == 2 && tokenst[0] == 'f' && tokenst[1] == 'v') { X ret = K_FV; X } else if (tokenl == 2 && tokenst[0] == 'p' && tokenst[1] == 'v') { X ret = K_PV; X } else if (tokenl == 2 && tokenst[0] == 'i' && tokenst[1] == 'f') { X ret = K_IF; X X } else { X ret = COL; X yylval.ival = atocol (tokenst, tokenl); X } X } else { X ret = WORD; X for (tblp = linelim ? experres : statres; tblp->key; tblp++) X if (((tblp->key[0]^tokenst[0])&0137)==0 X && tblp->key[tokenl]==0) { X register i = 1; X while (i<tokenl && ((tokenst[i]^tblp->key[i])&0137)==0) X i++; X if (i>=tokenl) { X ret = tblp->val; X break; X } X } X if (ret==WORD) { X struct range *r; X if (r = find_range(tokenst, tokenl, X (struct ent *)0, (struct ent *)0)) { X yylval.rval.left = r->r_left; X yylval.rval.right = r->r_right; X if (r->r_is_range) X ret = RANGE; X else X ret = VAR; X } else { X linelim = p-line; X yyerror ("Unintelligible word"); X } X } X } X } else if ((*p == '.') || isdigit(*p)) { X#ifdef SIGVOID X void (*sig_save)(); X#else X int (*sig_save)(); X#endif X double v = 0.0; X int temp; X char *nstart = p; X X sig_save = signal(SIGFPE, fpe_trap); X if (setjmp(fpe_buf)) { X (void) signal(SIGFPE, sig_save); X yylval.fval = v; X error("Floating point exception\n"); X return FNUMBER; X } X X if (*p != '.') { X do v = v*10.0 + (double) ((unsigned) *p - '0'); X while (isdigit(*++p)); X } X if (*p=='.' || *p == 'e' || *p == 'E') { X ret = FNUMBER; X p = strtof(nstart, &yylval.fval); X } else { X /* A NUMBER must hold at least MAXROW and MAXCOL */ X /* This is consistent with a short row and col in struct ent */ X if (v > (double)32767 || v < (double)-32768) { X ret = FNUMBER; X yylval.fval = v; X } else { X temp = (int)v; X if((double)temp != v) { X ret = FNUMBER; X yylval.fval = v; X } else { X ret = NUMBER; X yylval.ival = temp; X } X } X } X (void) signal(SIGFPE, sig_save); X } else if (*p=='"') { X char *ptr; X ptr = p+1; X while(*ptr && *ptr++ != '"'); X ptr = xmalloc((unsigned)(ptr-p)); X yylval.sval = ptr; X p += 1; X while (*p && *p!='"') *ptr++ = *p++; X *ptr = 0; X if (*p) p += 1; X ret = STRING; X } else if (*p=='[') { X while (*p && *p!=']') p++; X if (*p) p++; X linelim = p-line; X return yylex(); X } else ret = *p++; X linelim = p-line; X return ret; X} X X X/* X * Given a token string starting with a symbolic column name and its valid X * length, convert column name ("A"-"Z" or "AA"-"ZZ") to a column number (0-N). X * Never mind if the column number is illegal (too high). The procedure's name X * and function are the inverse of coltoa(). X * X * Case-insensitivity is done crudely, by ignoring the 040 bit. X */ X Xint Xatocol (string, len) X char *string; X int len; X{ X register int col; X X col = (string [0] & 0137) - 'A'; X X if (len == 2) /* has second char */ X col = ((col + 1) * 26) + ((string [1] & 0137) - 'A'); X X return (col); X} X X X#ifdef SIMPLE X Xvoid Xinitkbd() X{} X Xvoid Xkbd_again() X{} X Xvoid Xresetkbd() X{} X X#ifndef VMS X Xint Xnmgetch() X{ X return (toascii(getchar())); X} X X#else /* VMS */ X Xint Xnmgetch() X/* X This is not perfect, it doesn't move the cursor when goraw changes X over to deraw, but it works well enough since the whole sc package X is incredibly stable (loop constantly positions cursor). X X Question, why didn't the VMS people just implement cbreak? X X NOTE: During testing it was discovered that the DEBUGGER and curses X and this method of reading would collide (the screen was not updated X when continuing from screen mode in the debugger). X*/ X{ X short c; X static int key_id=0; X int status; X#define VMScheck(a) {if (~(status = (a)) & 1) VMS_MSG (status);} X X if (VMS_read_raw) { X VMScheck(smg$read_keystroke (&stdkb->_id, &c, 0, 0, 0)); X } X else X c = getchar(); X X switch (c) { X case SMG$K_TRM_LEFT: c = ctl('b'); break; X case SMG$K_TRM_RIGHT: c = ctl('f'); break; X case SMG$K_TRM_UP: c = ctl('p'); break; X case SMG$K_TRM_DOWN: c = ctl('n'); break; X default: c = c & 0x7f; X } X return (c); X} X X XVMS_MSG (status) Xint status; X/* X Routine to put out the VMS operating system error (if one occurs). X*/ X{ X#include <descrip.h> X char errstr[81], buf[120]; X $DESCRIPTOR(errdesc, errstr); X short int length; X#define err_out(msg) fprintf (stderr,msg) X X/* Check for no error or standard error */ X X if (~status & 1) { X status = status & 0x8000 ? status & 0xFFFFFFF : status & 0xFFFF; X if (SYS$GETMSG(status, &length, &errdesc, 1, 0) == SS$_NORMAL) { X errstr[length] = '\0'; X (void) sprintf (buf, "<0x%x> %s", status, errdesc.dsc$a_pointer); X err_out (buf); X } X else X err_out ("System error"); X } X} X#endif /* VMS */ X X#else /*SIMPLE*/ X X#if defined(BSD42) || defined (SYSIII) || defined(BSD43) X X#define N_KEY 4 X Xstruct key_map { X char *k_str; X char k_val; X char k_index; X}; X Xstruct key_map km[N_KEY]; X Xchar keyarea[N_KEY*30]; X Xchar *tgetstr(); Xchar *getenv(); Xchar *ks; Xchar ks_buf[20]; Xchar *ke; Xchar ke_buf[20]; X X#ifdef TIOCSLTC Xstruct ltchars old_chars, new_chars; X#endif X Xchar dont_use[] = { X ctl('['), ctl('a'), ctl('b'), ctl('c'), ctl('e'), ctl('f'), ctl('g'), ctl('h'), X ctl('i'), ctl('j'), ctl('l'), ctl('m'), ctl('n'), ctl('p'), ctl('q'), X ctl('r'), ctl('s'), ctl('t'), ctl('u'), ctl('v'), ctl('w'), ctl('x'), X ctl('z'), 0 X}; X Xvoid Xcharout(c) Xint c; X{ X (void)putchar(c); X} X Xvoid Xinitkbd() X{ X register struct key_map *kp; X register i,j; X char *p = keyarea; X char *ktmp; X static char buf[1024]; /* Why do I have to do this again? */ X X if (!(ktmp = getenv("TERM"))) { X (void) fprintf(stderr, "TERM environment variable not set\n"); X exit (1); X } X if (tgetent(buf, ktmp) <= 0) X return; X X km[0].k_str = tgetstr("kl", &p); km[0].k_val = ctl('b'); X km[1].k_str = tgetstr("kr", &p); km[1].k_val = ctl('f'); X km[2].k_str = tgetstr("ku", &p); km[2].k_val = ctl('p'); X km[3].k_str = tgetstr("kd", &p); km[3].k_val = ctl('n'); X ktmp = tgetstr("ks",&p); X if (ktmp) { X (void) strcpy(ks_buf, ktmp); X ks = ks_buf; X tputs(ks, 1, charout); X } X ktmp = tgetstr("ke",&p); X if (ktmp) { X (void) strcpy(ke_buf, ktmp); X ke = ke_buf; X } X X /* Unmap arrow keys which conflict with our ctl keys */ X /* Ignore unset, longer than length 1, and 1-1 mapped keys */ X X for (i = 0; i < N_KEY; i++) { X kp = &km[i]; X if (kp->k_str && (kp->k_str[1] == 0) && (kp->k_str[0] != kp->k_val)) X for (j = 0; dont_use[j] != 0; j++) X if (kp->k_str[0] == dont_use[j]) { X kp->k_str = (char *)0; X break; X } X } X X X#ifdef TIOCSLTC X (void)ioctl(fileno(stdin), TIOCGLTC, (char *)&old_chars); X new_chars = old_chars; X if (old_chars.t_lnextc == ctl('v')) X new_chars.t_lnextc = -1; X if (old_chars.t_rprntc == ctl('r')) X new_chars.t_rprntc = -1; X (void)ioctl(fileno(stdin), TIOCSLTC, (char *)&new_chars); X#endif X} X Xvoid Xkbd_again() X{ X if (ks) X tputs(ks, 1, charout); X X#ifdef TIOCSLTC X (void)ioctl(fileno(stdin), TIOCSLTC, (char *)&new_chars); X#endif X} X Xvoid Xresetkbd() X{ X if (ke) X tputs(ke, 1, charout); X X#ifdef TIOCSLTC X (void)ioctl(fileno(stdin), TIOCSLTC, (char *)&old_chars); X#endif X} X Xint Xnmgetch() X{ X register int c; X register struct key_map *kp; X register struct key_map *biggest; X register int i; X int almost; X int maybe; X X static char dumpbuf[10]; X static char *dumpindex; X X#ifdef SIGVOID X void time_out(); X#else X int time_out(); X#endif X X if (dumpindex && *dumpindex) X return (*dumpindex++); X X c = toascii(getchar()); X biggest = 0; X almost = 0; X X for (kp = &km[0]; kp < &km[N_KEY]; kp++) { X if (!kp->k_str) X continue; X if (c == kp->k_str[kp->k_index]) { X almost = 1; X kp->k_index++; X if (kp->k_str[kp->k_index] == 0) { X c = kp->k_val; X for (kp = &km[0]; kp < &km[N_KEY]; kp++) X kp->k_index = 0; X return(c); X } X } X if (!biggest && kp->k_index) X biggest = kp; X else if (kp->k_index && biggest->k_index < kp->k_index) X biggest = kp; X } X X if (almost) { X (void) signal(SIGALRM, time_out); X (void) alarm(1); X X if (setjmp(wakeup) == 0) { X maybe = nmgetch(); X (void) alarm(0); X return(maybe); X } X } X X if (biggest) { X for (i = 0; i<biggest->k_index; i++) X dumpbuf[i] = biggest->k_str[i]; X if (!almost) X dumpbuf[i++] = c; X dumpbuf[i] = '\0'; X dumpindex = &dumpbuf[1]; X for (kp = &km[0]; kp < &km[N_KEY]; kp++) X kp->k_index = 0; X return (dumpbuf[0]); X } X X return(c); X} X X#endif X X#if defined(SYSV2) || defined(SYSV3) X Xvoid Xinitkbd() X{ X keypad(stdscr, TRUE); X} X Xvoid Xkbd_again() X{ X keypad(stdscr, TRUE); X} X Xvoid Xresetkbd() X{ X keypad(stdscr, FALSE); X} X Xint Xnmgetch() X{ X register int c; X X c = getch(); X switch (c) { X case KEY_LEFT: c = ctl('b'); break; X case KEY_RIGHT: c = ctl('f'); break; X case KEY_UP: c = ctl('p'); break; X case KEY_DOWN: c = ctl('n'); break; X case KEY_BACKSPACE: c = ctl('h'); break; X#ifdef KEY_C1 X/* This stuff works for a wyse wy75 in ANSI mode under 5.3. Good luck. */ X/* It is supposed to map the curses keypad back to the numeric equiv. */ X case KEY_C1: c = '0'; break; X case KEY_A1: c = '1'; break; X case KEY_B2: c = '2'; break; X case KEY_A3: c = '3'; break; X case KEY_F(5): c = '4'; break; X case KEY_F(6): c = '5'; break; X case KEY_F(7): c = '6'; break; X case KEY_F(9): c = '7'; break; X case KEY_F(10): c = '8'; break; X case KEY_F0: c = '9'; break; X case KEY_C3: c = '.'; break; X case KEY_ENTER: c = ctl('m'); break; X#endif X default: c = toascii(c); X break; X } X return (c); X} X X#endif /* SYSV2 || SYSV3 */ X X#endif /* SIMPLE */ X X#ifdef SIGVOID Xvoid X#else Xint X#endif Xtime_out(signo) Xint signo; X{ X longjmp(wakeup, 1); X} X X/* X * This converts a floating point number of the form X * [s]ddd[.d*][esd*] where s can be a + or - and e is E or e. X * to floating point. X * p is advanced. X */ X Xchar * Xstrtof(p, res) Xregister char *p; Xdouble *res; X{ X double acc; X int sign; X double fpos; X int exp; X int exps; X#ifdef SIGVOID X void (*sig_save)(); X#else X int (*sig_save)(); X#endif X sig_save = signal(SIGFPE, fpe_trap); X if (setjmp(fpe_buf)) { X error("Floating point exception\n"); X *res = 0.0; X (void) signal(SIGFPE, sig_save); X return(p); X } X acc = 0.0; X sign = 1; X exp = 0; X exps = 1; X if (*p == '+') X p++; X else if (*p == '-') { X p++; X sign = -1; X } X while (isdigit(*p)) { X acc = acc * 10.0 + (double)(*p - '0'); X p++; X } X if (*p == 'e' || *p == 'E') { X p++; X if (*p == '+') X p++; X else if (*p == '-') { X p++; X exps = -1; X } X while(isdigit(*p)) { X exp = exp * 10 + (*p - '0'); X p++; X } X } X if (*p == '.') { X fpos = 1.0/10.0; X p++; X while(isdigit(*p)) { X acc += (*p - '0') * fpos; X fpos *= 1.0/10.0; X p++; X } X } X if (*p == 'e' || *p == 'E') { X exp = 0; X exps = 1; X p++; X if (*p == '+') X p++; X else if (*p == '-') { X p++; X exps = -1; X } X while(isdigit(*p)) { X exp = exp * 10 + (*p - '0'); X p++; X } X } X if (exp) { X if (exps > 0) X while (exp--) X acc *= 10.0; X else X while (exp--) X acc *= 1.0/10.0; X } X if (sign > 0) X *res = acc; X else X *res = -acc; X X (void) signal(SIGFPE, sig_save); X return(p); X} END_OF_FILE if test 13772 -ne `wc -c <'lex.c'`; then echo shar: \"'lex.c'\" unpacked with wrong size! fi # end of 'lex.c' fi if test -f 'vi.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'vi.c'\" else echo shar: Extracting \"'vi.c'\" \(13015 characters\) sed "s/^X//" >'vi.c' <<'END_OF_FILE' X/* SC A Spreadsheet Calculator X * X * One line vi emulation X * $Revision: 6.16 $ X */ X X#include <sys/types.h> X#ifdef BSD42 X#include <strings.h> X#else X#ifndef SYSIII X#include <string.h> X#endif X#endif X X#include <signal.h> X#include <curses.h> X Xextern char *strchr(); X X#include <stdio.h> X#include <ctype.h> X#include "sc.h" X X#define istext(a) (isalnum(a) || ((a) == '_')) X Xstatic void append_line(); Xstatic void back_hist(); Xstatic int back_line(); Xstatic int back_word(); Xstatic void back_space(); Xstatic void change_cmd(); Xstatic void col_0(); Xstatic void cr_line(); Xstatic void delete_cmd(); Xstatic void del_chars(); Xstatic void del_in_line(); Xstatic void del_to_end(); Xstatic void dotcmd(); Xstatic int find_char(); Xstatic void for_hist(); Xstatic int for_line(); Xstatic int for_word(); Xstatic void ins_in_line(); Xstatic void last_col(); Xstatic void rep_char(); Xstatic void replace_in_line(); Xstatic void replace_mode(); Xstatic void restore_it(); Xstatic void savedot(); Xstatic void save_hist(); Xstatic void search_again(); Xstatic void search_hist(); Xstatic void search_mode(); Xstatic void stop_edit(); Xstatic int to_char(); Xstatic void u_save(); X Xextern int showrange; Xextern char mode_ind; /* Mode indicator */ X X/* values for mode below */ X X#define INSERT_MODE 0 /* Insert mode */ X#define EDIT_MODE 1 /* Edit mode */ X#define REP_MODE 2 /* Replace mode */ X#define SEARCH_MODE 3 /* Get arguments for '/' command */ X X#define DOTLEN 200 X Xstatic int mode = INSERT_MODE; Xstruct hist { X unsigned int len; X char *histline; X} history[HISTLEN]; X Xstatic int histp = -1; Xstatic int lasthist = -1; Xstatic int endhist = -1; Xstatic char *last_search = NULL; Xstatic char *undo_line = NULL; Xstatic int undo_lim; Xstatic char dotb[DOTLEN]; Xstatic int doti = 0; Xstatic int do_dot = 0; X Xvoid Xwrite_line(c) Xint c; X{ X if (mode == EDIT_MODE) { X switch(c) { X case (ctl('h')): linelim = back_line(); break; X case (ctl('m')): cr_line(); break; X case ESC: stop_edit(); break; X case '+': for_hist(); break; X case '-': back_hist(); break; X case '$': last_col(); break; X case '.': dotcmd(); break; X case '/': search_mode(); break; X case '0': col_0(); break; X case 'D': u_save(c);del_to_end(); break; X case 'I': u_save(c);col_0();insert_mode();break; X case 'R': replace_mode(); break; X case 'X': u_save(c); back_space(); break; X case 'a': u_save(c); append_line(); break; X case 'b': linelim = back_word(); break; X case 'c': u_save(c); change_cmd(); break; X case 'd': u_save(c); delete_cmd(); break; X case 'f': linelim = find_char(); break; X case 'h': linelim = back_line(); break; X case 'i': u_save(c); insert_mode(); break; X case 'j': for_hist(); break; X case 'k': back_hist(); break; X case 'l': linelim = for_line(0); break; X case 'n': search_again(); break; X case 'q': stop_edit(); break; X case 'r': u_save(c); rep_char(); break; X case 't': linelim = to_char(); break; X case 'u': restore_it(); break; X case 'w': linelim = for_word(0); break; X case 'x': u_save(c); del_in_line(); break; X default: break; X } X } else if (mode == INSERT_MODE) { X savedot(c); X switch(c) { X case (ctl('h')): back_space(); break; X case (ctl('m')): cr_line(); break; X case ESC: edit_mode(); break; X default: ins_in_line(c); break; X } X } else if (mode == SEARCH_MODE) { X switch(c) { X case (ctl('h')): back_space(); break; X case (ctl('m')): search_hist(); break; X case ESC: edit_mode(); break; X default: ins_in_line(c); break; X } X } else if (mode == REP_MODE) { X savedot(c); X switch(c) { X case (ctl('h')): back_space(); break; X case (ctl('m')): cr_line(); break; X case ESC: edit_mode(); break; X default: replace_in_line(c); break; X } X } X} X Xvoid Xedit_mode() X{ X mode = EDIT_MODE; X mode_ind = 'e'; X histp = -1; X if (linelim < 0) /* -1 says stop editing, ...so we still aren't */ X return; X if (line[linelim] == '\0') X linelim = back_line(); X} X Xvoid Xinsert_mode() X{ X mode_ind = 'i'; X mode = INSERT_MODE; X} X Xstatic void Xsearch_mode() X{ X line[0] = '/'; X line[1] = '\0'; X linelim = 1; X histp = -1; X mode_ind = '/'; X mode = SEARCH_MODE; X} X Xstatic void Xreplace_mode() X{ X mode_ind = 'R'; X mode = REP_MODE; X} X X/* dot command functions. Saves info so we can redo on a '.' command */ X Xstatic void Xsavedot(c) Xint c; X{ X if (do_dot || (c == '\n')) X return; X X if (doti < DOTLEN-1) X { X dotb[doti++] = c; X dotb[doti] = '\0'; X } X} X Xstatic int dotcalled = 0; X Xstatic void Xdotcmd() X{ X int c; X X if (dotcalled) /* stop recursive calling of dotcmd() */ X return; X do_dot = 1; X doti = 0; X while(dotb[doti] != '\0') { X c = dotb[doti++]; X dotcalled = 1; X write_line(c); X } X do_dot = 0; X doti = 0; X dotcalled = 0; X} X Xint Xvigetch() X{ X int c; X X if(do_dot) { X if (dotb[doti] != '\0') { X return(dotb[doti++]); X } else { X do_dot = 0; X doti = 0; X return(nmgetch()); X } X } X c = nmgetch(); X savedot(c); X return(c); X} X X/* saves the current line for possible use by an undo cmd */ Xstatic void Xu_save(c) Xint c; X{ static unsigned undolen = 0; X X if (strlen(line)+1 > undolen) X { undolen = strlen(line)+40; X X undo_line = xrealloc(undo_line, undolen); X } X (void) strcpy(undo_line, line); X X undo_lim = linelim; X X /* reset dot command if not processing it. */ X X if (!do_dot) { X doti = 0; X savedot(c); X } X} X X/* Restores the current line saved by u_save() */ Xstatic void Xrestore_it() X{ X static char *tempc = NULL; X static unsigned templen = 0; X int tempi; X X if ((undo_line == NULL) || (*undo_line == '\0')) X return; X X if (strlen(line)+1 > templen) X { templen = strlen(line)+40; X tempc = xrealloc(tempc, templen); X } X X strcpy(tempc, line); X tempi = linelim; X (void) strcpy(line, undo_line); X linelim = undo_lim; X strcpy(undo_line, tempc); X undo_lim = tempi; X} X X/* This command stops the editing process. */ Xstatic void Xstop_edit() X{ X showrange = 0; X linelim = -1; X (void) move(1, 0); X (void) clrtoeol(); X} X X/* X * Motion commands. Forward motion commands take an argument X * which, when set, cause the forward motion to continue onto X * the null at the end of the line instead of stopping at the X * the last character of the line. X */ Xstatic int Xfor_line(stop_null) Xint stop_null; X{ X if (linelim >= 0 && line[linelim] != '\0' && X (line[linelim+1] != '\0' || stop_null)) X return(linelim+1); X else X return(linelim); X} X Xstatic int Xfor_word(stop_null) Xint stop_null; X{ X register int c; X register int cpos; X X cpos = linelim; X X if (line[cpos] == ' ') { X while (line[cpos] == ' ') X cpos++; X if (cpos > 0 && line[cpos] == '\0') X --cpos; X return(cpos); X } X X if (istext(line[cpos])) { X while ((c = line[cpos]) && istext(c)) X cpos++; X } else { X while ((c = line[cpos]) && !istext(c) && c != ' ') X cpos++; X } X X while (line[cpos] == ' ') X cpos++; X X if (cpos > 0 && line[cpos] == '\0' && !stop_null) X --cpos; X X return(cpos); X} X Xstatic int Xback_line() X{ X if (linelim) X return(linelim-1); X else X return(0); X} X Xstatic int Xback_word() X{ X register int c; X register int cpos; X X cpos = linelim; X X if (line[cpos] == ' ') { X /* Skip white space */ X while (cpos > 0 && line[cpos] == ' ') X --cpos; X } else if (cpos > 0 && (line[cpos-1] == ' ' X || istext(line[cpos]) && !istext(line[cpos-1]) X || !istext(line[cpos]) && istext(line[cpos-1]))) { X /* Started on the first char of a word - back up to prev. word */ X --cpos; X while (cpos > 0 && line[cpos] == ' ') X --cpos; X } X X /* Skip across the word - goes 1 too far */ X if (istext(line[cpos])) { X while (cpos > 0 && (c = line[cpos]) && istext(c)) X --cpos; X } else { X while (cpos > 0 && (c = line[cpos]) && !istext(c) && c != ' ') X --cpos; X } X X /* We are done - fix up the one too far */ X if (cpos > 0 && line[cpos] && line[cpos+1]) X cpos++; X X return(cpos); X} X X/* Text manipulation commands */ X Xstatic void Xdel_in_line() X{ X register int len, i; X X if (linelim >= 0) { X len = strlen(line); X if (linelim == len && linelim > 0) X linelim--; X for (i = linelim; i < len; i++) X line[i] = line[i+1]; X } X if (linelim > 0 && line[linelim] == '\0') X --linelim; X} X Xstatic void Xins_in_line(c) Xint c; X{ X register int i, len; X X if (linelim < 0) X { *line = '\0'; X linelim = 0; X } X len = strlen(line); X for (i = len; i >= linelim; --i) X line[i+1] = line[i]; X line[linelim++] = c; X line[len+1] = '\0'; X} X Xvoid Xins_string(s) Xchar *s; X{ X while (*s) X ins_in_line(*s++); X} X Xstatic void Xappend_line() X{ X register int i; X X i = linelim; X if (i >= 0 && line[i]) X linelim++; X insert_mode(); X} X Xstatic void Xrep_char() X{ X int c; X X if (linelim < 0) X { linelim = 0; X *line = '\0'; X } X c = vigetch(); X if (line[linelim] != '\0') { X line[linelim] = c; X } else { X line[linelim] = c; X line[linelim+1] = '\0'; X } X} X Xstatic void Xreplace_in_line(c) Xint c; X{ X register int len; X X if (linelim < 0) X { linelim = 0; X *line = '\0'; X } X len = strlen(line); X line[linelim++] = c; X if (linelim > len) X line[linelim] = '\0'; X} X Xstatic void Xback_space() X{ X if (linelim == 0) X return; X X if (line[linelim] == '\0') { X linelim = back_line(); X del_in_line(); X linelim = strlen(line); X } else { X linelim = back_line(); X del_in_line(); X } X} X Xint Xget_motion() X{ X int c; X X c = vigetch(); X switch (c) { X case 'b': return(back_word()); X case 'f': return(find_char()+1); X case 'h': return(back_line()); X case 'l': return(for_line(1)); X case 't': return(to_char()+1); X case 'w': return(for_word(1)); X default: return(linelim); X } X} X Xstatic void Xdelete_cmd() X{ X int cpos; X X cpos = get_motion(); X del_chars(cpos, linelim); X} X Xstatic void Xchange_cmd() X{ X delete_cmd(); X insert_mode(); X} X Xstatic void Xdel_chars(first, last) Xregister int first, last; X{ X int temp; X X if (first == last) X return; X X if (last < first) { X temp = last; last = first; first = temp; X } X X linelim = first; X while(first < last) { X del_in_line(); X --last; X } X} X Xstatic void Xdel_to_end() X{ X if (linelim < 0) X return; X line[linelim] = '\0'; X linelim = back_line(); X} X Xstatic void Xcr_line() X{ X insert_mode(); X if (linelim != -1) { X showrange = 0; X save_hist(); X linelim = 0; X (void) yyparse (); X linelim = -1; X } X else /* '\n' alone will put you into insert mode */ X { *line = '\0'; X linelim = 0; X } X} X X/* History functions */ X Xstatic void Xsave_hist() X{ X if (lasthist < 0) X { lasthist = 0; X } X else X lasthist = (lasthist + 1) % HISTLEN; X X if (lasthist > endhist) X endhist = lasthist; X X if (history[lasthist].len < strlen(line)+1) X { history[lasthist].len = strlen(line)+40; X history[lasthist].histline = xrealloc(history[lasthist].histline, X history[lasthist].len); X } X (void) strcpy(history[lasthist].histline, line); X} X Xstatic void Xback_hist() X{ X if (histp == -1) X histp = lasthist; X else X if (histp == 0) X { if (endhist != lasthist) X histp = endhist; X } X else X if (histp != ((lasthist + 1) % (endhist + 1))) X histp--; X X if (lasthist < 0) X line[linelim = 0] = '\0'; X else { X (void) strcpy(line, history[histp].histline); X linelim = 0; X } X} X Xstatic void Xsearch_hist() X{ X static unsigned lastsrchlen = 0; X X if(linelim < 1) { X linelim = 0; X edit_mode(); X return; X } X X if (strlen(line)+1 > lastsrchlen) X { lastsrchlen = strlen(line)+40; X last_search = xrealloc(last_search, lastsrchlen); X } X (void)strcpy(last_search, line+1); X search_again(); X mode = EDIT_MODE; X} X Xstatic void Xsearch_again() X{ X int found_it; X int do_next; X int prev_histp; X char *look_here; X X prev_histp = histp; X if ((last_search == NULL) || (*last_search == '\0')) X return; X X do { X back_hist(); X if (prev_histp == histp) X break; X prev_histp = histp; X look_here = line; X found_it = do_next = 0; X while ((look_here = strchr(look_here, last_search[0])) && X !found_it && !do_next) { X X if (strncmp(look_here, last_search, strlen(last_search)) == 0) X found_it++; X else if (look_here < line + strlen(line) - 1) X look_here++; X else X do_next++; X } X } while (!found_it); X} X Xstatic void Xfor_hist() X{ X if (histp == -1) X histp = lasthist; X else X if (histp != lasthist) X histp = (histp + 1) % (endhist + 1); X X if (lasthist < 0) X line[linelim = 0] = '\0'; X else { X (void) strcpy(line, history[histp].histline); X linelim = 0; X } X} X Xstatic void Xcol_0() X{ X linelim = 0; X} X Xstatic void Xlast_col() X{ X linelim = strlen(line); X if (linelim > 0) X --linelim; X} X Xstatic int Xfind_char() X{ X register int c; X register int i; X X X c = vigetch(); X i = linelim; X while(line[i] && line[i] != c) X i++; X if (!line[i]) X i = linelim; X return(i); X} X Xstatic int Xto_char() X{ X register int i; X X i = find_char(); X if (i > 0 && i != linelim) X --i; X X return(i); X} END_OF_FILE if test 13015 -ne `wc -c <'vi.c'`; then echo shar: \"'vi.c'\" unpacked with wrong size! fi # end of 'vi.c' fi echo shar: End of archive 6 \(of 7\). cp /dev/null ark6isdone MISSING="" for I in 1 2 3 4 5 6 7 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 7 archives. rm -f ark[1-9]isdone else echo You still must unpack the following archives: echo " " ${MISSING} fi exit 0 exit 0 # Just in case... -- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM Sterling Software, IMD UUCP: uunet!sparky!kent Phone: (402) 291-8300 FAX: (402) 291-4362 Please send comp.sources.misc-related mail to kent@uunet.uu.net.