Official Sc6.9 -> Sc6.10 patches (Please Apply) (1 of 2)

Jeffery A Buhrt buhrt at sawmill.uucp
Sat Oct 27 08:18:49 AEST 1990


These are patches to Sc6.9 and fix core dumping plus adds some new features;
see below for details.

Please mail me any new changes or additions. Sorry 6.9 -> 6.10 took so
long but news/mail has been unstable upline.

Assuming things go right your checksums should be: (SysV: sum -r, BSD:sum)
46813    12 CHANGES
64088     6 Makefile
02321     3 README
25584     2 TODO
06605     5 VMS_NOTES
02715    33 cmds.c
60659     4 crypt.c
32988     1 eres.sed
03167    14 format.c
30490    13 gram.y
01508    17 help.c
20140    49 interp.c
01181    14 lex.c
63789     7 psc.c
26774     3 psc.doc
44645     6 range.c
09435    35 sc.c
59554    51 sc.doc
33138    10 sc.h
44252     1 sres.sed
10320     5 tutorial.sc
43349     1 version.c
49264    13 vi.c
29399     5 vmtbl.c
04679     1 xmalloc.c

						-Jeff Buhrt
						317-477-6000
					sequent!sawmill!buhrt


*** 69/CHANGES	Thu Oct  4 09:12:41 1990
--- CHANGES	Fri Oct 26 16:57:00 1990
***************
*** 1,4
  
  CHANGES BETWEEN 6.9 and 6.8
  
  Jim Richardson

--- 1,36 -----
  
+ CHANGES BETWEEN 6.10 and 6.9
+ 
+ Tom Tkacik
+ 	- when moving off the current table (resizing) now move the cursor
+ 		on 'l' or 'k'.
+ 	- patches to sc.doc to correctly format the vi-mode notes
+ Jim Clausing
+ 	- made sure / doesn't try to divide by zero.
+ Tom Kloos
+ 	- correction to substr() example in help.c
+ Piercarlo "Peter" Grandi
+ 	- Disable non-constant expressions while loading
+ 	- Added extra code in dealing w/ floating point exceptions
+ 	- #ifdef'd SAVENAME (vs hardcoded SC.SAVE) to allowing changing the
+ 		emergency save name.
+ Casey Leedom
+ 	- Makefile changes: man extension, RINT note, make values should
+ 		never be left undefined and then referenced, don't leave
+ 		around *.old's
+ Tom Anderson
+ 	- patches to add type of column format (note format now has 3 args)
+ Jeff Buhrt
+ 	- xmalloc/xfree fatal() will now call diesave()
+ 		(MAKE SURE the saved file is ok if this were to happen)
+ 	- history[] is now a circular queue, this will cut down on the
+ 		number of data moves and also xmalloc/xfree calls
+ 		(idea from Keith Bostic)
+ 	- cells with an error (ex: divide by 0) will show 'ERROR'
+ 	- you can 'goto error' (or 'goto') to find an ERROR (for next ERROR)
+ Robert Bond
+ 	- When in numeric mode the ^B, ^F, ^N, ^P key will end a numeric entry.
+ 
  CHANGES BETWEEN 6.9 and 6.8
  
  Jim Richardson
*** 69/Makefile	Thu Oct  4 09:13:03 1990
--- Makefile	Fri Oct 26 17:00:51 1990
***************
*** 10,15
  
  # This is where the man page goes.
  #MANDIR=/site/man/man1
  MANDIR=/usr/man/manl
  
  # This is where the library file (tutorial) goes.

--- 10,16 -----
  
  # This is where the man page goes.
  #MANDIR=/site/man/man1
+ #MANEXT=1
  MANDIR=/usr/man/manl
  MANEXT=l
  
***************
*** 11,16
  # This is where the man page goes.
  #MANDIR=/site/man/man1
  MANDIR=/usr/man/manl
  
  # This is where the library file (tutorial) goes.
  #LIBDIR=/site/lib/sc

--- 12,18 -----
  #MANDIR=/site/man/man1
  #MANEXT=1
  MANDIR=/usr/man/manl
+ MANEXT=l
  
  # This is where the library file (tutorial) goes.
  #LIBDIR=/site/lib/sc
***************
*** 17,22
  LIBDIR=/usr/local/lib/sc
  
  # Set SIMPLE for lex.c if you don't want arrow keys or lex.c blows up
  #SIMPLE=-DSIMPLE
  
  # Set DOBACKUPS if you would like a backup copy of a source file on a save

--- 19,25 -----
  LIBDIR=/usr/local/lib/sc
  
  # Set SIMPLE for lex.c if you don't want arrow keys or lex.c blows up
+ SIMPLE=
  #SIMPLE=-DSIMPLE
  
  # Set DOBACKUPS if you would like a backup copy of a source file on a save
***************
*** 20,25
  #SIMPLE=-DSIMPLE
  
  # Set DOBACKUPS if you would like a backup copy of a source file on a save
  DOBACKUPS=-DDOBACKUPS
  
  # Set INTERNATIONAL if you need 8 bit characters.  You should

--- 23,29 -----
  #SIMPLE=-DSIMPLE
  
  # Set DOBACKUPS if you would like a backup copy of a source file on a save
+ #DOBACKUPS=
  DOBACKUPS=-DDOBACKUPS
  
  # Set INTERNATIONAL if you need 8 bit characters.  You should
***************
*** 25,30
  # Set INTERNATIONAL if you need 8 bit characters.  You should
  # not set this if you are running 5.3.0.  I think it is OK in 5.3.1.
  #INTERNATIONAL=-DINTERNATIONAL
  # Set SIGVOID if signal routines are type void.  System 5.3, VMS and ANSI C
  # Compliant systems use this.  Most BSD systems do not.
  #SIGVOID=-DSIGVOID

--- 29,36 -----
  # Set INTERNATIONAL if you need 8 bit characters.  You should
  # not set this if you are running 5.3.0.  I think it is OK in 5.3.1.
  #INTERNATIONAL=-DINTERNATIONAL
+ INTERNATIONAL=
+ 
  # Set SIGVOID if signal routines are type void.  System 5.3, VMS and ANSI C
  # Compliant systems use this.  Most BSD systems do not.
  SIGVOID=-DSIGVOID
***************
*** 27,33
  #INTERNATIONAL=-DINTERNATIONAL
  # Set SIGVOID if signal routines are type void.  System 5.3, VMS and ANSI C
  # Compliant systems use this.  Most BSD systems do not.
! #SIGVOID=-DSIGVOID
  
  # Set IEEE_MATH if you need setsticky() calls in your signal handlers
  #

--- 33,40 -----
  
  # Set SIGVOID if signal routines are type void.  System 5.3, VMS and ANSI C
  # Compliant systems use this.  Most BSD systems do not.
! SIGVOID=-DSIGVOID
! #SIGVOID=
  
  # Set IEEE_MATH if you need setsticky() calls in your signal handlers
  #
***************
*** 32,37
  # Set IEEE_MATH if you need setsticky() calls in your signal handlers
  #
  #IEEE_MATH=-DIEEE_MATH
  
  # Set RINT if you do not have rint() in math.h
  RINT=-DRINT

--- 39,45 -----
  # Set IEEE_MATH if you need setsticky() calls in your signal handlers
  #
  #IEEE_MATH=-DIEEE_MATH
+ IEEE_MATH=
  
  # Set RINT if you do not have rint() in math.h
  # So far I know you what to undefine this on/with:
***************
*** 34,39
  #IEEE_MATH=-DIEEE_MATH
  
  # Set RINT if you do not have rint() in math.h
  RINT=-DRINT
  
  # This is the name of a pager like "more" If the line is commented out

--- 42,50 -----
  IEEE_MATH=
  
  # Set RINT if you do not have rint() in math.h
+ # So far I know you what to undefine this on/with:
+ #	SunOS 4.0.3c compiler
+ #RINT=
  RINT=-DRINT
  
  # This is the name of a pager like "more".
***************
*** 36,44
  # Set RINT if you do not have rint() in math.h
  RINT=-DRINT
  
! # This is the name of a pager like "more" If the line is commented out
! # then "more" will be used. "pg" may be appropriate for SYSV
! PAGER=-DDFLT_PAGER=\"less\"
  
  # For ULTRIX: define the BSD4.2 section and SIGVOID above
  #	tdw at cl.cam.ac.uk tested on Ultrix 3.1C-0

--- 47,56 -----
  #RINT=
  RINT=-DRINT
  
! # This is the name of a pager like "more".
! # "pg" may be appropriate for SYSV.
! #DFLTPAGER=-DDFLT_PAGER=\"less\"
! DFLT_PAGER=-DDFLT_PAGER=\"more\"
  
  # For ULTRIX: define the BSD4.2 section and SIGVOID above
  #	tdw at cl.cam.ac.uk tested on Ultrix 3.1C-0
***************
*** 98,104
  
  # All of the source files
  SRC=sc.h sc.c lex.c gram.y interp.c crypt.c xmalloc.c cmds.c range.c help.c \
! 	vi.c eres.sed sres.sed Makefile psc.c vmtbl.c version.c
  
  # The objects
  OBJS=sc.o interp.o cmds.o crypt.o xmalloc.o range.o help.o vi.o lex.o gram.o \

--- 110,116 -----
  
  # All of the source files
  SRC=sc.h sc.c lex.c gram.y interp.c crypt.c xmalloc.c cmds.c range.c help.c \
! 	vi.c eres.sed sres.sed Makefile psc.c vmtbl.c version.c 
  
  # The objects
  OBJS=sc.o interp.o cmds.o gram.o lex.o crypt.o xmalloc.o range.o help.o vi.o \
***************
*** 101,108
  	vi.c eres.sed sres.sed Makefile psc.c vmtbl.c version.c
  
  # The objects
! OBJS=sc.o interp.o cmds.o crypt.o xmalloc.o range.o help.o vi.o lex.o gram.o \
! 	vmtbl.o format.o version.o
  
  # The documents in the Archive
  DOCS=README CHANGES sc.doc psc.doc tutorial.sc VMS_NOTES BSD_BUGS

--- 113,120 -----
  	vi.c eres.sed sres.sed Makefile psc.c vmtbl.c version.c 
  
  # The objects
! OBJS=sc.o interp.o cmds.o gram.o lex.o crypt.o xmalloc.o range.o help.o vi.o \
! 	vmtbl.o format.o version.o 
  
  # The documents in the Archive
  DOCS=README CHANGES sc.doc psc.doc tutorial.sc VMS_NOTES
***************
*** 105,111
  	vmtbl.o format.o version.o
  
  # The documents in the Archive
! DOCS=README CHANGES sc.doc psc.doc tutorial.sc VMS_NOTES BSD_BUGS
  
  $(name):$(PAR) 	$(OBJS)
  	$(CC) ${CFLAGS} ${LDFLAGS} ${OBJS} ${LIB} -o $(name)

--- 117,123 -----
  	vmtbl.o format.o version.o 
  
  # The documents in the Archive
! DOCS=README CHANGES sc.doc psc.doc tutorial.sc VMS_NOTES
  
  $(name):$(PAR) 	$(OBJS)
  	$(CC) ${CFLAGS} ${LDFLAGS} ${OBJS} ${LIB} -o $(name)
***************
*** 125,131
  	$(CC) ${CFLAGS} ${SIMPLE} ${IEEE_MATH} ${INTERNATIONAL} ${SIGVOID} -c lex.c
  
  sc.o:	sc.h sc.c
! 	$(CC) ${CFLAGS} ${INTERNATIONAL} ${PAGER} ${SIGVOID} -c sc.c
  
  interp.o:	interp.c sc.h
  	$(CC) ${CFLAGS} ${IEEE_MATH} ${SIGVOID} ${RINT} -c interp.c

--- 137,143 -----
  	$(CC) ${CFLAGS} ${SIMPLE} ${IEEE_MATH} ${INTERNATIONAL} ${SIGVOID} -c lex.c
  
  sc.o:	sc.h sc.c
