<<>> <> <> <> <> <> DIRECTORY BackStop, PreDebug USING [Explain], Rope USING [ROPE], RuntimeError USING [SendMsg, UNCAUGHT]; BackStopImpl: CEDAR PROGRAM IMPORTS PreDebug, RuntimeError EXPORTS BackStop = BEGIN SuspendBackStop: PUBLIC SIGNAL = CODE; ResumeBackStop: PUBLIC SIGNAL = CODE; alwaysRejectAny: BOOL ¬ FALSE; <> OZ: BOOL ¬ FALSE; <> lastAnyMsg: POINTER ¬ NIL; lastAnySignal: UNSAFE SIGNAL ANY RETURNS ANY ¬ NIL; <> lagMsg: Rope.ROPE ¬ NIL; <> Call: PUBLIC PROC [inner: PROC] RETURNS [Rope.ROPE] = TRUSTED { msg: Rope.ROPE ¬ NIL; suspensionCount: NAT ¬ 0; {{ENABLE { ABORTED => REJECT; UNWIND => REJECT; SuspendBackStop => { suspensionCount ¬ suspensionCount + 1; RESUME; }; ResumeBackStop => { IF suspensionCount > 0 THEN suspensionCount ¬ suspensionCount - 1; RESUME; }; ANY => TRUSTED { anyMsg: POINTER; anySignal: UNSAFE SIGNAL ANY RETURNS ANY; IF suspensionCount > 0 THEN REJECT; IF alwaysRejectAny THEN REJECT; [anySignal, anyMsg] ¬ SIGNAL RuntimeError.SendMsg; lastAnyMsg ¬ anyMsg; lastAnySignal ¬ anySignal; msg ¬ PreDebug.Explain[anySignal, anyMsg ! RuntimeError.UNCAUGHT => { msg ¬ "unknown error (explaining error raised error)"; CONTINUE }]; MaybeLeaveKansas[]; GO TO oops; }}; inner[]; RETURN [NIL]} EXITS oops => RETURN [(lagMsg ¬ msg)]; }; }; MaybeLeaveKansas: PROC = TRUSTED { IF OZ THEN ERROR <>; }; END.