DIRECTORY Basics USING [BYTE], MesaRuntimeInit USING [], PrincOps USING [ BytePC, ControlLink, --FieldDescriptor, --Frame, FrameHandle, localbase, markOffset, NullFrame, NullLink, SD, sError, sErrorList, sReturnError, sReturnErrorList, sSignal, sSignalList, StateVector, sUnnamedError, zCATCH, zJ2, zJ9, zJB, zJW, zLADRB, zPORTI, zWF], PrincOpsUtils USING [ Alloc, Codebase, Free, GetReturnFrame, GetReturnLink, MyGlobalFrame, MyLocalFrame, SetReturnLink], RuntimeError USING [UCSProc]; SignalsImpl: MONITOR IMPORTS PrincOpsUtils EXPORTS MesaRuntimeInit, RuntimeError = BEGIN BYTE: TYPE = Basics.BYTE; CatchPointer: TYPE = POINTER TO catch PrincOps.Frame; CatchCall: TYPE = PROCEDURE [SIGNAL ANY RETURNS ANY] RETURNS [ActionCode]; CatchContinue: TYPE = PROCEDURE; ActionCode: TYPE = INTEGER; reject: ActionCode = 0; resume: ActionCode = 1; exit: ActionCode = -1; ucsHandler: RuntimeError.UCSProc _ NIL; SendMsgSignal: PUBLIC SIGNAL RETURNS [UNSPECIFIED, UNSPECIFIED] = CODE; ResumeError: PUBLIC SIGNAL = CODE; UNCAUGHT: PUBLIC ERROR [signal: SIGNAL ANY RETURNS ANY, parameters: UNSPECIFIED] = CODE; InformationalSignal: PUBLIC SAFE PROC [signal: SIGNAL] = TRUSTED { MarkSignalHandlerFrame[FALSE]; SignalHandler[signal, -1, TRUE]; }; RegisterUncaughtSignalHandler: PUBLIC ENTRY PROC [proc: RuntimeError.UCSProc] RETURNS [old: RuntimeError.UCSProc] = {old _ ucsHandler; ucsHandler _ proc}; Error: PROC [signal: SIGNAL ANY RETURNS ANY, message: UNSPECIFIED] = { MarkSignalHandlerFrame[FALSE]; SignalHandler[signal, message]; ERROR ResumeError }; ErrorList: PROC [signal: SIGNAL ANY RETURNS ANY, message: POINTER TO UNSPECIFIED] = { MarkSignalHandlerFrame[FALSE]; SignalHandler[signal, message ! UNWIND => PrincOpsUtils.Free[message]]; PrincOpsUtils.Free[message]; ERROR ResumeError }; ReturnError: PROC [signal: SIGNAL ANY RETURNS ANY, message: UNSPECIFIED] = { caller: PrincOps.FrameHandle = PrincOpsUtils.GetReturnFrame[]; PrincOpsUtils.SetReturnLink[caller.returnlink]; MarkSignalHandlerFrame[FALSE]; SignalHandler[signal, message ! UNWIND => PrincOpsUtils.Free[caller]]; PrincOpsUtils.Free[caller]; ERROR ResumeError }; ReturnErrorList: PROC [ signal: SIGNAL ANY RETURNS ANY, message: POINTER TO UNSPECIFIED] = { caller: PrincOps.FrameHandle = PrincOpsUtils.GetReturnFrame[]; PrincOpsUtils.SetReturnLink[caller.returnlink]; MarkSignalHandlerFrame[FALSE]; SignalHandler[signal, message ! UNWIND => {PrincOpsUtils.Free[caller]; PrincOpsUtils.Free[message]} ]; PrincOpsUtils.Free[caller]; PrincOpsUtils.Free[message]; ERROR ResumeError }; UnnamedError: PROC = { MarkSignalHandlerFrame[FALSE]; SignalHandler[LOOPHOLE[-1], -1]; ERROR ResumeError }; Signal: PROC [signal: SIGNAL ANY RETURNS ANY, message: UNSPECIFIED] = { MarkSignalHandlerFrame[FALSE]; SignalHandler[signal, message]; }; SignalList: PROC [signal: SIGNAL ANY RETURNS ANY, message: POINTER TO UNSPECIFIED] = { MarkSignalHandlerFrame[FALSE]; SignalHandler[signal, message ! UNWIND => PrincOpsUtils.Free[message]]; PrincOpsUtils.Free[message]; }; MarkSignalHandlerFrame: PROC [value: BOOL] = MACHINE CODE { PrincOps.zLADRB, 0; PrincOps.zWF, --PrincOps.FieldDescriptor[offset: PrincOps.markOffset, posn: 0, size: 1]-- PrincOps.markOffset, 0; }; SignalHandler: PROC [ signal: SIGNAL ANY RETURNS ANY, message: UNSPECIFIED, informational: BOOL _ FALSE] = { SignalFrame: TYPE = POINTER TO FRAME[SignalHandler]; frame, nextFrame: PrincOps.FrameHandle; target, nextTarget: PrincOps.FrameHandle; self: PrincOps.FrameHandle = PrincOpsUtils.MyLocalFrame[]; start: PrincOps.FrameHandle; catchFrame: CatchPointer; action: ActionCode; unwinding: BOOL; catchPhrase: BOOL; catchFSIndex: BYTE; catchPC, exitPC: PrincOps.BytePC; catchState: PrincOps.StateVector; MarkSignalHandlerFrame[TRUE]; unwinding _ FALSE; start _ GetFrame[self.returnlink]; target _ PrincOps.NullFrame; DO nextFrame _ start; UNTIL nextFrame = target DO frame _ nextFrame; IF frame.accesslink = PrincOpsUtils.MyGlobalFrame[] AND frame.mark THEN { OPEN thisSignaller: LOOPHOLE[frame, SignalFrame]; IF unwinding THEN { IF signal = thisSignaller.signal THEN nextTarget _ IF thisSignaller.unwinding THEN thisSignaller.nextTarget ELSE thisSignaller.nextFrame; IF thisSignaller.unwinding THEN { IF thisSignaller.frame = LOOPHOLE[frame.returnlink] THEN frame.returnlink _ [frame[thisSignaller.nextFrame]]; PrincOpsUtils.Free[thisSignaller.frame]; }; nextFrame _ GetFrame[frame.returnlink]; } ELSE nextFrame _ IF signal ~= thisSignaller.signal THEN IF thisSignaller.unwinding THEN thisSignaller.nextFrame ELSE GetFrame[frame.returnlink] ELSE IF thisSignaller.unwinding THEN thisSignaller.nextTarget ELSE thisSignaller.nextFrame; } ELSE nextFrame _ GetFrame[frame.returnlink]; IF unwinding AND nextTarget = frame THEN nextTarget _ nextFrame; [catchPhrase, catchFSIndex, catchPC] _ CheckCatch[frame]; IF catchPhrase THEN { catchFrame _ PrincOpsUtils.Alloc[catchFSIndex]; catchFrame^ _ PrincOps.Frame[ accesslink: frame.accesslink, pc: catchPC, returnlink: [frame[self]], extensions: catch[unused: , staticlink: frame+PrincOps.localbase, messageval: message]]; action _ LOOPHOLE[catchFrame, CatchCall] [IF unwinding THEN LOOPHOLE[UNWIND] ELSE signal ! SendMsgSignal => RESUME[message, signal]]; catchState _ STATE; SELECT action FROM reject => NULL; resume => IF unwinding THEN ERROR ResumeError ELSE { catchState.dest _ PrincOpsUtils.GetReturnLink[]; catchState.source _ PrincOps.NullLink; RETURN WITH catchState }; exit => IF ~informational THEN { exitPC _ catchFrame.pc; PrincOpsUtils.Free[catchFrame]; target _ LOOPHOLE[catchState.stk[0]-PrincOps.localbase]; nextTarget _ nextFrame; unwinding _ TRUE; message _ NIL; GO TO StartUnwind; }; ENDCASE; }; IF unwinding THEN { IF frame = start THEN start _ nextFrame; IF frame = LOOPHOLE[self.returnlink] THEN self.returnlink _ [frame[nextFrame]]; PrincOpsUtils.Free[frame]; }; REPEAT StartUnwind => NULL; FINISHED => EXIT ENDLOOP; ENDLOOP; SELECT TRUE FROM unwinding => target.pc _ exitPC; informational OR signal = LOOPHOLE[UNCAUGHT] => NULL; -- does an implicit RESUME ENDCASE => { Uncaught: TYPE = SIGNAL [SIGNAL ANY RETURNS ANY, UNSPECIFIED]; LOOPHOLE[UNCAUGHT, Uncaught][signal, message]; ucsHandler[message, signal, frame]; }; }; CheckCatch: PROC [frame: PrincOps.FrameHandle] RETURNS [catchPhrase: BOOL, fsIndex: BYTE, pc: PrincOps.BytePC] = { code: LONG POINTER TO PACKED ARRAY [0..0) OF BYTE; MarkSignalHandlerFrame[FALSE]; code _ PrincOpsUtils.Codebase[frame.accesslink]; pc _ [frame.pc]; DO SELECT code[pc] FROM PrincOps.zCATCH => {catchPhrase _ TRUE; EXIT}; PrincOps.zPORTI => pc _ [pc + 1]; ENDCASE => {catchPhrase _ FALSE; EXIT}; ENDLOOP; IF catchPhrase THEN { fsIndex _ code[pc+1]; SELECT code[pc _ [pc+2]] FROM PrincOps.zJB => pc _ [pc + 2]; IN [PrincOps.zJ2..PrincOps.zJ9] => pc _ [pc + 1]; PrincOps.zJW => pc _ [pc + 3]; ENDCASE; }; }; GetFrame: PROC [link: PrincOps.ControlLink] RETURNS [PrincOps.FrameHandle] = { DO IF ~link.proc THEN IF link.indirect THEN link _ link.link^ ELSE --frame link-- RETURN[link.frame] ELSE RETURN[PrincOps.NullFrame]; ENDLOOP; }; Initialize: PROCEDURE = { pSD: POINTER TO ARRAY [0..0) OF UNSPECIFIED _ PrincOps.SD; pSD[PrincOps.sSignalList] _ SignalList; pSD[PrincOps.sSignal] _ Signal; pSD[PrincOps.sErrorList] _ ErrorList; pSD[PrincOps.sError] _ Error; pSD[PrincOps.sReturnErrorList] _ ReturnErrorList; pSD[PrincOps.sReturnError] _ ReturnError; pSD[PrincOps.sUnnamedError] _ UnnamedError; }; Initialize[]; END. ξSignalsImpl.mesa last edited by Levin on September 20, 1983 11:14 am Types and Related Declarations Global Variables (protected by monitor) Exported to RuntimeError Language support routines Internal Procedures catchFrame is waiting to execute its exit jump We want to be able to RESUME UNCAUGHT, but we don't want a random catch phrase to do so. So, we declare it to be an ERROR in the interface, but raise it as a SIGNAL here. When (if) UNCAUGHT percolates to the top of the stack, it is implicitly resumed (see the preceding line of code). Control then passes to the statement following the invocation of UNCAUGHT, which calls the debugger (or whatever). code[pc] points at zCatch MarkSignalHandlerFrame[FALSE]; Initialization Κ Y– "Cedar" style˜Jšœ™J™3J˜šΟk ˜ Jšœœœ˜Jšœœ˜šœ œ˜JšœΟcœ@œ™˜…—šœœ˜Jšœb˜b—Jšœ œ ˜J˜—šœ ˜Jšœ˜Jšœ ˜'J˜—Jš˜J˜J™Jšœ™J™Jšœœ œ˜J˜Jšœœœœ˜5JšΟn œœ œœœœœœ˜JJšŸ œœ œ˜ J˜šœ œœ˜J˜J˜J˜J˜—J™'J™Jšœ#œ˜'J™Jšœ™J™Jš œœœœ œ œœ˜GJšœ œœœ˜"Jšœœœ œœœœ œœ˜XJ˜š Ÿœœœœ œœ˜BJšœœ˜Jšœœ˜ Jšœ˜—J˜šŸœœœœ˜MJšœE˜LJ™—J™J™Jšœ™J™šŸœœ œœœœ  œ˜FJšœœ˜J˜Jšœ ˜Jšœ˜J˜—šŸ œœ œœœœ œœ œ˜UJšœœ˜˜Jšœ!˜'—J˜Jšœ ˜Jšœ˜J˜—šŸ œœ œœœœ  œ˜LJ˜>J˜/Jšœœ˜Jšœ œ ˜FJ˜Jšœ ˜Jšœ˜J˜—šŸœœ˜Jšœœœœœ œœ œ˜DJšœ>˜>Jšœ/˜/Jšœœ˜šœ˜Jšœœ=˜EJšœ˜—Jšœ˜Jšœ˜Jšœ ˜Jšœ˜J˜—šŸ œœ˜Jšœœ˜Jšœœ ˜ Jšœ ˜Jšœ˜J˜—šŸœœ œœœœ  œ˜GJšœœ˜J˜Jšœ˜J˜—šŸ œœ œœœœ œœ œ˜VJšœœ˜Jšœ œ!˜GJšœ˜Jšœ˜—J˜J™Jšœ™J˜š Ÿœœ œœœ˜;Jšœ˜šœ ˜ JšžK˜KJšœ˜—Jšœ˜J˜—šŸ œœ˜Jšœœœœœ  œœœ˜VJ˜Jš œ œœœœ˜4J˜J˜'J˜)J˜:J˜J˜J˜Jšœ œ˜Jšœ œ˜Jšœœ˜J˜!J˜!J˜Jšœœœ˜1J˜Bš˜J˜šœ˜J˜šœ2œ œ˜IJšœœ˜1šœ œ˜šœ˜%šœ œ˜'Jšœ˜Jšœ˜——šœœ˜!šœœ˜8J˜4—Jšœ(˜(Jšœ˜—J˜'Jšœ˜—š˜šœ œ ˜2šœ˜Jšœ˜Jšœ˜—š˜šœ˜Jšœ˜Jšœ˜————Jšœ˜—Jšœ(˜,Jšœ œœ˜AJ˜9šœ œ˜Jšœ/˜/˜J˜J˜ J˜˜J˜<——šœ œ˜(š œœ œœœœ˜/Jšœœ˜,——Jšœ œ˜šœ˜Jšœ œ˜˜ šœ ˜ Jšœœ ˜šœ˜Jšœ0˜0J˜&Jšœœ ˜Jšœ˜———˜šœœ˜Jšœ.™.J˜Jšœ˜Jšœ œ'˜8J˜Jšœ œ œ˜!Jšœœ ˜Jšœ˜——Jšœ˜—Jšœ˜—šœ œ˜Jšœœ˜(Jšœ œœ&˜OJšœ˜Jšœ˜—š˜Jšœœ˜Jšœ˜—Jšœ˜—Jšœ˜—šœœ˜J˜ Jš œœ œœœž˜Qšœ˜ Jšœ’™’Jšœ œœœœœœ œ˜>Jšœœ˜.Jšœ#˜#J˜——Jšœ˜J˜—šŸ œœ˜.Jšœœ œ˜CJšœœœœœœœœ˜2Jšœœ˜Jšœ0˜0J˜š˜šœ ˜Jšœ"œœ˜.Jšœ!˜!Jšœœœ˜'—Jšœ˜—šœ œ˜Jšœ™J˜šœ˜Jšœ˜Jšœ/˜1Jšœ˜Jšœ˜—Jšœ˜—Jšœ˜J˜—šŸœœœ˜OJšœ™š˜šœ ˜Jšœœ˜'Jšœžœœ ˜&—Jšœœ˜ Jšœ˜—Jšœ˜J˜J˜J˜—Jšœ™J˜šŸ œ œ˜Jš œœœœœ œ œ˜:J˜'J˜J˜%J˜J˜1J˜)J˜+Jšœ˜J˜—J˜ J˜Jšœ˜J˜J˜—…—&*m