BackStopImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Russ Atkinson, March 7, 1985 3:52:49 am PST
Paul Rovner, October 17, 1983 8:51 am
Russ Atkinson (RRA) May 29, 1985 1:57:04 am PDT
DIRECTORY
AMEvents USING [Debugged, Debugging],
AMTypes USING [Error, ErrorReason],
BackStop USING [],
FS USING [Error],
IO USING [PutFR, PutRope, RopeFromROS, ROS, STREAM],
Real USING [Exception, ExceptionFlags, NoExceptions, RealError, RealException],
Rope USING [ROPE],
SafeStorage USING [CantEstablishFinalization, InvalidType, NarrowRefFault, UnsafeProcAssignment],
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, Real, RuntimeError, SafeStorage, VM, WorldVM
EXPORTS BackStop
= BEGIN OPEN AMTypes, Rope, WorldVM;
ROPE: TYPE = Rope.ROPE;
STREAM: TYPE = IO.STREAM;
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: UNSAFE SIGNAL ANY RETURNS ANYNIL;
useful for debugging ANY errors
lagMsg: ROPENIL;
used to usually avoid GC of error message
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: %bB", [cardinal[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.CantEstablishFinalization => {
IF suspensionCount > 0 THEN REJECT;
msg1 ← "SafeStorage.CantEstablishFinalization";
MaybeLeaveKansas[];
GO TO oops};
SafeStorage.InvalidType => {
IF suspensionCount > 0 THEN REJECT;
msg1 ← "SafeStorage.InvalidType";
MaybeLeaveKansas[];
GO TO oops};
SafeStorage.NarrowRefFault => {
IF suspensionCount > 0 THEN REJECT;
msg1 ← "NarrowRefFault";
MaybeLeaveKansas[];
GO TO oops};
SafeStorage.UnsafeProcAssignment => {
IF suspensionCount > 0 THEN REJECT;
msg1 ← "SafeStorage.UnsafeProcAssignment";
MaybeLeaveKansas[];
GO TO oops};
Real.RealError => {
IF suspensionCount > 0 THEN REJECT;
msg1 ← "Real.RealError";
MaybeLeaveKansas[];
GO TO oops};
Real.RealException => TRUSTED {
RealFlagsNames: ARRAY Real.Exception OF ROPE = [
"fixOverflow", "inexactResult", "invalidOperation",
"divisionByZero", "overflow", "underflow"
];
ros: STREAMIO.ROS[];
temp: Real.ExceptionFlags ← flags;
IF suspensionCount > 0 THEN REJECT;
msg1 ← "Real.RealException";
IO.PutRope[ros, "{"];
IF temp # Real.NoExceptions THEN
FOR flag: Real.Exception IN Real.Exception DO
IF temp[flag] THEN {
temp[flag] ← FALSE;
IO.PutRope[ros, RealFlagsNames[flag]];
IF temp = Real.NoExceptions THEN EXIT;
IO.PutRope[ros, ", "];
};
ENDLOOP;
IO.PutRope[ros, "}"];
msg2 ← IO.RopeFromROS[ros];
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: %bB", [cardinal[LOOPHOLE[address, LONG CARDINAL]]]];
MaybeLeaveKansas[];
GO TO oops};
WorldVM.AddressFault => {
IF suspensionCount > 0 THEN REJECT;
msg1 ← IO.PutFR["WriteProtectFault: %bB", [cardinal[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 => {
IF suspensionCount > 0 THEN suspensionCount ← suspensionCount - 1;
RESUME};
ANY => TRUSTED {
anyMsg: CARDINAL;
anySignal: UNSAFE SIGNAL ANY RETURNS ANY;
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: %bB, msg: %bB]",
[cardinal[LOOPHOLE[anySignal, CARDINAL]]],
[cardinal[anyMsg]]
];
};
MaybeLeaveKansas[];
GO TO oops}};
inner[];
RETURN [NIL]}
EXITS
oops => {
IF msg2 # NIL THEN msg1 ← IO.PutFR["%g[%g]", [rope[msg1]], [rope[msg2]]];
RETURN[(lagMsg ← msg1)]}}
};
MaybeLeaveKansas: PROC = TRUSTED {
IF OZ THEN
DebuggerSwap.CallDebugger["Toto, I don't think that we are in Kansas anymore..."L];
};
END.