[comp.lang.pascal] On error goto for pascal?

mpratap@CUE.BC.CA (Matt Pratap) (05/03/91)

 
This may be old hat, but I just started reading this group.
 
I need to get my programs, written in Tp5.5, to execute a procedure
or flag a variable/address when a run-time error occurs, instead
of exiting the program with an error. I know how to do this with
dos and graphics errors.

eg: if a user enters 2 real numbers and  the program multiplies them
together, and if the result is too large for even a real number to
handle, the program will quit with an error.
Instead I would like to check (via a variable or address) if the
result was ok, before proceeding, else it will take steps to
deal with the problem.

Even my instructor ('Turbo Tom') can figure out how to do this.

Thanks

-------------------------------------------------------------------------
Matt Pratap, Victoria B.C. -=- mpratap@cue.bc.ca  *  (Insert quote here!)
-------------------------------------------------------------------------

dmurdoch@watstat.waterloo.edu (Duncan Murdoch) (05/03/91)

In article <9105030125.AA18493@cue.bc.ca> mpratap@CUE.BC.CA (Matt Pratap) writes:
>This may be old hat, but I just started reading this group.
> 
>I need to get my programs, written in Tp5.5, to execute a procedure
>or flag a variable/address when a run-time error occurs, instead
>of exiting the program with an error. I know how to do this with
>dos and graphics errors.
>
>eg: if a user enters 2 real numbers and  the program multiplies them
>together, and if the result is too large for even a real number to
>handle, the program will quit with an error.
>Instead I would like to check (via a variable or address) if the
>result was ok, before proceeding, else it will take steps to
>deal with the problem.

This is hard.  The Turbo and Object Professional packages from TurboPower
allow automatic recovery from some errors, but not floating point errors.
For those, the only way I know of is as follows:

Run in the N+ state (i.e. use the IEEE reals, not the TP "real" type).  Then
before a questionable instruction, set the control word of the coprocessor
so that all errors are masked.  This seems to work with the emulator too,
so it doesn't matter if you really have an 87.  Your calculation is then
guaranteed to succeed, but it may contain a non-numeric answer.

There are a few things you could do at this point.  You could just
go on with the work, if answers like +INF and NAN don't bother you;
the coprocessor is designed so that they propagate more or less the
way you'd expect, and TP knows how to print them. 

You could check whether the answer is numeric or not, and proceed accordingly.

You could query the coprocessor to find out whether any exceptions have 
occurred.  Records of exceptions are kept up until the next query, which
makes this sound like the best way to go, except for one bug in TP:
any time you do I/O on floating point values the flags are reset, so that
you lose any record of whether an error has occurred or not.

There's code to help you do this in the Turbo/Object Professional toolkits;
it's not too hard to write if you're comfortable in assembler.

Here's a routine to do the check for a numeric answer, for the Double type:

type
  Float    = Double;
  Float_as_Words = array[1..4] of Word;

  function Is_Numeric(x : Float) : Boolean;
  var
    xw       : Float_as_Words absolute x;
  begin
    Is_Numeric := (xw[4] and $7fff) < $7ff0;
  end;

I hope this helps.

Duncan Murdoch

CDHWilli@exua.exeter.ac.uk (Charles Williams) (05/05/91)

#
#>eg: if a user enters 2 real numbers and  the program multiplies them
#>together, and if the result is too large for even a real number to
#>handle, the program will quit with an error.
#>Instead I would like to check (via a variable or address) if the
#>result was ok, before proceeding, else it will take steps to
#>deal with the problem.
#
#This is hard.  The Turbo and Object Professional packages from TurboPower
#allow automatic recovery from some errors, but not floating point errors.
#For those, the only way I know of is as follows:
#
#[IEEE stuff, FPU modes etc]
#
Checking status bits and using IEEE (pronounced I-trickery?) is fast but
if portability is important then there are other approaches which are
worth thinking about...for example:

Q)  Will A*B overflow?
A)  overflow:=(ln(MinReal+abs(A))+ln(MinReal+abs(B)))>ln(MaxReal);

Q)  Will A/B overflow?
A1) overflow:=(ln(MinReal+abs(A))-ln(MinReal+abs(B)))>ln(MaxReal);
A2) overflow:=abs(A/MaxReal)>abs(B);

Where MaxReal and MinReal are the smallest and largest normalised postive
reals.  If you've got a good elementary function library then taking
logs is remarkably fast.  (If you want to hack-up the speed a bit then
you can use variant record structures to extract the binary exponents
from the reals by overlaying with a set and a couple of integers and use
them in place of the logs, but then you're back in the tar-pit again...)

===============================================================================
================== World's most embarassing alias: l 'ls *.f' =================
===============================================================================

Kai_Henningsen@ms.maus.de (Kai Henningsen) (05/08/91)

Matt Pratap mpratap%CUE.BC.CA @ SUB schrieb am 02.05.1991, 23:25

MP>This may be old hat, but I just started reading this group.
MP>
MP>I need to get my programs, written in Tp5.5, to execute a procedure
MP>or flag a variable/address when a run-time error occurs, instead
MP>of exiting the program with an error. I know how to do this with
MP>dos and graphics errors.

Look in the manuals under "ExitProc", for a start. When you need to return to a
higher level from there, I'll look where I left my assembler functions to do
what C calls a longjmp().

MfG Kai