! 	$(CC) ${CFLAGS} ${INTERNATIONAL} ${DFLT_PAGER} ${SIGVOID} -c sc.c
  
  interp.o:	interp.c sc.h
  	$(CC) ${CFLAGS} ${IEEE_MATH} ${SIGVOID} ${RINT} -c interp.c
***************
*** 192,198
  p$(name).man:	p$(name).1
  	nroff -man p$(name).1 > p$(name).man
  
! install: $(EXDIR)/$(name) $(LIBDIR)/tutorial
  
  inst-man: $(MANDIR)/$(name).1
  

--- 204,210 -----
  p$(name).man:	p$(name).1
  	nroff -man p$(name).1 > p$(name).man
  
! install: $(EXDIR)/$(name) $(LIBDIR)/tutorial $(MANDIR)/$(name).$(MANEXT)
  
  $(EXDIR)/$(name): $(name)
  	cp $(name) $(EXDIR)
***************
*** 194,201
  
  install: $(EXDIR)/$(name) $(LIBDIR)/tutorial
  
- inst-man: $(MANDIR)/$(name).1
- 
  $(EXDIR)/$(name): $(name)
  	-mv $(EXDIR)/$(name) $(EXDIR)/$(name).old
  	cp $(name) $(EXDIR)

--- 206,211 -----
  
  install: $(EXDIR)/$(name) $(LIBDIR)/tutorial $(MANDIR)/$(name).$(MANEXT)
  
  $(EXDIR)/$(name): $(name)
  	cp $(name) $(EXDIR)
  	strip $(EXDIR)/$(name)
***************
*** 197,203
  inst-man: $(MANDIR)/$(name).1
  
  $(EXDIR)/$(name): $(name)
- 	-mv $(EXDIR)/$(name) $(EXDIR)/$(name).old
  	cp $(name) $(EXDIR)
  	strip $(EXDIR)/$(name)
  

--- 207,212 -----
  install: $(EXDIR)/$(name) $(LIBDIR)/tutorial $(MANDIR)/$(name).$(MANEXT)
  
  $(EXDIR)/$(name): $(name)
  	cp $(name) $(EXDIR)
  	strip $(EXDIR)/$(name)
  
***************
*** 201,208
  	cp $(name) $(EXDIR)
  	strip $(EXDIR)/$(name)
  
! $(LIBDIR)/tutorial: tutorial.sc
! 	-mkdir $(LIBDIR)
  	cp tutorial.sc $(LIBDIR)
  
  $(MANDIR)/$(name).1: $(name).1

--- 210,216 -----
  	cp $(name) $(EXDIR)
  	strip $(EXDIR)/$(name)
  
! $(LIBDIR)/tutorial: tutorial.sc $(LIBDIR)
  	cp tutorial.sc $(LIBDIR)
  
  $(LIBDIR):
***************
*** 205,212
  	-mkdir $(LIBDIR)
  	cp tutorial.sc $(LIBDIR)
  
! $(MANDIR)/$(name).1: $(name).1
! 	cp $(name).1 $(MANDIR)
  
  diffs: ${SRC}
  	for i in ${SRC} ${DOCS} ;\

--- 213,220 -----
  $(LIBDIR)/tutorial: tutorial.sc $(LIBDIR)
  	cp tutorial.sc $(LIBDIR)
  
! $(LIBDIR):
! 	mkdir $(LIBDIR)
  
  $(MANDIR)/$(name).$(MANEXT): $(name).1
  	cp $(name).1 $(MANDIR)/$(name).$(MANEXT)
***************
*** 208,213
  $(MANDIR)/$(name).1: $(name).1
  	cp $(name).1 $(MANDIR)
  
  diffs: ${SRC}
  	for i in ${SRC} ${DOCS} ;\
  		do \

--- 216,224 -----
  $(LIBDIR):
  	mkdir $(LIBDIR)
  
+ $(MANDIR)/$(name).$(MANEXT): $(name).1
+ 	cp $(name).1 $(MANDIR)/$(name).$(MANEXT)
+ 
  diffs: ${SRC}
  	for i in ${SRC} ${DOCS} ;\
  		do \
***************
*** 212,217
  	for i in ${SRC} ${DOCS} ;\
  		do \
  		rcsdiff -c -r6.1 $$i ;\
  		done
  
  test: test.o vmtbl.o

--- 223,236 -----
  	for i in ${SRC} ${DOCS} ;\
  		do \
  		rcsdiff -c -r6.1 $$i ;\
+ 		done
+ 
+ # THA 10/14/90  Added code to make a patchfile
+ patchfile: ${SRC}
+ 	rm -f patchfile
+ 	for i in ${SRC} ${DOCS} format.c ;\
+ 		do \
+ 		diffc $$i /users/toma/sc6.8me/$$i >> patchfile ;\
  		done
  
  test: test.o vmtbl.o
*** 69/README	Thu Oct  4 09:13:17 1990
--- README	Fri Oct 26 17:04:45 1990
***************
*** 1,8
  This is a much modified version of the public domain spread sheet sc,
  posted several years ago by Mark Weiser as vc, originally by James Gosling.
  
! Changes since my last version (5.1) are detailed at great length :-)
! in CHANGES (sequent!rgb (Robert Bond)).
  
  When you get it built, try "sc tutorial.sc" for a simple introduction
  to the basic commands.

--- 1,8 -----
  This is a much modified version of the public domain spread sheet sc,
  posted several years ago by Mark Weiser as vc, originally by James Gosling.
  
! CHANGES lists the changes since 6.1 to 6.10.
! Current maintainer: sequent!sawmill!buhrt (Jeff Buhrt)
  
  When you get it built, try "sc tutorial.sc" for a simple introduction
  to the basic commands.
***************
*** 25,32
  have nroff, you will have to change sc.man yourself.
  
  This release has been tested against a Sequent S81 running DYNIX 3.0.14
! (BSD 4.2) and an ICM-3216 with system V.3.  The ICM has a National Semi
! 32016.  Just check the makefile for the system flags.   I have heard
  reports of lots of other machines that work. If you have problems with
  lex.c, and don't care about arrow keys, define SIMPLE (-DSIMPLE in the
  makefile).  SIMPLE causes the arrow keys to not be used.

--- 25,32 -----
  have nroff, you will have to change sc.man yourself.
  
  This release has been tested against a Sequent S81 running DYNIX 3.0.14
! (BSD 4.2), AT&T SysV 3.2.2, ESIX SysV 3.2 Rev D.
! Just check the makefile for the system flags.   I have heard
  reports of lots of other machines that work. If you have problems with
  lex.c, and don't care about arrow keys, define SIMPLE (-DSIMPLE in the
  makefile).  SIMPLE causes the arrow keys to not be used.
***************
*** 59,62
  
  					Jeff Buhrt
  					Grauel Enterprises, Inc.
! 	{pur-phy (aka: newton.physics.purdue.edu), sequent}!sawmill!buhrt

--- 59,63 -----
  
  					Jeff Buhrt
  					Grauel Enterprises, Inc.
! 					sequent!sawmill!buhrt
! 
*** 69/cmds.c	Thu Oct  4 09:16:00 1990
--- cmds.c	Fri Oct 26 17:00:59 1990
***************
*** 7,13
   *
   *              More mods Robert Bond, 12/86
   *
!  *		$Revision: 6.9 $
   */
  
  #include <curses.h>

--- 7,13 -----
   *
   *              More mods Robert Bond, 12/86
   *
!  *		$Revision: 6.10 $
   */
  
  #include <curses.h>
***************
*** 422,427
      for (i = maxcol; i > cs; i--) {
  	fwidth[i] = fwidth[i-numcol];
  	precision[i] = precision[i-numcol];
  	col_hidden[i] = col_hidden[i-numcol];
      }
      for (c = cs; c - cs < numcol; c++)

--- 422,428 -----
      for (i = maxcol; i > cs; i--) {
  	fwidth[i] = fwidth[i-numcol];
  	precision[i] = precision[i-numcol];
+ 	realfmt[i] = realfmt[i-numcol];
  	col_hidden[i] = col_hidden[i-numcol];
      }
      for (c = cs; c - cs < numcol; c++)
***************
*** 427,432
      for (c = cs; c - cs < numcol; c++)
      {	fwidth[c] = DEFWIDTH;
  	precision[c] =  DEFPREC;
      }
  	
      for (r=0; r<=maxrow; r++) {

--- 428,434 -----
      for (c = cs; c - cs < numcol; c++)
      {	fwidth[c] = DEFWIDTH;
  	precision[c] =  DEFPREC;
+ 	realfmt[c] = DEFREFMT;
      }
  	
      for (r=0; r<=maxrow; r++) {
***************
*** 490,495
      for (i = cs; i < maxcols - numcol - 1; i++) {
  	fwidth[i] = fwidth[i+numcol];
  	precision[i] = precision[i+numcol];
  	col_hidden[i] = col_hidden[i+numcol];
      }
      for (; i < maxcols - 1; i++) {

--- 492,498 -----
      for (i = cs; i < maxcols - numcol - 1; i++) {
  	fwidth[i] = fwidth[i+numcol];
  	precision[i] = precision[i+numcol];
+ 	realfmt[i] = realfmt[i+numcol];
  	col_hidden[i] = col_hidden[i+numcol];
      }
      for (; i < maxcols - 1; i++) {
***************
*** 495,500
      for (; i < maxcols - 1; i++) {
  	fwidth[i] = DEFWIDTH;
  	precision[i] = DEFPREC;
  	col_hidden[i] = 0;
      }
  

--- 498,504 -----
      for (; i < maxcols - 1; i++) {
  	fwidth[i] = DEFWIDTH;
  	precision[i] = DEFPREC;
+ 	realfmt[i] = DEFREFMT;
  	col_hidden[i] = 0;
      }
  
***************
*** 577,582
      }
  }
  
  void
  doformat(c1,c2,w,p)
  int c1,c2,w,p;

--- 581,587 -----
      }
  }
  
+ /* Modified 9/17/90 THA to handle more formats */
  void
  doformat(c1,c2,w,p,r)
  int c1,c2,w,p,r;
***************
*** 578,585
  }
  
  void
! doformat(c1,c2,w,p)
! int c1,c2,w,p;
  {
      register int i;
  

--- 583,590 -----
  
  /* Modified 9/17/90 THA to handle more formats */
  void
! doformat(c1,c2,w,p,r)
! int c1,c2,w,p,r;
  {
      register int i;
  
***************
*** 597,603
      }
  
      for(i = c1; i<=c2; i++)
! 	fwidth[i] = w, precision[i] = p;
  
      FullUpdate++;
      modflg++;

--- 602,608 -----
      }
  
      for(i = c1; i<=c2; i++)
! 	fwidth[i] = w, precision[i] = p, realfmt[i] = r;
  
      FullUpdate++;
      modflg++;
***************
*** 658,668
      register row, col;
      register struct ent **pp;
  
-     if((pline = (char *)malloc(FBUFLEN * ++fbufs_allocated)) == (char *)NULL) {
-         error("Malloc failed in printfile()");
-         return;
-     }
- 
      if ((strcmp(fname, curfile) == 0) &&
  	!yn_ask("Confirm that you want to destroy the data base: (y,n)")) {
          free((char *)pline);

--- 663,668 -----
      register row, col;
      register struct ent **pp;
  
      if ((strcmp(fname, curfile) == 0) &&
  	!yn_ask("Confirm that you want to destroy the data base: (y,n)")) {
          free((char *)pline);
***************
*** 669,674
  	return;
      }
  
      if ((f = openout(fname, &pid)) == (FILE *)0)
      {	error ("Can't create file \"%s\"", fname);
          free((char *)pline);

--- 669,679 -----
  	return;
      }
  
+     if((pline = (char *)malloc(FBUFLEN * ++fbufs_allocated)) == (char *)NULL) {
+         error("Malloc failed in printfile()");
+         return;
+     }
+ 
      if ((f = openout(fname, &pid)) == (FILE *)0)
      {	error ("Can't create file \"%s\"", fname);
          free((char *)pline);
***************
*** 721,731
  			free((char *)pline);
  			return;
  		      }
! 		    }		  
! 		    if ((*pp)->format) {
! 			char field[FBUFLEN];
! 
! 			(void) format ((*pp)->format, (*pp)->v, field,
  				       sizeof(field));
  			(void) sprintf (pline+plinelim, "%*s", fwidth[col],
  					field);

--- 726,740 -----
  			free((char *)pline);
  			return;
  		      }
