rterror.mod 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. IMPLEMENTATION MODULE RTerror;
  2. IMPORT Lib, SYSTEM;
  3. CONST
  4. MaxProcs = 8; (* number of handlers which may be installed *)
  5. IndexCode = 95H;
  6. OverflowCode = 90H;
  7. StackCode = 91H;
  8. SubrangeCode = 92H;
  9. EnumCode = 93H;
  10. NILCode = 94H;
  11. NoRETURNCode = 97H;
  12. TYPE
  13. SP = POINTER TO SHORTCARD;
  14. VAR
  15. Int4VecRTL : SYSTEM.ADDRESS; (* saved int 4 set by rtl.a *)
  16. Int4Procs : ARRAY[1..MaxProcs] OF RTproc; (* the user handlers *)
  17. CurrInt4Proc : CARDINAL; (* the top of Int4Procs *)
  18. Int4Vec [0:4*4] : SYSTEM.ADDRESS; (* the interrupt vector *)
  19. trapped : BOOLEAN; (* TRUE if we have int 4 *)
  20. (*$C FF,J+,S-*) (* save all regs, issue IRET for return, no stack check *)
  21. PROCEDURE Int4Handler(flags : BITSET);
  22. VAR
  23. stack : POINTER TO RECORD (* the stack frame *)
  24. IP,
  25. CS : CARDINAL;
  26. FLAGS : BITSET;
  27. END;
  28. code : RTtype;
  29. aseg,
  30. rseg : CARDINAL;
  31. BEGIN
  32. Int4Vec := Int4VecRTL; (* restore rtl.a handler, so that if an error
  33. occurs, we don't enter this procedure
  34. recursively *)
  35. stack := [SYSTEM.Seg(flags):SYSTEM.Ofs(flags)-4]; (* point to the
  36. stack frame *)
  37. CASE [stack^.CS:stack^.IP SP]^ OF (* the error code *)
  38. IndexCode : code := IndexOutOfRange;
  39. | OverflowCode : code := ArithmeticOverflow;
  40. (* This will be handled by ELSE...
  41. | StackCode : DEC(stack^.IP,2);
  42. CurrInt4Proc := 0;
  43. RETURN;
  44. *)
  45. | SubrangeCode : code := SubOutOfRange;
  46. | EnumCode : code := EnumValue;
  47. | NILCode : code := NILusage;
  48. (* This will be handled by ELSE...
  49. | NoRETURNCode : DEC(stack^.IP,2);
  50. CurrInt4Proc := 0;
  51. RETURN;
  52. *)
  53. ELSE
  54. DEC(stack^.IP,2); (* will return to int 4 which brought us here *)
  55. CurrInt4Proc := 0; (* all user-installed handlers are forgotten *)
  56. RETURN; (* which will invoke the rtl.a int 4 routine *)
  57. END;
  58. aseg := stack^.CS; (* absolute segment of error *)
  59. IF (aseg < Lib.PSP+16) OR (aseg > SYSTEM.HeapBase) THEN
  60. (* if absolute segment is outside of program... *)
  61. rseg := 0FFFFH; (* then flag it *)
  62. ELSE
  63. rseg := aseg-Lib.PSP-16; (* relative segment *)
  64. END;
  65. IF NOT Int4Procs[CurrInt4Proc](aseg,rseg,stack^.IP,code) THEN
  66. (* if user-installed handler returns FALSE... *)
  67. DEC(stack^.IP,2); (* then return to int 4 which brought us here *)
  68. CurrInt4Proc := 0; (* all user-installed handlers are forgotten *)
  69. RETURN;
  70. END;
  71. INC(stack^.IP); (* otherwise, skip error code *)
  72. Int4Vec := SYSTEM.ADR(Int4Handler); (* and rehook vector *)
  73. END Int4Handler;
  74. (*$C F0,J-,S=*) (* back to saving DS, ES, SI, DI, issue RET for return,
  75. restore previous stack-checking state *)
  76. PROCEDURE InstallRT(handler : RTproc);
  77. BEGIN
  78. IF CurrInt4Proc = 0 THEN (* are any handlers installed? *)
  79. Int4Vec := SYSTEM.ADR(Int4Handler); (* no - trap the interrupt *)
  80. END;
  81. IF CurrInt4Proc < MaxProcs THEN (* can we install another one? *)
  82. INC(CurrInt4Proc); (* yes - so do it *)
  83. Int4Procs[CurrInt4Proc] := handler;
  84. END;
  85. END InstallRT;
  86. PROCEDURE UnInstallRT;
  87. BEGIN
  88. IF CurrInt4Proc > 0 THEN (* are there any handlers installed? *)
  89. DEC(CurrInt4Proc); (* yes - remove the last one *)
  90. IF CurrInt4Proc = 0 THEN (* are all the handlers gone? *)
  91. Int4Vec := Int4VecRTL; (* yes - untrap the interrupt *)
  92. END;
  93. END;
  94. END UnInstallRT;
  95. BEGIN
  96. CurrInt4Proc := 0; (* no handler installed *)
  97. Int4VecRTL := Int4Vec; (* get interrupt vector that rtl.a installed *)
  98. trapped := FALSE;
  99. END RTerror.
  100.