| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- IMPLEMENTATION MODULE RTerror;
- IMPORT Lib, SYSTEM;
- CONST
- MaxProcs = 8; (* number of handlers which may be installed *)
- IndexCode = 95H;
- OverflowCode = 90H;
- StackCode = 91H;
- SubrangeCode = 92H;
- EnumCode = 93H;
- NILCode = 94H;
- NoRETURNCode = 97H;
- TYPE
- SP = POINTER TO SHORTCARD;
- VAR
- Int4VecRTL : SYSTEM.ADDRESS; (* saved int 4 set by rtl.a *)
- Int4Procs : ARRAY[1..MaxProcs] OF RTproc; (* the user handlers *)
- CurrInt4Proc : CARDINAL; (* the top of Int4Procs *)
- Int4Vec [0:4*4] : SYSTEM.ADDRESS; (* the interrupt vector *)
- trapped : BOOLEAN; (* TRUE if we have int 4 *)
- (*$C FF,J+,S-*) (* save all regs, issue IRET for return, no stack check *)
- PROCEDURE Int4Handler(flags : BITSET);
- VAR
- stack : POINTER TO RECORD (* the stack frame *)
- IP,
- CS : CARDINAL;
- FLAGS : BITSET;
- END;
- code : RTtype;
- aseg,
- rseg : CARDINAL;
- BEGIN
- Int4Vec := Int4VecRTL; (* restore rtl.a handler, so that if an error
- occurs, we don't enter this procedure
- recursively *)
- stack := [SYSTEM.Seg(flags):SYSTEM.Ofs(flags)-4]; (* point to the
- stack frame *)
- CASE [stack^.CS:stack^.IP SP]^ OF (* the error code *)
- IndexCode : code := IndexOutOfRange;
- | OverflowCode : code := ArithmeticOverflow;
- (* This will be handled by ELSE...
- | StackCode : DEC(stack^.IP,2);
- CurrInt4Proc := 0;
- RETURN;
- *)
- | SubrangeCode : code := SubOutOfRange;
- | EnumCode : code := EnumValue;
- | NILCode : code := NILusage;
- (* This will be handled by ELSE...
- | NoRETURNCode : DEC(stack^.IP,2);
- CurrInt4Proc := 0;
- RETURN;
- *)
- ELSE
- DEC(stack^.IP,2); (* will return to int 4 which brought us here *)
- CurrInt4Proc := 0; (* all user-installed handlers are forgotten *)
- RETURN; (* which will invoke the rtl.a int 4 routine *)
- END;
- aseg := stack^.CS; (* absolute segment of error *)
- IF (aseg < Lib.PSP+16) OR (aseg > SYSTEM.HeapBase) THEN
- (* if absolute segment is outside of program... *)
- rseg := 0FFFFH; (* then flag it *)
- ELSE
- rseg := aseg-Lib.PSP-16; (* relative segment *)
- END;
- IF NOT Int4Procs[CurrInt4Proc](aseg,rseg,stack^.IP,code) THEN
- (* if user-installed handler returns FALSE... *)
- DEC(stack^.IP,2); (* then return to int 4 which brought us here *)
- CurrInt4Proc := 0; (* all user-installed handlers are forgotten *)
- RETURN;
- END;
- INC(stack^.IP); (* otherwise, skip error code *)
- Int4Vec := SYSTEM.ADR(Int4Handler); (* and rehook vector *)
- END Int4Handler;
- (*$C F0,J-,S=*) (* back to saving DS, ES, SI, DI, issue RET for return,
- restore previous stack-checking state *)
- PROCEDURE InstallRT(handler : RTproc);
- BEGIN
- IF CurrInt4Proc = 0 THEN (* are any handlers installed? *)
- Int4Vec := SYSTEM.ADR(Int4Handler); (* no - trap the interrupt *)
- END;
- IF CurrInt4Proc < MaxProcs THEN (* can we install another one? *)
- INC(CurrInt4Proc); (* yes - so do it *)
- Int4Procs[CurrInt4Proc] := handler;
- END;
- END InstallRT;
- PROCEDURE UnInstallRT;
- BEGIN
- IF CurrInt4Proc > 0 THEN (* are there any handlers installed? *)
- DEC(CurrInt4Proc); (* yes - remove the last one *)
- IF CurrInt4Proc = 0 THEN (* are all the handlers gone? *)
- Int4Vec := Int4VecRTL; (* yes - untrap the interrupt *)
- END;
- END;
- END UnInstallRT;
- BEGIN
- CurrInt4Proc := 0; (* no handler installed *)
- Int4VecRTL := Int4Vec; (* get interrupt vector that rtl.a installed *)
- trapped := FALSE;
- END RTerror.
|