! 		    }
! 		    if ((*pp)->cellerror)
! 			(void) sprintf (pline+plinelim, "%*s", "ERROR",
! 						fwidth[col]);
! 		    else
! 		    {
! 		      if ((*pp)->format) {
! 	   	        char field[FBUFLEN];
! 			format ((*pp)->format, (*pp)->v, field,
  				       sizeof(field));
  			(void) sprintf (pline+plinelim, "%*s", fwidth[col],
  					field);
***************
*** 729,737
  				       sizeof(field));
  			(void) sprintf (pline+plinelim, "%*s", fwidth[col],
  					field);
! 		    } else {
! 			(void)sprintf (pline+plinelim,"%*.*f",fwidth[col],
! 				       precision[col], (*pp)->v);
  		    }
  		    plinelim += strlen (pline+plinelim);
  		}

--- 738,751 -----
  				       sizeof(field));
  			(void) sprintf (pline+plinelim, "%*s", fwidth[col],
  					field);
! 		      } else {
! 	   	        char field[FBUFLEN];
! 			engformat(realfmt[col], fwidth[col],
!                                              precision[col], (*pp) -> v,
!                                              field, sizeof(field));
! 			(void)sprintf (pline+plinelim, "%*s", fwidth[col],
! 				       field);
! 		      }
  		    }
  		    plinelim += strlen (pline+plinelim);
  		}
***************
*** 846,853
  				       sizeof(field));
  			(void) fprintf (f, "%s", field);
  		    } else {
! 		        (void) fprintf (f,"%.*f",precision[col],
! 					(*pp)->v);
  		    }
  		}
  		if (s = (*pp)->label) {

--- 860,870 -----
  				       sizeof(field));
  			(void) fprintf (f, "%s", field);
  		    } else {
! 		        char field[FBUFLEN];
!                         engformat(realfmt[col], fwidth[col],
!                                              precision[col], (*pp) -> v,
!                                              field, sizeof(field));
! 			(void) fprintf (f, "%s", field);
  		    }
  		}
  		if (s = (*pp)->label) {
***************
*** 1181,1188
      (void) fprintf (f, "# You almost certainly shouldn't edit it.\n\n");
      print_options(f);
      for (c=0; c<maxcols; c++)
! 	if (fwidth[c] != DEFWIDTH || precision[c] != DEFPREC)
! 	    (void) fprintf (f, "format %s %d %d\n",coltoa(c),fwidth[c],precision[c]);
      for (c=c0; c<cn; c++) {
          if (col_hidden[c]) {
              (void) fprintf(f, "hide %s\n", coltoa(c));

--- 1198,1205 -----
      (void) fprintf (f, "# You almost certainly shouldn't edit it.\n\n");
      print_options(f);
      for (c=0; c<maxcols; c++)
! 	if (fwidth[c] != DEFWIDTH || precision[c] != DEFPREC || realfmt[c] != DEFREFMT )
! 	    (void) fprintf (f, "format %s %d %d %d\n",coltoa(c),fwidth[c],precision[c],realfmt[c]);
      for (c=c0; c<cn; c++) {
          if (col_hidden[c]) {
              (void) fprintf(f, "hide %s\n", coltoa(c));
***************
*** 1314,1319
      for (c = 0; c<=maxcol; c++) {
  	fwidth[c] = DEFWIDTH;
  	precision[c] = DEFPREC;
      }
  
      for (r = 0; r<=maxrow; r++) {

--- 1331,1337 -----
      for (c = 0; c<=maxcol; c++) {
  	fwidth[c] = DEFWIDTH;
  	precision[c] = DEFPREC;
+ 	realfmt[c] = DEFREFMT;
      }
  
      for (r = 0; r<=maxrow; r++) {
***************
*** 1356,1361
  	else
  	if (!growtbl(GROWCOL, 0, arg))	/* get as much as needed */
  		break;
  	while(col_hidden[curcol]&&(curcol<maxcols-1))
  	    curcol++;
      }

--- 1374,1381 -----
  	else
  	if (!growtbl(GROWCOL, 0, arg))	/* get as much as needed */
  		break;
+ 	else
+ 		curcol++;
  	while(col_hidden[curcol]&&(curcol<maxcols-1))
  	    curcol++;
      }
***************
*** 1371,1376
  	else
  	if (!growtbl(GROWROW, arg, 0))	/* get as much as needed */
  		break;
  	while (row_hidden[currow]&&(currow<maxrows-1))
  	    currow++;
      }

--- 1391,1398 -----
  	else
  	if (!growtbl(GROWROW, arg, 0))	/* get as much as needed */
  		break;
+ 	else
+ 		currow++;
  	while (row_hidden[currow]&&(currow<maxrows-1))
  	    currow++;
      }
*** 69/crypt.c	Thu Oct  4 09:16:09 1990
--- crypt.c	Fri Oct 26 16:57:11 1990
***************
*** 2,8
   * Encryption utilites
   * Bradley Williams	
   * {allegra,ihnp4,uiucdcs,ctvax}!convex!williams
!  * $Revision: 6.9 $
   */
  
  #include <stdio.h>

--- 2,8 -----
   * Encryption utilites
   * Bradley Williams	
   * {allegra,ihnp4,uiucdcs,ctvax}!convex!williams
!  * $Revision: 6.10 $
   */
  
  #include <stdio.h>
***************
*** 24,30
  
  int         Crypt = 0;
  #define MAXKEYWORDSIZE 30
! char	    KeyWord[MAXKEYWORDSIZE] = NULL;
  
  creadfile (save, eraseflg)
  char *save;

--- 24,30 -----
  
  int         Crypt = 0;
  #define MAXKEYWORDSIZE 30
! char	    KeyWord[MAXKEYWORDSIZE] = {NULL};
  
  void
  creadfile (save, eraseflg)
***************
*** 26,31
  #define MAXKEYWORDSIZE 30
  char	    KeyWord[MAXKEYWORDSIZE] = NULL;
  
  creadfile (save, eraseflg)
  char *save;
  int  eraseflg;

--- 26,32 -----
  #define MAXKEYWORDSIZE 30
  char	    KeyWord[MAXKEYWORDSIZE] = {NULL};
  
+ void
  creadfile (save, eraseflg)
  char *save;
  int  eraseflg;
***************
*** 97,102
      EvalAll();
  }
  
  cwritefile (fname, r0, c0, rn, cn)
  char *fname;
  int r0, c0, rn, cn;

--- 98,104 -----
      EvalAll();
  }
  
+ int
  cwritefile (fname, r0, c0, rn, cn)
  char *fname;
  int r0, c0, rn, cn;
*** 69/gram.y	Thu Oct  4 09:13:08 1990
--- gram.y	Fri Oct 26 16:57:41 1990
***************
*** 9,15
   *
   *		More mods by Alan Silverstein, 3/88, see list of changes.
   *
!  *		$Revision: 6.9 $
   */
  
  

--- 9,15 -----
   *
   *		More mods by Alan Silverstein, 3/88, see list of changes.
   *
!  *		$Revision: 6.10 $
   */
  
  
***************
*** 68,73
  %token S_HIDE
  %token S_SET
  
  %token K_FIXED
  %token K_SUM
  %token K_PROD

--- 68,75 -----
  %token S_HIDE
  %token S_SET
  
+ %token K_ERROR
+ %token K_INVALID
  %token K_FIXED
  %token K_SUM
  %token K_PROD
***************
*** 160,169
  				{ slet($2.left.vp, $4, -1); }
  	|	S_RIGHTSTRING var_or_range '=' e
  				{ slet($2.left.vp, $4, 1); }
! 	|	S_FORMAT COL ':' COL NUMBER NUMBER
! 				{ doformat($2,$4,$5,$6); }
! 	|	S_FORMAT COL NUMBER NUMBER
! 				{ doformat($2,$2,$3,$4); }
  	|	S_GET strarg	{  /* This tmp hack is because readfile
  				    * recurses back through yyparse. */
  				  char *tmp;

--- 162,175 -----
  				{ slet($2.left.vp, $4, -1); }
  	|	S_RIGHTSTRING var_or_range '=' e
  				{ slet($2.left.vp, $4, 1); }
! 	|	S_FORMAT COL ':' COL NUMBER NUMBER NUMBER
! 				{ doformat($2,$4,$5,$6,$7); }
! 	|	S_FORMAT COL NUMBER NUMBER NUMBER
! 				{ doformat($2,$2,$3,$4,$5); }
!         |       S_FORMAT COL ':' COL NUMBER NUMBER
!                                 { doformat($2,$4,$5,$6, 0); }
!         |       S_FORMAT COL NUMBER NUMBER
!                                 { doformat($2,$2,$3,$4, 0); }
  	|	S_GET strarg	{  /* This tmp hack is because readfile
  				    * recurses back through yyparse. */
  				  char *tmp;
***************
*** 228,235
  	|	S_FMT var_or_range STRING
  				{ format_cell($2.left.vp, $2.right.vp, $3); }
  	|	S_GOTO var_or_range {moveto($2.left.vp->row, $2.left.vp->col);}
! 	|       S_GOTO num          {num_search($2);}
! 	|       S_GOTO STRING       {str_search($2);}
  	|	S_GOTO              {go_last();}
  	|	S_DEFINE strarg       { struct ent_ptr arg1, arg2;
  					arg1.vp = lookat(showsr, showsc);

--- 234,242 -----
  	|	S_FMT var_or_range STRING
  				{ format_cell($2.left.vp, $2.right.vp, $3); }
  	|	S_GOTO var_or_range {moveto($2.left.vp->row, $2.left.vp->col);}
! 	|       S_GOTO num          {num_search($2, 0);}
! 	|       S_GOTO errlist
! 	|       S_GOTO STRING	    {str_search($2);}
  	|	S_GOTO              {go_last();}
  	|	S_DEFINE strarg       { struct ent_ptr arg1, arg2;
  					arg1.vp = lookat(showsr, showsc);
***************
*** 241,247
  	|	S_DEFINE strarg range { add_range($2, $3.left, $3.right, 1); }
  	|	S_DEFINE strarg var   { add_range($2, $3, $3, 0); }
  	|	S_UNDEFINE var_or_range { del_range($2.left.vp, $2.right.vp); }
!  	|	S_SET setlist
  	|	/* nothing */
  	|	error;
  

--- 248,254 -----
  	|	S_DEFINE strarg range { add_range($2, $3.left, $3.right, 1); }
  	|	S_DEFINE strarg var   { add_range($2, $3, $3, 0); }
  	|	S_UNDEFINE var_or_range { del_range($2.left.vp, $2.right.vp); }
!  	|	S_SET setitem
  	|	/* nothing */
  	|	error;
  
***************
*** 245,251
  	|	/* nothing */
  	|	error;
  
! term: 		var		{ $$ = new_var('v', $1); }
  	|	K_FIXED term	{ $$ = new ('f', ENULL, $2); }
  	|       '@' K_SUM '(' var_or_range ')' 
  				{ $$ = new_range(REDUCE | '+', $4); }

--- 252,258 -----
  	|	/* nothing */
  	|	error;
  
! term: 		var		{ $$ = new_var(O_VAR, $1); }
  	|	K_FIXED term	{ $$ = new ('f', ENULL, $2); }
  	|       '@' K_SUM '(' var_or_range ')' 
  				{ $$ = new_range(REDUCE | '+', $4); }
***************
*** 327,335
  	|	'(' e ')'	 { $$ = $2; }
  	|	'+' term	 { $$ = $2; }
  	|	'-' term	 { $$ = new ('m', ENULL, $2); }
! 	|	NUMBER		 { $$ = new_const('k', (double) $1); }
! 	|	FNUMBER		 { $$ = new_const('k', $1); }
! 	|	K_PI	{ $$ = new_const('k', (double)3.14159265358979323846); }
  	|	STRING	         { $$ = new_str($1); }
  	|	'~' term	 { $$ = new ('~', ENULL, $2); }
  	|	'!' term	 { $$ = new ('~', ENULL, $2); }

--- 334,342 -----
  	|	'(' e ')'	 { $$ = $2; }
  	|	'+' term	 { $$ = $2; }
  	|	'-' term	 { $$ = new ('m', ENULL, $2); }
! 	|	NUMBER		 { $$ = new_const(O_CONST, (double) $1); }
! 	|	FNUMBER		 { $$ = new_const(O_CONST, $1); }
! 	|	K_PI	{ $$ = new_const(O_CONST, (double)3.14159265358979323846); }
  	|	STRING	         { $$ = new_str($1); }
  	|	'~' term	 { $$ = new ('~', ENULL, $2); }
  	|	'!' term	 { $$ = new ('~', ENULL, $2); }
***************
*** 394,403
  				}
    	;
  
- setlist :	
- 	|	setlist setitem
- 	;
- 
  setitem	:	K_AUTO		{ setauto(1); }
  	|	K_AUTOCALC	{ setauto(1); }
  	|	'~' K_AUTO	{ setauto(0); }

--- 401,406 -----
  				}
    	;
  
  setitem	:	K_AUTO		{ setauto(1); }
  	|	K_AUTOCALC	{ setauto(1); }
  	|	'~' K_AUTO	{ setauto(0); }
***************
*** 425,427
  	|	K_RNDINFINITY		{ rndinfinity = 1; FullUpdate++;}
  	|	'!' K_RNDINFINITY	{ rndinfinity = 0; FullUpdate++;}
    	;

--- 428,434 -----
  	|	K_RNDINFINITY		{ rndinfinity = 1; FullUpdate++;}
  	|	'!' K_RNDINFINITY	{ rndinfinity = 0; FullUpdate++;}
    	;
+ 
+ errlist :	K_ERROR		{num_search((double)0, CELLERROR);}
+ 	|	K_INVALID	{num_search((double)0, CELLINVALID);}
+ 	;
*** 69/help.c	Thu Oct  4 09:14:19 1990
--- help.c	Fri Oct 26 16:57:44 1990
***************
*** 1,7
  /*
   * Help functions for sc 
   * R. Bond, 1988
!  * $Revision: 6.9 $
   */
  
  #include <curses.h>

--- 1,7 -----
  /*
   * Help functions for sc 
   * R. Bond, 1988
!  * $Revision: 6.10 $
   */
  
  #include <curses.h>
***************
*** 78,84
  "     b          Back then up to the previous valid cell.",
  "     w          Forward then down to the next valid cell.",
  "     g          Go to a cell.  Cell name, range name, quoted string,",
! "                or a number specify which cell.",
  (char *)0
  };
  

--- 78,84 -----
  "     b          Back then up to the previous valid cell.",
  "     w          Forward then down to the next valid cell.",
  "     g          Go to a cell.  Cell name, range name, quoted string,",
! "                a number, 'error', or 'invalid' to specify which cell.",
  (char *)0
  };
  
***************
*** 317,323
  "     @substr(se,e1,e2) Extract characters e1 through e2 from the",
  "                       string expression se.  For example,",
  "                       ``@substr(\"Nice jacket\" 4, 7)'' yields ",
! "                       ``e jac''.",
  "     @fmt(se,e)        Convert a number to a string using sprintf(3).",
  "                       For example,  ``@fmt(\"*%6.3f*\",10.5)'' yields",
  "                       ``*10.500*''.  Use formats are e, E, f, g, and G.", 

--- 317,323 -----
  "     @substr(se,e1,e2) Extract characters e1 through e2 from the",
  "                       string expression se.  For example,",
  "                       ``@substr(\"Nice jacket\" 4, 7)'' yields ",
! "                       ``e ja''.",
  "     @fmt(se,e)        Convert a number to a string using sprintf(3).",
  "                       For example,  ``@fmt(\"*%6.3f*\",10.5)'' yields",
  "                       ``*10.500*''.  Use formats are e, E, f, g, and G.", 
***************
*** 385,390
  "                       last full minute: 0 to 59.",
  (char *)0
  };
  void
  help()
  {

--- 385,393 -----
  "                       last full minute: 0 to 59.",
  (char *)0
  };
