BackStopImpl.mesa
Russ Atkinson, October 7, 1983 1:50 pm
Paul Rovner, October 17, 1983 8:51 am
DIRECTORY
AMEvents USING [Debugged, Debugging],
AMTypes USING [Error, ErrorReason],
BackStop USING [],
FS USING [Error],
IO USING [PutFR, card],
Rope USING [Cat, ROPE],
SafeStorage USING [InvalidType, NarrowRefFault],
DebuggerSwap USING [CallDebugger],
RuntimeError USING
[BoundsFault, ControlFault, DivideCheck, PointerFault, SendMsgSignal, StackError, StartFault, UnboundProcedure, ZeroDivisor],
VM USING [AddressFault, CantAllocate, WriteProtectFault],
WorldVM USING [Address, AddressFault, BadWorld];
BackStopImpl: CEDAR PROGRAM
IMPORTS
AMEvents, AMTypes, DebuggerSwap, FS, IO, Rope, RuntimeError, SafeStorage, VM, WorldVM
EXPORTS BackStop
= BEGIN OPEN Rope, AMTypes, WorldVM;
Pair: TYPE = MACHINE DEPENDENT RECORD [lo,hi: CARDINAL];
Global Variables
SuspendBackStop: PUBLIC SIGNAL = CODE;
ResumeBackStop: PUBLIC SIGNAL = CODE;
alwaysRejectAny: BOOLFALSE; -- for debugging
OZ: BOOLFALSE; -- used to enter debugger when a signal/error occurs
lastAnyMsg: UNSPECIFIED ← 0;
lastAnySignal: SIGNAL ANY RETURNS ANYNIL; -- useful for debugging ANY errors
lagMsg: ROPENIL; -- used to usually avoid GC of error message
lagLagMsg: ROPENIL; -- nothing like being safe...
Call: PUBLIC PROC [inner: PROC] RETURNS [ROPE] = TRUSTED {
msg1, msg2: ROPENIL;
suspensionCount: NAT ← 0;
{{ENABLE {
AMEvents.Debugged, AMEvents.Debugging => REJECT;
ABORTED => REJECT;
UNWIND => REJECT;
FS.Error => {
IF suspensionCount >0 THEN REJECT;
msg1 ← "FS.Error";
msg2 ← error.explanation;
MaybeLeaveKansas[];
GO TO oops};
VM.AddressFault => {
IF suspensionCount >0 THEN REJECT;
msg1 ← IO.PutFR["AddressFault: %b", IO.card[LOOPHOLE[address, LONG CARDINAL]]];
MaybeLeaveKansas[];
GO TO oops};
AMTypes.Error => {
IF suspensionCount >0 THEN REJECT;
msg1 ← SELECT reason FROM
noSymbols => "NoSymbols",
notImplemented => "NotImplemented",
incompatibleTypes => "IncompatibleTypes",
rangeFault => "RangeFault",
notMutable => "NotMutable",
internalTV => "InternalTV",
badName => "BadName",
badIndex => "BadIndex",
typeFault => "TypeFault",
ENDCASE => "Unknown AMTypes.Error";
msg2 ← msg;
MaybeLeaveKansas[];
GO TO oops};
SafeStorage.InvalidType => {
IF suspensionCount >0 THEN REJECT;
msg1 ← "InvalidType";
MaybeLeaveKansas[];
GO TO oops};
SafeStorage.NarrowRefFault => {
IF suspensionCount >0 THEN REJECT;
msg1 ← "NarrowRefFault";
MaybeLeaveKansas[];
GO TO oops};
RuntimeError.BoundsFault => {
IF suspensionCount >0 THEN REJECT;
msg1 ← "BoundsFault";
MaybeLeaveKansas[];
GO TO oops};
RuntimeError.ControlFault => {
IF suspensionCount >0 THEN REJECT;
msg1 ← "ControlFault";
MaybeLeaveKansas[];
GO TO oops};
RuntimeError.DivideCheck => {
IF suspensionCount >0 THEN REJECT;
msg1 ← "DivideCheck";
MaybeLeaveKansas[];
GO TO oops};
RuntimeError.PointerFault => {
IF suspensionCount >0 THEN REJECT;
msg1 ← "PointerFault";
MaybeLeaveKansas[];
GO TO oops};
RuntimeError.StartFault => {
IF suspensionCount >0 THEN REJECT;
msg1 ← "StartFault";
MaybeLeaveKansas[];
GO TO oops};
RuntimeError.StackError => {
IF suspensionCount >0 THEN REJECT;
msg1 ← "StackError";
MaybeLeaveKansas[];
GO TO oops};
RuntimeError.UnboundProcedure => {
IF suspensionCount >0 THEN REJECT;
msg1 ← "UnboundProcedure";
MaybeLeaveKansas[];
GO TO oops};
RuntimeError.ZeroDivisor => {
IF suspensionCount >0 THEN REJECT;
msg1 ← "ZeroDivisor";
MaybeLeaveKansas[];
GO TO oops};
VM.CantAllocate => {
IF suspensionCount >0 THEN REJECT;
msg1 ← "VM.CantAllocate";
MaybeLeaveKansas[];
GO TO oops};
VM.WriteProtectFault => {
IF suspensionCount >0 THEN REJECT;
msg1 ← IO.PutFR["WriteProtectFault: %b", IO.card[LOOPHOLE[address, LONG CARDINAL]]];
MaybeLeaveKansas[];
GO TO oops};
WorldVM.AddressFault => {
IF suspensionCount >0 THEN REJECT;
msg1 ← IO.PutFR["WriteProtectFault: %b", IO.card[LOOPHOLE[addr, LONG CARDINAL]]];
MaybeLeaveKansas[];
GO TO oops};
WorldVM.BadWorld => {
IF suspensionCount >0 THEN REJECT;
msg1 ← "WorldVM.BadWorld";
MaybeLeaveKansas[];
GO TO oops};
SuspendBackStop => {suspensionCount ← suspensionCount + 1; RESUME};
ResumeBackStop => {suspensionCount ← suspensionCount - 1; RESUME};
ANY => TRUSTED{
anyMsg: CARDINAL;
anySignal: UNSPECIFIED;
IF suspensionCount >0 THEN REJECT;
IF alwaysRejectAny THEN REJECT;
[anyMsg, anySignal] ← SIGNAL RuntimeError.SendMsgSignal;
lastAnyMsg ← anyMsg;
lastAnySignal ← anySignal;
SELECT LOOPHOLE[anySignal, CARDINAL] FROM
177777B => {
the overused unnamed ERROR
msg1 ← "unnamed ERROR";
};
ENDCASE => {
msg1 ← IO.PutFR[
"UnknownError[sig: %b, msg: %b]",
IO.card[LOOPHOLE[anySignal, CARDINAL]],
IO.card[anyMsg]
];
};
MaybeLeaveKansas[];
GO TO oops}};
inner[];
RETURN [NIL]}
EXITS
oops => {
IF msg2 # NIL THEN msg1 ← msg1.Cat["[", msg2, "]"];
lagLagMsg ← lagMsg;
RETURN[(lagMsg ← msg1)]}}
};
MaybeLeaveKansas: PROC = TRUSTED {
IF OZ THEN
DebuggerSwap.CallDebugger["Toto, I don't think that we are in Kansas anymore..."];
};
END.