home *** CD-ROM | disk | FTP | other *** search
/ RBBS in a Box Volume 1 #3.1 / RBBSIABOX31.cdr / fasm / errhan.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1990-09-29  |  5.5 KB  |  170 lines

  1. (*[72457,2131]
  2. ERRHAN.PAS     03-Oct-85 5145
  3.  
  4.     Keywords: IBM ERROR PCDOS 3.01 HANDLER INTERRUPT
  5.  
  6.     This program demonstrates a run-time error handler for Turbo version 3.01A.
  7.     It allows control to return to the program after a run-time error, and
  8.     provides a global variable containing information about what the error was.
  9.     For PCDOS Turbo 3.01A (plain vanilla) only, but could be modified for
  10.     others (there is one absolute address that would require change).
  11. *)
  12.  
  13.   {
  14.   Demonstrates a run-time error handler for PCDOS Turbo version 3.01A.
  15.   Captures run-time errors with the built-in Turbo facility, but also
  16.   allows returning to the executing program after the error occurs. A
  17.   global variable ErrorResult can be polled to determine whether an error
  18.   has occurred, and which type.
  19.  
  20.   Some errors do not allow graceful recovery, and for these the program
  21.   will just halt.
  22.  
  23.   Note that it is possible to avoid all run-time errors by appropriate
  24.   checking of values prior to performing operations. The "preventative"
  25.   method is recommended over the techniques provided here, but these
  26.   techniques may be handy for special cases.
  27.  
  28.   Written 10/2/85, Kim Kokkonen, TurboPower Software.
  29.   408-378-3672, CompuServe 72457,2131.
  30.   }
  31.  
  32.   {$R+}
  33.  
  34. PROGRAM ErrorTest;
  35.   VAR
  36.     ErrorResult : Byte;
  37.  
  38.     {the following variables are for the purpose of demonstration only}
  39.     x, y, z : Real;
  40.     i, j, k : Integer;
  41.     s : STRING[255];
  42.     a : ARRAY[1..10] OF Integer;
  43.     v : 1..10;
  44.  
  45.   PROCEDURE Error(ErrNo, ErrAddr : Integer);
  46.       {-errors interrupt to this procedure, not to be called directly}
  47.     VAR
  48.       ErrType, ErrNum : Byte;
  49.       ErrOfs : Integer;
  50.     BEGIN
  51.       ErrType := Hi(ErrNo);
  52.       IF ErrType = 0 THEN BEGIN
  53.         {^C, just exit without an address printed}
  54.         Halt(1);
  55.       END ELSE IF ErrType = 1 THEN BEGIN
  56.         {I/O error,let turbo handle it}
  57.         {using the $I- directive and polling IOResult gives full control}
  58.       END ELSE BEGIN
  59.         {runtime error, return when possible to calling scope}
  60.         {ErrOfs is number of bytes to skip on return to calling scope}
  61.         ErrNum := Lo(ErrNo);
  62.         CASE ErrNum OF
  63.           4 : ErrOfs := 7;
  64.           $10 : BEGIN
  65.                   {recovery is unreliable, prevention is a better answer}
  66.                   WriteLn('string length exceeds 255');
  67.                   Halt(2);
  68.                 END;
  69.           $11 : ErrOfs := 8;
  70.           $F0 : BEGIN
  71.                   {no way to gracefully recover}
  72.                   WriteLn('overlay file not found');
  73.                   Halt(2);
  74.                 END;
  75.           $FF : BEGIN
  76.                   {no way to gracefully recover}
  77.                   {prevention is straightforward using memavail}
  78.                   WriteLn('heap/stack collision');
  79.                   Halt(2);
  80.                 END;
  81.         ELSE
  82.           ErrOfs := 3;
  83.         END;
  84.         {this global variable is accessed to handle error types}
  85.         ErrorResult := ErrNum;
  86.         INLINE(
  87.           $8B/$46/$04/        {MOV   AX,[BP+04]   ;get erraddr              }
  88.           $03/$46/< ErrOfs/   {ADD   AX,errofs[BP];compute return address   }
  89.           $8B/$E5/            {MOV   SP,BP        ;restore stack            }
  90.           $5D/                {POP   BP                                     }
  91.           $50/                {PUSH  AX           ;return address on stack  }
  92.           $31/$C0/            {XOR   AX,AX        ;required for string instr}
  93.           $A3/$88/$01/        {MOV   [188],AX     ;required for further errs}
  94.           $C2/$02/$00         {RET   0002         ;return and realign stack }
  95.           );
  96.       END;
  97.     END;                      {error}
  98.  
  99.   PROCEDURE HandleError;
  100.       {-print error message or do whatever is necessary}
  101.     BEGIN
  102.       CASE ErrorResult OF
  103.         1 : WriteLn('floating point overflow');
  104.         2 : WriteLn('floating point division by zero');
  105.         3 : WriteLn('negative Sqrt argument');
  106.         4 : WriteLn('integer divide by zero or negative Ln argument');
  107.         $11 : WriteLn('string index out of range');
  108.         $90 : WriteLn('array index out of range');
  109.         $91 : WriteLn('scalar or subrange assignment out of range');
  110.         $92 : WriteLn('integer assignment out of range');
  111.       END;
  112.       {reset to find next error}
  113.       ErrorResult := 0;
  114.     END;                      {handleerror}
  115.  
  116.   PROCEDURE SetupErrorHandler;
  117.     BEGIN
  118.       errorptr := Ofs(Error);
  119.       ErrorResult := 0;
  120.     END;                      {setuperrorhandler}
  121.  
  122.   BEGIN
  123.     SetupErrorHandler;
  124.  
  125.     {string index error}
  126.     i := 256;
  127.     s := 'hello';
  128.     s := Copy(s, i, 1);
  129.     IF ErrorResult <> 0 THEN HandleError;
  130.  
  131.     {array index error, only caught with $R+}
  132.     i := 20;
  133.     a[i] := 10;
  134.     IF ErrorResult <> 0 THEN HandleError;
  135.  
  136.     {subrange assignment error}
  137.     i := 20;
  138.     v := i;
  139.     IF ErrorResult <> 0 THEN HandleError;
  140.  
  141.     {integer range error}
  142.     x := -65536.0;
  143.     i := Trunc(x);
  144.     IF ErrorResult <> 0 THEN HandleError;
  145.  
  146.     {negative Ln error}
  147.     y := -3.0;
  148.     z := Ln(y);
  149.     IF ErrorResult <> 0 THEN HandleError;
  150.  
  151.     {floating point divide by zero error}
  152.     y := 0;
  153.     x := 1;
  154.     z := x/y;
  155.     IF ErrorResult <> 0 THEN HandleError;
  156.  
  157.     {integer divide by zero error}
  158.     i := 0;
  159.     j := 1;
  160.     k := j DIV i;
  161.     IF ErrorResult <> 0 THEN HandleError;
  162.  
  163.     {floating point overflow error}
  164.     x := 1.0E20;
  165.     y := 1.0E-20;
  166.     z := x/y;
  167.     IF ErrorResult <> 0 THEN HandleError;
  168.  
  169.   END.
  170.