+ 
+ static	int	pscreen();
+ 
  void
  help()
  {
***************
*** 416,421
      (void) clrtobot();
  }
  
  pscreen(screen)
  char *screen[];
  {

--- 419,425 -----
      (void) clrtobot();
  }
  
+ static	int
  pscreen(screen)
  char *screen[];
  {
***************
*** 431,437
  	(void) clrtoeol();
      }
      (void) move(0,0);
!     (void) printw("Which Screen? [a-n, q]");
      (void) clrtoeol();
      (void) refresh();
      return(nmgetch());

--- 435,441 -----
  	(void) clrtoeol();
      }
      (void) move(0,0);
!     (void) printw("Which Screen? [a-o, q]");
      (void) clrtoeol();
      (void) refresh();
      return(nmgetch());
*** 69/interp.c	Thu Oct  4 09:17:13 1990
--- interp.c	Fri Oct 26 16:57:53 1990
***************
*** 7,13
   *
   *              More mods Robert Bond, 12/86
   *		More mods by Alan Silverstein, 3-4/88, see list of changes.
!  *		$Revision: 6.9 $
   */
  
  #define DEBUGDTS 1		/* REMOVE ME */

--- 7,13 -----
   *
   *              More mods Robert Bond, 12/86
   *		More mods by Alan Silverstein, 3-4/88, see list of changes.
!  *		$Revision: 6.10 $
   */
  
  #define DEBUGDTS 1		/* REMOVE ME */
***************
*** 11,17
   */
  
  #define DEBUGDTS 1		/* REMOVE ME */
- /* #define EXPRTREE	/* expr. dependency tree stuff, not ready yet */
  
  #ifdef aiws
  #undef _C_func			/* Fixes for undefined symbols on AIX */

--- 11,16 -----
   */
  
  #define DEBUGDTS 1		/* REMOVE ME */
  
  #ifdef aiws
  #undef _C_func			/* Fixes for undefined symbols on AIX */
***************
*** 57,62
      int quit();
  #endif
  
  /* Use this structure to save the the last 'g' command */
  
  struct go_save {

--- 56,65 -----
      int quit();
  #endif
  
+ /* Suffixes for engineering notation THA 9/19/88 */
+ extern char engmult[];
+ 
+ 
  /* Use this structure to save the the last 'g' command */
  
  struct go_save {
***************
*** 65,70
  	char *g_s;
  	int  g_row;
  	int  g_col;
  } gs;
  
  /* g_type can be: */

--- 68,74 -----
  	char *g_s;
  	int  g_row;
  	int  g_col;
+ 	int  errsearch;
  } gs;
  
  /* g_type can be: */
***************
*** 87,92
  double fn2_eval();
  struct	ent *firstev = (struct ent *)0;	/* first expr in the eval list */
  double	rint();
  
  #define PI (double)3.14159265358979323846
  #define dtr(x) ((x)*(PI/(double)180.0))

--- 91,97 -----
  double fn2_eval();
  struct	ent *firstev = (struct ent *)0;	/* first expr in the eval list */
  double	rint();
+ int	cellerror = CELLOK;	/* is there an error in this cell */
  
  #define PI (double)3.14159265358979323846
  #define dtr(x) ((x)*(PI/(double)180.0))
***************
*** 103,109
   	switch(fun)
   	{
   	case PV:
!  		answer = v1 * (1 - 1/p) / v2;
   		break;
   	case FV:
   		answer = v1 * (p - 1) / v2;

--- 108,119 -----
   	switch(fun)
   	{
   	case PV:
! 		if (v2)
! 			answer = v1 * (1 - 1/p) / v2;
! 		else
! 		{	cellerror = CELLERROR;
! 			answer = (double)0;
! 		}
   		break;
   	case FV:
  		if (v2)
***************
*** 106,112
   		answer = v1 * (1 - 1/p) / v2;
   		break;
   	case FV:
!  		answer = v1 * (p - 1) / v2;
   		break;
   	case PMT:
   		answer = v1 * v2 / (1 - 1/p);

--- 116,127 -----
  		}
   		break;
   	case FV:
! 		if (v2)
! 			answer = v1 * (p - 1) / v2;
! 		else
! 		{	cellerror = CELLERROR;
! 			answer = (double)0;
! 		}
   		break;
   	case PMT:
  		/* CHECK IF ~= 1 - 1/1 */
***************
*** 109,115
   		answer = v1 * (p - 1) / v2;
   		break;
   	case PMT:
!  		answer = v1 * v2 / (1 - 1/p);
   		break;
  	default:
  		error("Unknown function in finfunc");

--- 124,137 -----
  		}
   		break;
   	case PMT:
! 		/* CHECK IF ~= 1 - 1/1 */
! 		if (p && p != (double)1)
! 			answer = v1 * v2 / (1 - 1/p);
! 		else
! 		{	cellerror = CELLERROR;
! 			answer = (double)0;
! 		}
! 		
   		break;
  	default:
  		error("Unknown function in finfunc");
***************
*** 113,118
   		break;
  	default:
  		error("Unknown function in finfunc");
  		return((double)0);
  	}
  	return(answer);

--- 135,141 -----
   		break;
  	default:
  		error("Unknown function in finfunc");
+ 		cellerror = CELLERROR;
  		return((double)0);
  	}
  	return(answer);
***************
*** 141,146
  	    p = *ATBL(tbl, r, c);
      } else {
  	error ("range specified to @stindex");
  	return((char *)0);
      }
  

--- 164,170 -----
  	    p = *ATBL(tbl, r, c);
      } else {
  	error ("range specified to @stindex");
+ 	cellerror = CELLERROR;
  	return((char *)0);
      }
  
***************
*** 147,152
      if (p && p->label) {
  	pr = xmalloc((unsigned)(strlen(p->label)+1));
  	(void)strcpy(pr, p->label);
  	return (pr);
       } else
  	return((char *)0);

--- 171,178 -----
      if (p && p->label) {
  	pr = xmalloc((unsigned)(strlen(p->label)+1));
  	(void)strcpy(pr, p->label);
+ 	if (p->cellerror)
+ 		cellerror = CELLINVALID;
  	return (pr);
       } else
  	return((char *)0);
***************
*** 169,175
  	c = minc + x - 1;
  	if (c <= maxc && c >=minc 
  		&& (p = *ATBL(tbl, r, c)) && p->flags&is_valid )
! 					return p->v;
  	}
      else if ( minc == maxc ){ /* look down the column */
  	r = minr + x - 1;

--- 195,203 -----
  	c = minc + x - 1;
  	if (c <= maxc && c >=minc 
  		&& (p = *ATBL(tbl, r, c)) && p->flags&is_valid )
! 	{	if (p->cellerror)
! 			cellerror = CELLINVALID;
! 		return p->v;
  	}
      }
      else if ( minc == maxc ){ /* look down the column */
***************
*** 171,176
  		&& (p = *ATBL(tbl, r, c)) && p->flags&is_valid )
  					return p->v;
  	}
      else if ( minc == maxc ){ /* look down the column */
  	r = minr + x - 1;
  	if (r <= maxr && r >=minr 

--- 199,205 -----
  			cellerror = CELLINVALID;
  		return p->v;
  	}
+     }
      else if ( minc == maxc ){ /* look down the column */
  	r = minr + x - 1;
  	if (r <= maxr && r >=minr 
***************
*** 175,181
  	r = minr + x - 1;
  	if (r <= maxr && r >=minr 
  		&& (p = *ATBL(tbl, r, c)) && p->flags&is_valid )
! 					return p->v;
  	}
      else error(" range specified to @index");
      return v;

--- 204,212 -----
  	r = minr + x - 1;
  	if (r <= maxr && r >=minr 
  		&& (p = *ATBL(tbl, r, c)) && p->flags&is_valid )
! 	{	if (p->cellerror)
! 			cellerror = CELLINVALID;
! 		return p->v;
  	}
      }
      else {
***************
*** 177,183
  		&& (p = *ATBL(tbl, r, c)) && p->flags&is_valid )
  					return p->v;
  	}
