SC Spreadhseet Calculator on sysV/386

Bob Bond rgb at sequent.uucp
Sat Oct 6 03:26:50 AEST 1990


Richard Foulk points out that sc core dumps after 5 divide by zero
errors.  The problem is that the 378 FPU state is not cleaned up
properly by the runtime system  (OS/C compiler) after an exception.

The 387 has a stack that the FP operands are pushed on before each
operation.  If the operation completes successfully, the stack is
popped and things go on their merry way.  If the operation errors out,
for example by a divide by 0, the operands are not popped.  So the next
operation adds a couple more operands, etc.  Eventually (after 5
errors) the stack fills and some innocent operation gets killed because
there is not enough stack space to hold its data.  Since the program
was not expecting that particular operation to generate an exception,
the program dumps core.

I have some disgusting, non-portable, 387 only code that does "asm
fpusave" and "asm fpurestore" operations at the right time.  If I get
enough response (please, mail only) I'll pass it on to Jeffery Buhrt so
he can post.

I'd suggest that rather than trying to patch in the asm code, you tell
your vendor about the problem :-).  In the meantime, the tried and true
(and easy) fix for this is to apply the following hack to interp.c and
stop most of the divide by 0's from happening in the first place.  This
is the way things used to be, in version 5.1 and before.

						Bob Bond
----------------------------
*** interp.c	Fri Oct  5 10:16:12 1990
--- interp.c.new	Fri Oct  5 10:14:26 1990
***************
*** 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));

--- 629,636 -----
  	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 denom = eval (e->e.o.right);
! 			       return denom ? eval(e->e.o.left) / denom : 0; }
  	case '%':     {	double num, denom;
  			num = floor(eval(e->e.o.left));
  			denom = floor(eval (e->e.o.right));



More information about the Comp.unix.sysv386 mailing list