v20i040: sc - The SC Spreadsheet, release 6.16, Part06/07
Jeff Buhrt
prslnk!buhrt at cs.indiana.edu
Thu Jun 6 03:28:50 AEST 1991
Submitted-by: Jeff Buhrt <prslnk!buhrt at 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 at uunet.uu.net if you want that tool.
# Contents: Makefile TODO gram.y lex.c vi.c
# Wrapped by kent at 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 at 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 at 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 at uunet.uu.net.
More information about the Comp.sources.misc
mailing list