!     else error(" range specified to @index");
      return v;
  }
  

--- 208,218 -----
  			cellerror = CELLINVALID;
  		return p->v;
  	}
!     }
!     else {
! 	error(" range specified to @index");
! 	cellerror = CELLERROR;
!     }
      return v;
  }
  
***************
*** 202,208
  		    fndc = incr ? (minc + offc) : c;
  		    if (ISVALID(fndr,fndc))
  			p = *ATBL(tbl, fndr, fndc);
! 		    else error(" range specified to @[hv]lookup");
  		    if ( p && p->flags&is_valid)
  			ret = p->v;
  		} else break;

--- 237,246 -----
  		    fndc = incr ? (minc + offc) : c;
  		    if (ISVALID(fndr,fndc))
  			p = *ATBL(tbl, fndr, fndc);
! 		    else {
! 			error(" range specified to @[hv]lookup");
! 			cellerror = CELLERROR;
! 		    }
  		    if ( p && p->flags&is_valid)
  		    {	if (p->cellerror)
  				cellerror = CELLINVALID;
***************
*** 204,209
  			p = *ATBL(tbl, fndr, fndc);
  		    else error(" range specified to @[hv]lookup");
  		    if ( p && p->flags&is_valid)
  			ret = p->v;
  		} else break;
  	    }

--- 242,249 -----
  			cellerror = CELLERROR;
  		    }
  		    if ( p && p->flags&is_valid)
+ 		    {	if (p->cellerror)
+ 				cellerror = CELLINVALID;
  			ret = p->v;
  		    }
  		} else break;
***************
*** 205,210
  		    else error(" range specified to @[hv]lookup");
  		    if ( p && p->flags&is_valid)
  			ret = p->v;
  		} else break;
  	    }
  	}

--- 245,251 -----
  		    {	if (p->cellerror)
  				cellerror = CELLINVALID;
  			ret = p->v;
+ 		    }
  		} else break;
  	    }
  	}
***************
*** 216,223
  		    fndr = incc ? (minr + offr) : r;
  		    fndc = incr ? (minc + offc) : c;
  		    if (ISVALID(fndr,fndc))
! 			p = *ATBL(tbl, fndr, fndc);
! 		    else error(" range specified to @[hv]lookup");
  		    break;
  		}
  	    }

--- 257,270 -----
  		    fndr = incc ? (minr + offr) : r;
  		    fndc = incr ? (minc + offc) : c;
  		    if (ISVALID(fndr,fndc))
! 		    {	p = *ATBL(tbl, fndr, fndc);
! 			if (p->cellerror)
! 				cellerror = CELLINVALID;
! 		    }
! 		    else {
! 			error(" range specified to @[hv]lookup");
! 			cellerror = CELLERROR;
! 		    }
  		    break;
  		}
  	    }
***************
*** 241,246
      for (r = minr; r<=maxr; r++)
  	for (c = minc; c<=maxc; c++)
  	    if ((p = *ATBL(tbl, r, c)) && p->flags&is_valid)
  		v++;
      return v;
  }

--- 288,295 -----
      for (r = minr; r<=maxr; r++)
  	for (c = minc; c<=maxc; c++)
  	    if ((p = *ATBL(tbl, r, c)) && p->flags&is_valid)
+ 	    {	if (p->cellerror)
+ 			cellerror = CELLINVALID;
  		v++;
  	    }
      return v;
***************
*** 242,247
  	for (c = minc; c<=maxc; c++)
  	    if ((p = *ATBL(tbl, r, c)) && p->flags&is_valid)
  		v++;
      return v;
  }
  

--- 291,297 -----
  	    {	if (p->cellerror)
  			cellerror = CELLINVALID;
  		v++;
+ 	    }
      return v;
  }
  
***************
*** 257,262
      for (r = minr; r<=maxr; r++)
  	for (c = minc; c<=maxc; c++)
  	    if ((p = *ATBL(tbl, r, c)) && p->flags&is_valid)
  		v += p->v;
      return v;
  }

--- 307,314 -----
      for (r = minr; r<=maxr; r++)
  	for (c = minc; c<=maxc; c++)
  	    if ((p = *ATBL(tbl, r, c)) && p->flags&is_valid)
+ 	    {	if (p->cellerror)
+ 			cellerror = CELLINVALID;
  		v += p->v;
  	    }
      return v;
***************
*** 258,263
  	for (c = minc; c<=maxc; c++)
  	    if ((p = *ATBL(tbl, r, c)) && p->flags&is_valid)
  		v += p->v;
      return v;
  }
  

--- 310,316 -----
  	    {	if (p->cellerror)
  			cellerror = CELLINVALID;
  		v += p->v;
+ 	    }
      return v;
  }
  
***************
*** 273,278
      for (r = minr; r<=maxr; r++)
  	for (c = minc; c<=maxc; c++)
  	    if ((p = *ATBL(tbl, r, c)) && p->flags&is_valid)
  		v *= p->v;
      return v;
  }

--- 326,333 -----
      for (r = minr; r<=maxr; r++)
  	for (c = minc; c<=maxc; c++)
  	    if ((p = *ATBL(tbl, r, c)) && p->flags&is_valid)
+ 	    {	if (p->cellerror)
+ 			cellerror = CELLINVALID;
  		v *= p->v;
  	    }
      return v;
***************
*** 274,279
  	for (c = minc; c<=maxc; c++)
  	    if ((p = *ATBL(tbl, r, c)) && p->flags&is_valid)
  		v *= p->v;
      return v;
  }
  

--- 329,335 -----
  	    {	if (p->cellerror)
  			cellerror = CELLINVALID;
  		v *= p->v;
+ 	    }
      return v;
  }
  
***************
*** 290,295
      for (r = minr; r<=maxr; r++)
  	for (c = minc; c<=maxc; c++)
  	    if ((p = *ATBL(tbl, r, c)) && p->flags&is_valid) {
  		v += p->v;
  		count++;
  	    }

--- 346,354 -----
      for (r = minr; r<=maxr; r++)
  	for (c = minc; c<=maxc; c++)
  	    if ((p = *ATBL(tbl, r, c)) && p->flags&is_valid) {
+ 		if (p->cellerror)
+ 			cellerror = CELLINVALID;
+ 
  		v += p->v;
  		count++;
  	    }
