home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1988 / 02 / porter / porter.ls1 next >
Text File  |  1979-12-31  |  6KB  |  194 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10. Unit criterr;
  11.  
  12.  { Critical error handler, Turbo Pascal Release 4.0 }
  13.  
  14. Interface
  15. Uses dos, crt;
  16.  
  17. { EXTERNALLY VISIBLE PORTION }
  18.  
  19.    { The following are for saving and restoring the screen,     }
  20.    { which is assumed to be in text mode and display page 0     }
  21.  
  22. Const bell = #7;
  23.  
  24. Type scrnPtr = ^scrnBuffer;
  25.      scrnBuffer = array [1..4096] of byte;
  26.  
  27. Var  display, saveNode  : scrnPtr;             { display buffer }
  28.  
  29.    { The following are global variables available to the using  }
  30.    { program to find out if an error occurred and, if so, what  }
  31.    { it was. The program can then take appropriate action.      }
  32.  
  33.      criticalErrorOccurred : boolean;
  34.      criticalErrorCode     : integer;
  35.      criticalErrorDrive    : integer;
  36.      criticalActionCode    : char;
  37.  
  38.    { The only externally visible routine installs the critical  }
  39.    { error handler in Int 24h, replacing the DOS default.       }
  40.  
  41. Procedure InstallCEH;
  42. Implementation
  43. { ------------------------------------------------------------- }
  44.  
  45.    { Following is a general-purpose critical error handler }
  46.  
  47. {$F+}
  48. Procedure CEHandler (
  49.        Flags, CS, IP, AX, BX, CX, DX, SI, DI, DS, ES, BP : word);
  50. Interrupt;
  51.  
  52. Var  AH, AL    : byte;
  53.      row, col  : integer;
  54.      action    : char;
  55. { --------------------------- }
  56.   { Local functions }
  57.  
  58.   { giveReason lists reason for critical error by decoding the  }
  59.   { low byte of the DI register. Called by procs DiskError and  }
  60.   { CharDeviceError. Writes to screen.                          }
  61.  
  62.   Procedure GiveReason (error : byte);
  63.   Begin
  64.     Case error of
  65.       $00: Writeln ('Write protect');
  66.       $01: Writeln ('Unknown unit');
  67.       $02: Writeln ('Drive not ready');
  68.       $03: Writeln ('Unknown command');
  69.       $04: Writeln ('CRC data error');
  70.       $05: Writeln ('Bad request structure length');
  71.       $06: Writeln ('Seek error');
  72.       $07: Writeln ('Unknown media type');
  73.       $08: Writeln ('Sector not found');
  74.       $0A: Writeln ('Write fault');
  75.       $0B: Writeln ('Read fault');
  76.       $0C: Writeln ('General failure');
  77.       $0D: Writeln ('Bad file allocation table');
  78.       else Writeln ('Unknown');
  79.     End;
  80.   End;
  81. { --------------------------- }
  82.  
  83.   { DiskError is dispatched when H/O bit of AH is 0 }
  84.  
  85.   Function DiskError : word;
  86.  
  87.   Var   area, why : byte;
  88.  
  89.   Begin
  90.     Writeln;
  91.     CriticalErrorDrive := AL;
  92.     Writeln ('Disk error on drive ', char (AL + 65));
  93.     Area := (AH and 6) shr 1;                 { get AH bits 1-2 }
  94.     Case area of
  95.       0: Writeln ('Error in DOS communications area');
  96.       2: Writeln ('Error in disk directory');
  97.       3: Writeln ('Error in files area');
  98.     End;
  99.     Why := lo (DI);
  100.     Write ('Type of error: ');
  101.     GiveReason (why);
  102.     DiskError := why;                       { error return code }
  103.   End;
  104. { --------------------------- }
  105.  
  106.   { NonDiskError is dispatched when H/O bit of AH is 1. }
  107.   { Usually triggered by a printer problem or bad FAT.  }
  108.  
  109.   Function NonDiskError : word;
  110.  
  111.   Var  why         : byte;
  112.        deviceAttr  : ^word;
  113.        deviceName  : ^char;
  114.        ch          : shortInt;
  115.  
  116.   Begin
  117.     DeviceAttr := ptr (BP, SI+4);   { point to device attr word }
  118.     If (deviceAttr^ and $8000) <> 0 then    { if bit 15 is on.. }
  119.       Begin
  120.         Writeln ('Character device error');
  121.         Write ('Failing device is ');
  122.         ch := 0;
  123.         Repeat
  124.           deviceName := ptr (BP, SI + $0A + ch);
  125.           Write (deviceName^);
  126.           inc (ch);
  127.         Until (deviceName^ = chr (0)) or (ch > 7);
  128.         Writeln;
  129.       End
  130.     Else                                       { assume bad FAT }
  131.       Begin
  132.         Writeln ('Disk error has occurred');
  133.         Write   ('Probable cause: ');
  134.         Why := $0D;
  135.         GiveReason (why);
  136.       End;
  137.     NonDiskError := why;                    { return error code }
  138.   End;
  139. { --------------------------- }
  140.  
  141. Begin   { Body of CEHandler procedure }
  142.   CriticalErrorOccurred := TRUE;              { set global flag }
  143.   AH := hi (AX);
  144.   AL := lo (AX);
  145.   Col := whereX;                  { get current cursor position }
  146.   Row := whereY;
  147.   New (saveNode);
  148.   SaveNode^ := display^;                { and save screen image }
  149.   Write (bell);                            { beep to alert user }
  150.   If (AH and $80) = 0 then                    { if AH bit 7 = 0 }
  151.     CriticalErrorCode := DiskError
  152.   Else
  153.     CriticalErrorCode := NonDiskError;
  154.   Repeat                { what are we gonna do about the error? }
  155.     Write ('Abort/Retry/Ignore? ');
  156.     Action := upCase (readKey);
  157.     Writeln (action);
  158.   Until action in ['A', 'I', 'R'];
  159.   CriticalActionCode := action;
  160.   If action = 'I' then begin  { pretend the error didn't happen }
  161.     CriticalErrorOccurred := FALSE;
  162.     CriticalErrorCode     := 0;
  163.     CriticalErrorDrive    := $FF;
  164.     CriticalActionCode    := ' ';
  165.   End;
  166.   Display^ := saveNode^;                 { restore screen image }
  167.   Dispose (saveNode);
  168.   Gotoxy (col, row);                  { restore cursor position }
  169.   AX := 0;                       { tell DOS to ignore the error }
  170. End;
  171. {$F-}
  172. { ------------------------------------------------------------- }
  173.  
  174.    { Externally visible: installs the error handler.            }
  175.    { NOTE: Program termination automatically reinstalls the     }
  176.    { default handler in the vector table.                       }
  177.  
  178. Procedure InstallCEH;
  179.  
  180. Var   videoMode : byte absolute $0040 : $0049;
  181.  
  182. Begin
  183.   SetIntVec ($24, @CEHandler);             { install in int 24h }
  184.   CriticalErrorOccurred := FALSE;                 { set globals }
  185.   CriticalErrorCode     := 0;
  186.   CriticalErrorDrive    := $FF;
  187.   CriticalActionCode    := ' ';
  188.   If videoMode = 7 then
  189.     Display := ptr ($B000, $0000)         { set display address }
  190.   Else
  191.     Display := ptr ($B800, $0000);
  192. End;
  193.  
  194. End.