Xref: utzoo comp.sources.d:5868 comp.unix.sysv386:1013 comp.unix.xenix.sco:373 Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!samsung!uunet!zephyr.ens.tek.com!tektronix!sequent!sequent.uucp!rgb From: rgb@sequent.uucp (Bob Bond) Newsgroups: comp.sources.d,comp.unix.sysv386,comp.unix.xenix.sco Subject: Re: SC Spreadhseet Calculator on sysV/386 Message-ID: <43599@sequent.UUCP> Date: 5 Oct 90 17:26:50 GMT Sender: rgb@sequent.UUCP Organization: Sequent Computer Systems, Inc. Lines: 48 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));