***************
*** 314,319
      for (r = minr; r<=maxr; r++)
  	for (c = minc; c<=maxc; c++)
  	    if ((p = *ATBL(tbl, r, c)) && p->flags&is_valid) {
  		v = p->v;
  		lp += v*v;
  		rp += v;

--- 373,381 -----
      for (r = minr; r<=maxr; r++)
  	for (c = minc; c<=maxc; c++)
  	    if ((p = *ATBL(tbl, r, c)) && p->flags&is_valid) {
+ 		if (p->cellerror)
+ 			cellerror = CELLINVALID;
+ 
  		v = p->v;
  		lp += v*v;
  		rp += v;
***************
*** 338,343
      for (r = minr; r<=maxr; r++)
  	for (c = minc; c<=maxc; c++)
  	    if ((p = *ATBL(tbl, r, c)) && p->flags&is_valid) {
  		if (!count) {
  		    v = p->v;
  		    count++;

--- 400,408 -----
      for (r = minr; r<=maxr; r++)
  	for (c = minc; c<=maxc; c++)
  	    if ((p = *ATBL(tbl, r, c)) && p->flags&is_valid) {
+ 		if (p->cellerror)
+ 			cellerror = CELLINVALID;
+ 
  		if (!count) {
  		    v = p->v;
  		    count++;
***************
*** 363,368
      for (r = minr; r<=maxr; r++)
  	for (c = minc; c<=maxc; c++)
  	    if ((p = *ATBL(tbl, r, c)) && p->flags&is_valid) {
  		if (!count) {
  		    v = p->v;
  		    count++;

--- 428,436 -----
      for (r = minr; r<=maxr; r++)
  	for (c = minc; c<=maxc; c++)
  	    if ((p = *ATBL(tbl, r, c)) && p->flags&is_valid) {
+ 		if (p->cellerror)
+ 			cellerror = CELLINVALID;
+ 
  		if (!count) {
  		    v = p->v;
  		    count++;
***************
*** 397,402
      if (mo < 1 || mo > 12 || day < 1 || day > mdays[--mo] ||
  		yr > 1999 || yr < 1970) {
  	error("@dts: invalid argument");
  	return(0.0);
      }
  

--- 465,471 -----
      if (mo < 1 || mo > 12 || day < 1 || day > mdays[--mo] ||
  		yr > 1999 || yr < 1970) {
  	error("@dts: invalid argument");
+ 	cellerror = CELLERROR;
  	return(0.0);
      }
  
***************
*** 436,442
      tp = localtime(&trial);
      if (tp->tm_mday + tp->tm_hour + tp->tm_min + tp->tm_sec + 
  	tp->tm_year + tp->tm_mon != yr+mo+day)
! 		error("Dts broke down");
  #endif
  
      return ((double)trial);

--- 505,513 -----
      tp = localtime(&trial);
      if (tp->tm_mday + tp->tm_hour + tp->tm_min + tp->tm_sec + 
  	tp->tm_year + tp->tm_mon != yr+mo+day)
! 	{	error("Dts broke down");
! 		cellerror = CELLERROR;
! 	}
  #endif
  
      return ((double)trial);
***************
*** 448,453
  {
      if (hr < 0 || hr > 23 || min < 0 || min > 59 || sec < 0 || sec > 59) {
  	error ("@tts: Invalid argument");
  	return ((double)0);
      }
      return ((double)(sec+min*60+hr*3600));

--- 519,525 -----
  {
      if (hr < 0 || hr > 23 || min < 0 || min > 59 || sec < 0 || sec > 59) {
  	error ("@tts: Invalid argument");
+ 	cellerror = CELLERROR;
  	return ((double)0);
      }
      return ((double)(sec+min*60+hr*3600));
***************
*** 487,492
  	    case YEAR: return((double)(tm_cache.tm_year));
  	}
  	/* Safety net */
  	return ((double)0);
  }
  

--- 559,565 -----
  	    case YEAR: return((double)(tm_cache.tm_year));
  	}
  	/* Safety net */
+ 	cellerror = CELLERROR;
  	return ((double)0);
  }
  
***************
*** 544,550
  {
      int collen;		/* length of string */
      int row, col;	/* integer values   */
!     struct ent *ep = (struct ent *)0;	/* selected entry   */
  
      if (((row = (int) floor (rowdoub)) >= 0)
       && (row < maxrows)				/* in range */

--- 617,623 -----
  {
      int collen;		/* length of string */
      int row, col;	/* integer values   */
!     struct ent *p = (struct ent *)0;	/* selected entry   */
  
      if (((row = (int) floor (rowdoub)) >= 0)
       && (row < maxrows)				/* in range */
***************
*** 552,558
       && ((col = atocol (colstr, collen)) >= 0)
       && (col < maxcols))			/* in range */
      {
! 	ep = *ATBL(tbl, row, col);
      }
  
      xfree (colstr);

--- 625,633 -----
       && ((col = atocol (colstr, collen)) >= 0)
       && (col < maxcols))			/* in range */
      {
! 	p = *ATBL(tbl, row, col);
! 	if (p->cellerror)
! 		cellerror = CELLINVALID;
      }
  
      xfree (colstr);
***************
*** 556,562
      }
  
      xfree (colstr);
!     return (ep);
  }
  
  

--- 631,637 -----
      }
  
      xfree (colstr);
!     return (p);
  }
  
  
***************
*** 590,595
  	register double maxval = 0; /* Assignment to shut up lint */
  	register struct enode *p;
  	register double v;
  
  	for (p = ep; p; p = p->e.o.left) {
  		v = eval(p->e.o.right);

--- 665,671 -----
  	register double maxval = 0; /* Assignment to shut up lint */
  	register struct enode *p;
  	register double v;
+ 	int	lcellerror = 0;	/* if any error occurs return so */
  
  	for (p = ep; p; p = p->e.o.left) {
  		v = eval(p->e.o.right);
***************
*** 593,598
  
  	for (p = ep; p; p = p->e.o.left) {
  		v = eval(p->e.o.right);
  		if (!count || v > maxval) {
  			maxval = v; count++;
  		}

--- 669,676 -----
  
  	for (p = ep; p; p = p->e.o.left) {
  		v = eval(p->e.o.right);
+ 		if (cellerror)
+ 			lcellerror++;
  		if (!count || v > maxval) {
  			maxval = v; count++;
  		}
***************
*** 597,602
  			maxval = v; count++;
  		}
  	}
  	if (count) return maxval;
  	else return (double)0;
  }

--- 675,682 -----
  			maxval = v; count++;
  		}
  	}
+ 	if (lcellerror)
+ 		cellerror = CELLINVALID;
  	if (count) return maxval;
  	else return (double)0;
  }
***************
*** 609,614
  	register double minval = 0; /* Assignment to shut up lint */
  	register struct enode *p;
  	register double v;
  
  	for (p = ep; p; p = p->e.o.left) {
  		v = eval(p->e.o.right);

--- 689,695 -----
  	register double minval = 0; /* Assignment to shut up lint */
  	register struct enode *p;
  	register double v;
+ 	int	lcellerror = 0;	/* if any error occurs return so */
  
  	for (p = ep; p; p = p->e.o.left) {
  		v = eval(p->e.o.right);
***************
*** 612,617
  
  	for (p = ep; p; p = p->e.o.left) {
  		v = eval(p->e.o.right);
  		if (!count || v < minval) {
  			minval = v; count++;
  		}

--- 693,700 -----
  
  	for (p = ep; p; p = p->e.o.left) {
  		v = eval(p->e.o.right);
+ 		if (cellerror)
+ 			lcellerror++;
  		if (!count || v < minval) {
  			minval = v; count++;
  		}
***************
*** 616,621
  			minval = v; count++;
  		}
  	}
  	if (count) return minval;
  	else return (double)0;
  }

--- 699,706 -----
  			minval = v; count++;
  		}
  	}
+ 	if (lcellerror)
+ 		cellerror = CELLINVALID;
  	if (count) return minval;
  	else return (double)0;
  }
***************
*** 625,630
  register struct enode *e;
  {
      if (e == (struct enode *)0) return (double)0;
      switch (e->op) {
  	case '+':	return (eval(e->e.o.left) + eval(e->e.o.right));
  	case '-':	return (eval(e->e.o.left) - eval(e->e.o.right));

--- 710,716 -----
  register struct enode *e;
  {
      if (e == (struct enode *)0) return (double)0;
+     cellerror = CELLOK;
      switch (e->op) {
  	case '+':	return (eval(e->e.o.left) + eval(e->e.o.right));
  	case '-':	return (eval(e->e.o.left) - eval(e->e.o.right));
***************
*** 629,635
  	case '+':	return (eval(e->e.o.left) + eval(e->e.o.right));
  	case '-':	return (eval(e->e.o.left) - eval(e->e.o.right));
  	case '*':	return (eval(e->e.o.left) * eval(e->e.o.right));
! 	case '/':       return (eval(e->e.o.left) / eval(e->e.o.right));
  	case '%':     {	double num, denom;
  			num = floor(eval(e->e.o.left));
  			denom = floor(eval (e->e.o.right));

--- 715,730 -----
  	case '+':	return (eval(e->e.o.left) + eval(e->e.o.right));
  	case '-':	return (eval(e->e.o.left) - eval(e->e.o.right));
  	case '*':	return (eval(e->e.o.left) * eval(e->e.o.right));
! 	case '/':     { double num, denom;
! 			num = eval(e->e.o.left);
! 			denom = eval(e->e.o.right);
! 			if (denom)
! 				return(num/denom);
! 			else
! 			{	cellerror = CELLERROR;
! 				return((double) 0);
! 			}
! 	}
  	case '%':     {	double num, denom;
  			num = floor(eval(e->e.o.left));
  			denom = floor(eval (e->e.o.right));
***************
*** 633,639
  	case '%':     {	double num, denom;
  			num = floor(eval(e->e.o.left));
  			denom = floor(eval (e->e.o.right));
! 			return denom ? num - floor(num/denom)*denom : (double)0; }
  	case '^':	return (fn2_eval(pow,eval(e->e.o.left),eval(e->e.o.right)));
  	case '<':	return (eval(e->e.o.left) < eval(e->e.o.right));
  	case '=':	return (eval(e->e.o.left) == eval(e->e.o.right));

--- 728,740 -----
  	case '%':     {	double num, denom;
  			num = floor(eval(e->e.o.left));
  			denom = floor(eval (e->e.o.right));
! 			if (denom)
! 				return(num - floor(num/denom)*denom);
! 			else
! 			{	cellerror = CELLERROR;
! 				return((double) 0);
! 			}
! 	}
  	case '^':	return (fn2_eval(pow,eval(e->e.o.left),eval(e->e.o.right)));
  	case '<':	return (eval(e->e.o.left) < eval(e->e.o.right));
  	case '=':	return (eval(e->e.o.left) == eval(e->e.o.right));
***************
*** 646,653
  	case 'm':	return (-eval(e->e.o.right));
  	case 'f':	return (eval(e->e.o.right));
  	case '~':	return (eval(e->e.o.right) == 0.0);
! 	case 'k':	return (e->e.k);
! 	case 'v':	return (e->e.v.vp->v);
  	case INDEX:
  	case LOOKUP:
  	case HLOOKUP:

--- 747,756 -----
  	case 'm':	return (-eval(e->e.o.right));
  	case 'f':	return (eval(e->e.o.right));
  	case '~':	return (eval(e->e.o.right) == 0.0);
! 	case O_CONST:	return (e->e.k);
! 	case O_VAR:	if (e->e.v.vp->cellerror)
! 				cellerror = CELLINVALID;
! 			return (e->e.v.vp->v);
  	case INDEX:
  	case LOOKUP:
  	case HLOOKUP:
***************
*** 772,777
  	default:	 error ("Illegal numeric expression");
  			 exprerr = 1;
      }
      return((double)0.0);
  }
  

--- 875,881 -----
  	default:	 error ("Illegal numeric expression");
  			 exprerr = 1;
      }
+     cellerror = CELLERROR;
      return((double)0.0);
  }
  
***************
*** 777,782
  
  #ifdef SIGVOID
  void
  #endif
  eval_fpe(signo) /* Trap for FPE errors in eval */
  int signo;

--- 881,888 -----
  
  #ifdef SIGVOID
  void
+ #else
+ int
  #endif
  eval_fpe(signo) /* Trap for FPE errors in eval */
  int signo;
***************
*** 781,786
  eval_fpe(signo) /* Trap for FPE errors in eval */
  int signo;
  {
  #ifdef IEEE_MATH
  	(void)fpsetsticky((fp_except)0); 		/* Clear exception */
  #endif /* IEEE_MATH */

--- 887,896 -----
  eval_fpe(signo) /* Trap for FPE errors in eval */
  int signo;
  {
+ #ifdef i386
+ 	asm("	fnclex");
+ 	asm("	fwait");
+ #else
  #ifdef IEEE_MATH
  	(void)fpsetsticky((fp_except)0);	/* Clear exception */
  #endif /* IEEE_MATH */
***************
*** 782,788
  int signo;
  {
  #ifdef IEEE_MATH
! 	(void)fpsetsticky((fp_except)0); 		/* Clear exception */
  #endif /* IEEE_MATH */
  	longjmp(fpe_save, 1);
  }

--- 892,898 -----
  	asm("	fwait");
  #else
  #ifdef IEEE_MATH
! 	(void)fpsetsticky((fp_except)0);	/* Clear exception */
  #endif /* IEEE_MATH */
  #endif
  	longjmp(fpe_save, 1);
***************
*** 784,789
  #ifdef IEEE_MATH
  	(void)fpsetsticky((fp_except)0); 		/* Clear exception */
  #endif /* IEEE_MATH */
  	longjmp(fpe_save, 1);
  }
  

--- 894,900 -----
  #ifdef IEEE_MATH
  	(void)fpsetsticky((fp_except)0);	/* Clear exception */
  #endif /* IEEE_MATH */
+ #endif
  	longjmp(fpe_save, 1);
  }
  
***************
*** 795,802
  	errno = 0;
  	res = (*fn)(arg);
  	if(errno)
! 	  eval_fpe(0);
! 
  	return res;
  }
  

--- 906,914 -----
  	errno = 0;
  	res = (*fn)(arg);
  	if(errno)
! 	{	cellerror = CELLERROR;
! 		eval_fpe(0);
! 	}
  	return res;
  }
  
***************
*** 807,814
  	double res;
  	errno = 0;
  	res = (*fn)(arg1, arg2);
! 	if(errno) 
! 	    eval_fpe(0);
  
  	return res;
  }

--- 919,928 -----
  	double res;
  	errno = 0;
  	res = (*fn)(arg1, arg2);
! 	if(errno)
! 	{	cellerror = CELLERROR;
! 		eval_fpe(0);
! 	}
  
  	return res;
  }
***************
*** 890,895
  double value;
  {
      error("Warning: External functions unavailable on VMS");
      if (command)
  	xfree(command);
      return (strcpy (xmalloc((unsigned) 1), "\0"));

--- 1004,1010 -----
  double value;
  {
      error("Warning: External functions unavailable on VMS");
+     cellerror = CELLERROR	/* not sure if this should be a cellerror */
      if (command)
  	xfree(command);
      return (strcpy (xmalloc((unsigned) 1), "\0"));
***************
*** 920,925
  
  	if ((! command) || (! *command)) {
  	    error ("Warning: external function given null command name");
  	    if (command) xfree (command);
  	} else {
  	    FILE *pp;

--- 1035,1041 -----
  
  	if ((! command) || (! *command)) {
  	    error ("Warning: external function given null command name");
+ 	    cellerror = CELLERROR;
  	    if (command) xfree (command);
  	} else {
  	    FILE *pp;
***************
*** 930,936
  	    error ("Running external function...");
  	    (void) refresh();
  
! 	    if ((pp = popen (buff, "r")) == (FILE *) NULL)	/* run it */
  		error ("Warning: running \"%s\" failed", buff);
  	    else {
  		if (fgets (buff, sizeof(buff)-1, pp) == NULL)	/* one line */

--- 1046,1052 -----
  	    error ("Running external function...");
  	    (void) refresh();
  
! 	    if ((pp = popen (buff, "r")) == (FILE *) NULL) {	/* run it */
  		error ("Warning: running \"%s\" failed", buff);
  		cellerror = CELLERROR;
  	    }
***************
*** 932,937
  
  	    if ((pp = popen (buff, "r")) == (FILE *) NULL)	/* run it */
  		error ("Warning: running \"%s\" failed", buff);
  	    else {
  		if (fgets (buff, sizeof(buff)-1, pp) == NULL)	/* one line */
  		    error ("Warning: external function returned nothing");

--- 1048,1055 -----
  
  	    if ((pp = popen (buff, "r")) == (FILE *) NULL) {	/* run it */
  		error ("Warning: running \"%s\" failed", buff);
+ 		cellerror = CELLERROR;
+ 	    }
  	    else {
  		if (fgets (buff, sizeof(buff)-1, pp) == NULL)	/* one line */
  		    error ("Warning: external function returned nothing");
***************
*** 1020,1025
      register char *p;
  
      if (se == (struct enode *)0) return (char *)0;
      switch (se->op) {
  	case O_SCONST: p = xmalloc((unsigned)(strlen(se->e.s)+1));
  		     (void) strcpy(p, se->e.s);

--- 1138,1144 -----
      register char *p;
  
      if (se == (struct enode *)0) return (char *)0;
+     cellerror = CELLOK;
      switch (se->op) {
  	case O_SCONST: p = xmalloc((unsigned)(strlen(se->e.s)+1));
  		     (void) strcpy(p, se->e.s);
***************
*** 1109,1118
      register struct ent *p;
  
      (void) signal(SIGFPE, eval_fpe);
- #ifdef EXPRTREE
-     for (p = firstev; p; p = p->evnext)
- 	    RealEvalOne(p, &chgct);
- #else
      if(calc_order == BYROWS ) {
  	for (i=0; i<=maxrow; i++)
  	    for (j=0; j<=maxcol; j++)

--- 1228,1233 -----
      register struct ent *p;
  
      (void) signal(SIGFPE, eval_fpe);
      if(calc_order == BYROWS ) {
  	for (i=0; i<=maxrow; i++)
  	    for (j=0; j<=maxcol; j++)
***************
*** 1125,1131
  	}
      }
      else error("Internal error calc_order");
- #endif
   
      (void) signal(SIGFPE, quit);
      return(chgct);

--- 1240,1245 -----
  	}
      }
      else error("Internal error calc_order");
   
      (void) signal(SIGFPE, quit);
      return(chgct);
***************
*** 1132,1142
  }
  
  void
- #ifdef EXPRTREE
- RealEvalOne(p, chgct)
- register struct ent *p;
- int *chgct;
- #else
  RealEvalOne(p, i, j, chgct)
  register struct ent *p;
  int i, j, *chgct;

--- 1246,1251 -----
  }
  
  void
  RealEvalOne(p, i, j, chgct)
  register struct ent *p;
  int i, j, *chgct;
***************
*** 1140,1146
  RealEvalOne(p, i, j, chgct)
  register struct ent *p;
  int i, j, *chgct;
- #endif
  {
  	if (p->flags & is_strexpr) {
  	    char *v;

--- 1249,1254 -----
  RealEvalOne(p, i, j, chgct)
  register struct ent *p;
  int i, j, *chgct;
  {
  	(void) signal(SIGFPE, eval_fpe);
  	if (p->flags & is_strexpr) {
***************
*** 1142,1147
  int i, j, *chgct;
  #endif
  {
  	if (p->flags & is_strexpr) {
  	    char *v;
  	    if (setjmp(fpe_save)) {

--- 1250,1256 -----
  register struct ent *p;
  int i, j, *chgct;
  {
+ 	(void) signal(SIGFPE, eval_fpe);
  	if (p->flags & is_strexpr) {
  	    char *v;
  	    if (setjmp(fpe_save)) {
***************
*** 1145,1153
  	if (p->flags & is_strexpr) {
  	    char *v;
  	    if (setjmp(fpe_save)) {
- #ifdef EXPRTREE
- 		error("Floating point exception %s", v_name(p->row, p->col));
- #else
  		error("Floating point exception %s", v_name(i, j));
  #endif
  		v = "";

--- 1254,1259 -----
  	if (p->flags & is_strexpr) {
  	    char *v;
  	    if (setjmp(fpe_save)) {
  		error("Floating point exception %s", v_name(i, j));
  		cellerror = CELLERROR;
  		v = "";
***************
*** 1149,1155
  		error("Floating point exception %s", v_name(p->row, p->col));
  #else
  		error("Floating point exception %s", v_name(i, j));
! #endif
  		v = "";
  	    } else {
  		v = seval(p->expr);

--- 1255,1261 -----
  	    char *v;
  	    if (setjmp(fpe_save)) {
  		error("Floating point exception %s", v_name(i, j));
! 		cellerror = CELLERROR;
  		v = "";
  	    } else {
  		v = seval(p->expr);
***************
*** 1154,1159
  	    } else {
  		v = seval(p->expr);
  	    }
  	    if (!v && !p->label) /* Everything's fine */
  		return;
  	    if (!p->label || !v || strcmp(v, p->label) != 0) {

--- 1260,1266 -----
  	    } else {
  		v = seval(p->expr);
  	    }
+ 	    p->cellerror = cellerror;
  	    if (!v && !p->label) /* Everything's fine */
  		return;
  	    if (!p->label || !v || strcmp(v, p->label) != 0) {
***************
*** 1167,1175
  	} else {
  	    double v;
  	    if (setjmp(fpe_save)) {
- #ifdef EXPRTREE
- 		error("Floating point exception %s", v_name(p->row, p->col));
- #else
  		error("Floating point exception %s", v_name(i, j));
  #endif
  		v = (double)0.0;

--- 1274,1279 -----
  	} else {
  	    double v;
  	    if (setjmp(fpe_save)) {
  		error("Floating point exception %s", v_name(i, j));
  		cellerror = CELLERROR;
  		v = (double)0.0;
***************
*** 1171,1177
  		error("Floating point exception %s", v_name(p->row, p->col));
  #else
  		error("Floating point exception %s", v_name(i, j));
! #endif
  		v = (double)0.0;
  	    } else {
  		v = eval (p->expr);

--- 1275,1281 -----
  	    double v;
  	    if (setjmp(fpe_save)) {
  		error("Floating point exception %s", v_name(i, j));
! 		cellerror = CELLERROR;
  		v = (double)0.0;
  	    } else {
  		v = eval (p->expr);
***************
*** 1176,1181
  	    } else {
  		v = eval (p->expr);
  	    }
  	    if (v != p->v) {
  		p->v = v; (*chgct)++;
  		p->flags |= is_changed|is_valid;

--- 1280,1286 -----
  	    } else {
  		v = eval (p->expr);
  	    }
+ 	    p->cellerror = cellerror;
  	    if (v != p->v) {
  		p->v = v; (*chgct)++;
  		p->flags |= is_changed|is_valid;
***************
*** 1333,1338
      default: break;
      }
      gs.g_type = G_NONE;
  }
  
  void

--- 1438,1444 -----
      default: break;
      }
      gs.g_type = G_NONE;
+     gs.errsearch = 0;
  }
  
  void
***************
*** 1342,1348
      case G_NONE:
  		error("Nothing to repeat"); break;
      case G_NUM:
! 		num_search(gs.g_n);
  		break;
      case  G_CELL:
  		moveto(gs.g_row, gs.g_col);

--- 1448,1454 -----
      case G_NONE:
  		error("Nothing to repeat"); break;
      case G_NUM:
! 		num_search(gs.g_n, gs.errsearch);
  		break;
      case  G_CELL:
  		moveto(gs.g_row, gs.g_col);
***************
*** 1369,1375
  }
  
  void
! num_search(n)
  double n;
  {
      register struct ent *p;

--- 1475,1481 -----
  }
  
  void
! num_search(n, errsearch)
  double n;
  int	errsearch;
  {
***************
*** 1371,1376
  void
  num_search(n)
  double n;
  {
      register struct ent *p;
      register int r,c;

--- 1477,1483 -----
  void
  num_search(n, errsearch)
  double n;
+ int	errsearch;
  {
      register struct ent *p;
      register int r,c;
***************
*** 1379,1384
      g_free();
      gs.g_type = G_NUM;
      gs.g_n = n;
  
      if (currow > maxrow)
  	endr = maxrow ? maxrow-1 : 0;

--- 1486,1492 -----
      g_free();
      gs.g_type = G_NUM;
      gs.g_n = n;
+     gs.errsearch = errsearch;
  
      if (currow > maxrow)
  	endr = maxrow ? maxrow-1 : 0;
***************
*** 1403,1409
  	    }
  	}
  	if (r == endr && c == endc) {
! 	    error("Number not found");
  	    return;
  	}
  	p = *ATBL(tbl, r, c);

--- 1511,1521 -----
  	    }
  	}
  	if (r == endr && c == endc) {
! 	    if (errsearch)
! 		error("no %s cell found", errsearch == CELLERROR ? "ERROR" :
! 		      "INVALID");
! 	    else
! 		error("Number not found");
  	    return;
  	}
  	p = *ATBL(tbl, r, c);
***************
*** 1407,1414
  	    return;
  	}
  	p = *ATBL(tbl, r, c);
!     } while(col_hidden[c] || !p || p && (!(p->flags & is_valid) 
!                                         || (p->flags&is_valid) && p->v != n));
      currow = r;
      curcol = c;
  }

--- 1519,1529 -----
  	    return;
  	}
  	p = *ATBL(tbl, r, c);
!     } while (col_hidden[c] || !p || !(p->flags & is_valid)
! 	|| (!errsearch && (p->v != n))
! 	|| (errsearch && !((p->cellerror == errsearch) ||
! 		(p->cellerror == errsearch))));	/* CELLERROR vs CELLINVALID */
! 		
      currow = r;
      curcol = c;
  }
***************
*** 1432,1437
  #if defined(SYSV2) || defined(SYSV3)
      if ((tmp = regcmp(s, (char *)0)) == (char *)0) {
  	xfree(s);
  	error("Invalid search string");
  	return;
      }

--- 1547,1553 -----
  #if defined(SYSV2) || defined(SYSV3)
      if ((tmp = regcmp(s, (char *)0)) == (char *)0) {
  	xfree(s);
+ 	cellerror = CELLERROR;
  	error("Invalid search string");
  	return;
      }
***************
*** 1469,1475
  	    return;
  	}
  	p = *ATBL(tbl, r, c);
!     } while(col_hidden[c] || !p || p && (!(p->label) 
  #if defined(BSD42) || defined(BSD43)
  		  			|| (re_exec(p->label) == 0)));
  #else

--- 1585,1591 -----
  	    return;
  	}
  	p = *ATBL(tbl, r, c);
!     } while(col_hidden[c] || !p || !(p->label)
  #if defined(BSD42) || defined(BSD43)
  		  			|| (re_exec(p->label) == 0));
  #else
***************
*** 1471,1477
  	p = *ATBL(tbl, r, c);
      } while(col_hidden[c] || !p || p && (!(p->label) 
  #if defined(BSD42) || defined(BSD43)
! 		  			|| (re_exec(p->label) == 0)));
  #else
  #if defined(SYSV2) || defined(SYSV3)
                                         || (regex(tmp, p->label) == (char *)0)));

--- 1587,1593 -----
  	p = *ATBL(tbl, r, c);
      } while(col_hidden[c] || !p || !(p->label)
  #if defined(BSD42) || defined(BSD43)
! 		  			|| (re_exec(p->label) == 0));
  #else
  #if defined(SYSV2) || defined(SYSV3)
  				|| (regex(tmp, p->label) == (char *)0));
***************
*** 1474,1480
  		  			|| (re_exec(p->label) == 0)));
  #else
  #if defined(SYSV2) || defined(SYSV3)
!                                        || (regex(tmp, p->label) == (char *)0)));
  #else
                                         || (strcmp(s, p->label) != 0)));
  #endif

--- 1590,1596 -----
  		  			|| (re_exec(p->label) == 0));
  #else
  #if defined(SYSV2) || defined(SYSV3)
! 				|| (regex(tmp, p->label) == (char *)0));
  #else
  					|| (strcmp(s, p->label) != 0));
  #endif
***************
*** 1476,1482
  #if defined(SYSV2) || defined(SYSV3)
                                         || (regex(tmp, p->label) == (char *)0)));
  #else
!                                        || (strcmp(s, p->label) != 0)));
  #endif
  #endif
      currow = r;

--- 1592,1598 -----
  #if defined(SYSV2) || defined(SYSV3)
  				|| (regex(tmp, p->label) == (char *)0));
  #else
! 					|| (strcmp(s, p->label) != 0));
  #endif
  #endif
      currow = r;
***************
*** 1537,1542
  struct enode *e;
  {
      double val;
  
      exprerr = 0;
      (void) signal(SIGFPE, eval_fpe);

--- 1653,1659 -----
  struct enode *e;
  {
      double val;
+     unsigned isconstant = constant(e);
  
      if (loading && !isconstant)
  	val = (double)0.0;
***************
*** 1538,1547
  {
      double val;
  
!     exprerr = 0;
!     (void) signal(SIGFPE, eval_fpe);
!     if (setjmp(fpe_save)) {
! 	error ("Floating point exception in cell %s", v_name(v->row, v->col));
  	val = (double)0.0;
      } else {
  	val = eval(e);

--- 1655,1661 -----
      double val;
      unsigned isconstant = constant(e);
  
!     if (loading && !isconstant)
  	val = (double)0.0;
      else
      {
***************
*** 1543,1550
      if (setjmp(fpe_save)) {
  	error ("Floating point exception in cell %s", v_name(v->row, v->col));
  	val = (double)0.0;
!     } else {
! 	val = eval(e);
      }
      (void) signal(SIGFPE, quit);
      if (exprerr) {

--- 1657,1679 -----
  
      if (loading && !isconstant)
  	val = (double)0.0;
!     else
!     {
! 	exprerr = 0;
! 	(void) signal(SIGFPE, eval_fpe);
! 	if (setjmp(fpe_save)) {
! 	    error ("Floating point exception in cell %s", v_name(v->row, v->col));
! 	    val = (double)0.0;
! 	    cellerror = CELLERROR;
! 	} else {
! 	    val = eval(e);
! 	}
! 	v->cellerror = cellerror;
! 	(void) signal(SIGFPE, quit);
! 	if (exprerr) {
! 	    efree((struct ent *)0, e);
! 	    return;
! 	}
      }
  
      if (isconstant) {
***************
*** 1546,1561
      } else {
  	val = eval(e);
      }
!     (void) signal(SIGFPE, quit);
!     if (exprerr) {
! 	efree((struct ent *)0, e);
! 	return;
!     }
!     if (constant(e)) {
! 	if (!loading)
! 	    v->v = val * prescale;
! 	else
! 	    v->v = val;
  	if (!(v->flags & is_strexpr)) {
              efree(v, v->expr);
  	    v->expr = (struct enode *)0;

--- 1675,1686 -----
  	    return;
  	}
      }
! 
!     if (isconstant) {
! 	if (!loading && prescale < (double)0.9999999)
! 	    val *= prescale;
! 	v->v = val;
! 
  	if (!(v->flags & is_strexpr)) {
              efree(v, v->expr);
  	    v->expr = (struct enode *)0;
***************
*** 1561,1570
  	    v->expr = (struct enode *)0;
  	}
  	efree((struct ent *)0, e);
-         v->flags |= (is_changed|is_valid);
-         changed++;
-         modflg++;
- 	return;
      }
      efree (v, v->expr);
      v->expr = e;

--- 1686,1691 -----
  	    v->expr = (struct enode *)0;
  	}
  	efree((struct ent *)0, e);
      }
      else
      {
***************
*** 1566,1575
          modflg++;
  	return;
      }
!     efree (v, v->expr);
!     v->expr = e;
!     v->flags |= (is_changed|is_valid);
!     v->flags &= ~is_strexpr;
  
  #ifdef EXPRTREE
      totoptree(v);

--- 1687,1698 -----
  	}
  	efree((struct ent *)0, e);
      }
!     else
!     {
! 	efree (v, v->expr);
! 	v->expr = e;
! 	v->flags &= ~is_strexpr;
!     }
  
      v->flags |= (is_changed|is_valid);
      changed++; modflg++;
***************
*** 1571,1581
      v->flags |= (is_changed|is_valid);
      v->flags &= ~is_strexpr;
  
! #ifdef EXPRTREE
!     totoptree(v);
! #endif
!     changed++;
!     modflg++;
  }
  
  void

--- 1694,1701 -----
  	v->flags &= ~is_strexpr;
      }
  
!     v->flags |= (is_changed|is_valid);
!     changed++; modflg++;
  }
  
  void
***************
*** 1590,1595
      (void) signal(SIGFPE, eval_fpe);
      if (setjmp(fpe_save)) {
  	error ("Floating point exception in cell %s", v_name(v->row, v->col));
  	p = "";
      } else {
  	p = seval(se);

--- 1710,1716 -----
      (void) signal(SIGFPE, eval_fpe);
      if (setjmp(fpe_save)) {
  	error ("Floating point exception in cell %s", v_name(v->row, v->col));
+ 	cellerror = CELLERROR;
  	p = "";
      } else {
  	p = seval(se);
***************
*** 1594,1599
      } else {
  	p = seval(se);
      }
      (void) signal(SIGFPE, quit);
      if (exprerr) {
  	efree((struct ent *)0, se);

--- 1715,1721 -----
      } else {
  	p = seval(se);
      }
+     v->cellerror = cellerror;
      (void) signal(SIGFPE, quit);
      if (exprerr) {
  	efree((struct ent *)0, se);
***************
*** 1617,1625
      if (flushdir<0) v->flags |= is_leftflush;
      else v->flags &= ~is_leftflush;
  
- #ifdef EXPRTREE
-     totoptree();
- #endif
      FullUpdate++;
      changed++;
      modflg++;

--- 1739,1744 -----
      if (flushdir<0) v->flags |= is_leftflush;
      else v->flags &= ~is_leftflush;
  
      FullUpdate++;
      changed++;
      modflg++;
***************
*** 1625,1749
      modflg++;
  }
  
! #ifdef EXPRTREE
! /*
!  * put an expression in the expression tree, only the top of each branch is
!  * in the firstev list
!  */
! totoptree(v)
! struct	ent *v;
! {
!     int	right;
!     int	left;
!     if (!v->expr)
! 	return;
! 
! #ifdef notdef
!     right = FALSE;
!     left = FALSE;
!     switch(v->expr->op)
!     {
! 		/* no real expression */
! 	case 'v':
! 		if (v->expr->o.v->evnext)
! 			evdel(v->expr->o.v);
! 	case 'k':
! 	case LMAX:
! 	case LMIN:
! 	case NOW:
! 	case O_SCONST:
! 	case O_VAR:
! 	default:
! 		return;
! 
! 		/* left && right */
! 	case '#':
! 	case '%':
! 	case '&':
! 	case '*':
! 	case '+':
! 	case '-':
! 	case '/':
! 	case '<':
! 	case '=':
! 	case '>':
! 	case '?':
! 	case '^':
! 	case '|':
! 	case ATAN2:
! 	case DTS:
! 	case EQS:
! 	case EXT:
! 	case FMT:
! 	case FV:
! 	case HYPOT:
! 	case IF:
! 	case NVAL:
! 	case PMT:
! 	case POW:
! 	case PV:
! 	case REDUCE | '*':
! 	case REDUCE | '+':
! 	case REDUCE | 'a':
! 	case REDUCE | 'c':
! 	case REDUCE | 's':
! 	case REDUCE | MAX:
! 	case REDUCE | MIN:
! 	case ROUND:
! 	case STINDEX:
! 	case SUBSTR:
! 	case SVAL:
! 	case TTS:
! 		left = right = TRUE;
! 		break;
! 		/* right only */
! 	case 'f':
! 	case 'm':
! 	case '~':
! 	case ABS:
! 	case ACOS:
! 	case ASIN:
! 	case ATAN:
! 	case CEIL:
! 	case COS:
! 	case DATE:
! 	case DAY:
! 	case DTR:
! 	case EXP:
! 	case FABS:
! 	case FLOOR:
! 	case HLOOKUP:
! 	case HOUR:
! 	case IF:
! 	case INDEX:
! 	case LOG10:
! 	case LOG:
! 	case LOOKUP:
! 	case MINUTE:
! 	case MONTH:
! 	case RND:
! 	case RTD:
! 	case SECOND:
! 	case SIN:
! 	case SQRT:
! 	case STON:
! 	case TAN:
! 	case VLOOKUP:
! 	case YEAR:
! 		right = TRUE;
! 		break;
!     }
! 	/* for now insert at the beginning of the list */
!     v->evnext = firstev;
!     v->evprev = (struct ent *)0;
!     if (firstev)
! 	firstev->evprev = v;
!     firstev = v;
! #endif
!     firstev = v;
! }
! #endif /* EXPRTREE*/
! 
  format_cell(v1, v2, s)
  struct ent *v1, *v2;
  char *s;

--- 1744,1750 -----
      modflg++;
  }
  
! void
  format_cell(v1, v2, s)
  struct ent *v1, *v2;
  char *s;
***************
*** 1840,1856
  constant (e)
      register struct enode *e;
  {
!     return ((e == (struct enode *)0)
! 	 || ((e -> op) == O_CONST)
! 	 || ((e -> op) == O_SCONST)
! 	 || (((e -> op) != O_VAR)
! 	  && (((e -> op) & REDUCE) != REDUCE)
! 	  && constant (e -> e.o.left)
! 	  && constant (e -> e.o.right)
! 	  && (e -> op != EXT)	 /* functions look like constants but aren't */
! 	  && (e -> op != NVAL)
! 	  && (e -> op != SVAL)
! 	  && (e -> op != NOW)));
  }
  
  void

--- 1841,1861 -----
  constant (e)
      register struct enode *e;
  {
!     return (
! 	 e == (struct enode *)0
! 	 || e -> op == O_CONST
! 	 || e -> op == O_SCONST
! 	 || (
! 	     e -> op != O_VAR
! 	     && (e -> op & REDUCE) != REDUCE
! 	     && constant (e -> e.o.left)
! 	     && constant (e -> e.o.right)
! 	     && e -> op != EXT	 /* functions look like constants but aren't */
! 	     && e -> op != NVAL
! 	     && e -> op != SVAL
! 	     && e -> op != NOW
! 	)
!     );
  }
  
  void
***************
*** 1867,1882
  	if (e->op == O_SCONST && e->e.s)
  	    xfree(e->e.s);
  	xfree ((char *)e);
- 
- #ifdef EXPRTREE
- 	/* delete this cell from the eval list */
- 	if (v)
- 	{	if (v->evprev)
- 			v->evprev->evnext = v->evnext;
- 		if (v->evnext)
- 			v->evnext->evprev = v->evprev;
- 	}
- #endif /* EXPRTREE */
      }
  }
  

--- 1872,1877 -----
  	if (e->op == O_SCONST && e->e.s)
  	    xfree(e->e.s);
  	xfree ((char *)e);
      }
  }
  
***************
*** 1988,1994
  	case '~':	line[linelim++] = '~';
  			decompile (e->e.o.right, 30);
  			break;
! 	case 'v':	decodev (e->e.v);
  			break;
  	case 'k':	(void)sprintf (line+linelim,"%.15g",e->e.k);
  			linelim += strlen (line+linelim);

--- 1983,1989 -----
  	case '~':	line[linelim++] = '~';
  			decompile (e->e.o.right, 30);
  			break;
! 	case O_VAR:	decodev (e->e.v);
  			break;
  	case O_CONST:	(void)sprintf (line+linelim,"%.15g",e->e.k);
  			linelim += strlen (line+linelim);
***************
*** 1990,1996
  			break;
  	case 'v':	decodev (e->e.v);
  			break;
! 	case 'k':	(void)sprintf (line+linelim,"%.15g",e->e.k);
  			linelim += strlen (line+linelim);
  			break;
  	case '$':	(void)sprintf (line+linelim, "\"%s\"", e->e.s);

--- 1985,1991 -----
  			break;
  	case O_VAR:	decodev (e->e.v);
  			break;
! 	case O_CONST:	(void)sprintf (line+linelim,"%.15g",e->e.k);
  			linelim += strlen (line+linelim);
  			break;
  	case O_SCONST:	(void)sprintf (line+linelim, "\"%s\"", e->e.s);
***************
*** 1993,1999
  	case 'k':	(void)sprintf (line+linelim,"%.15g",e->e.k);
  			linelim += strlen (line+linelim);
  			break;
! 	case '$':	(void)sprintf (line+linelim, "\"%s\"", e->e.s);
  			linelim += strlen(line+linelim);
  			break;
  

--- 1988,1994 -----
  	case O_CONST:	(void)sprintf (line+linelim,"%.15g",e->e.k);
  			linelim += strlen (line+linelim);
  			break;
! 	case O_SCONST:	(void)sprintf (line+linelim, "\"%s\"", e->e.s);
  			linelim += strlen(line+linelim);
  			break;
  
***************
*** 2165,2170
      line[linelim++] = ')';
  }
  
  editfmt (row, col)
  int row, col;
  {

--- 2160,2166 -----
      line[linelim++] = ')';
  }
  
+ void
  editfmt (row, col)
  int row, col;
  {



More information about the Comp.sources.bugs mailing list