-- file: BackStop.Mesa -- edited by Levin, March 13, 1981 4:44 PM -- edited by Schroeder, March 15, 1981 2:45 PM -- edited by Brotz, March 6, 1981 2:22 PM DIRECTORY Ascii, ControlDefs, crD: FROM "CoreDefs", DiskDefs, drD: FROM "LaurelDriverDefs", dsD: FROM "DisplayDefs", Editor, exD: FROM "ExceptionDefs", FrameOps, gsD: FROM "GlobalStorageDefs", ImageDefs, inD: FROM "InteractorDefs", Inline, intCommon: FROM "IntCommon", ModuleName, ovD: FROM "OverviewDefs", PupDefs, SegmentDefs, SDDefs, String, TrapDefs, vmD: FROM "VirtualMgrDefs"; BackStop: PROGRAM IMPORTS crD, DiskDefs, dsD, Editor, exD, FrameOps, gsD, ImageDefs, Inline, intC: intCommon, inD, ModuleName, PupDefs, SegmentDefs, String, TrapDefs, vmD EXPORTS drD SHARES inD = PUBLIC BEGIN OPEN inD; recursionDepth: INTEGER _ -1; oldSignalMessage: STRING _ "Signal lost."; PupTrouble: ERROR[why: UNSPECIFIED] = CODE; -- ProcessBugReport is called during initialization if a /b switch is encountered. ProcessBugReport: PROCEDURE = BEGIN error: ovD.ErrorCode; state: {initial, firstCR, endOfHeader, secondCR} _ initial; selectionStart, selectionEnd: CARDINAL; mnp: inD.MessageTextNbrPtr = intC.cmTextNbr; message: vmD.ComposeMessagePtr = LOOPHOLE[mnp.message]; modelessEditor: BOOLEAN = (intC.editorType = modeless); [error, ] _ vmD.InsertFileInMessage[0, message, "Laurel.BugReport$"L, intC.user]; IF error = ovD.ok THEN BEGIN i: ovD.CharIndex; char: CHARACTER; FOR i IN [0 .. vmD.GetMessageSize[message]) DO char _ vmD.GetMessageChar[message, i]; SELECT state FROM initial => IF char = Ascii.CR THEN state _ firstCR; firstCR => IF char = Ascii.CR THEN {state _ endOfHeader; selectionStart _ i+1} ELSE state _ initial; endOfHeader => IF char = Ascii.CR THEN state _ secondCR; secondCR => IF char = Ascii.CR THEN {selectionEnd _ i-1; EXIT} ELSE state _ endOfHeader; ENDCASE; REPEAT FINISHED => GO TO MalFormedMessage; ENDLOOP; intC.target _ inD.TextSelection [mnp: mnp, start: selectionStart, end: selectionEnd, point: selectionStart, mode: char, pendingDelete: intC.editorType = modeless]; intC.newTargetSelection _ TRUE; intC.pendingDeleteSetByControl _ FALSE; Editor.SetHighWaterMark[0]; mnp.haveMessage _ TRUE; IF modelessEditor THEN inD.StopBlinkingCaret[]; Editor.RefreshSoThatFirstCharStartsLine[firstChar: 0, firstLine: mnp.lines, mnp: mnp]; IF modelessEditor THEN inD.SetCaretBlinking[selectionStart, mnp]; END ELSE GO TO MalFormedMessage; EXITS MalFormedMessage => exD.DisplayException[exception: exD.noBugReportFile]; END; -- of ProcessBugReport -- CapturePupGlitch: PROCEDURE[why: UNSPECIFIED -- DriverDefs.GlitchType --] = BEGIN ERROR PupTrouble[why]; END; -- of CapturePupGlitch -- -- "Streaming" Procedures maxChars: CARDINAL = 512; buffer: POINTER TO PACKED ARRAY [0..maxChars) OF CHARACTER _ NIL; charsInBuffer: [0..maxChars]; currentPage: CARDINAL; fileH: crD.UFileHandle _ NIL; CantMessWithFile: ERROR = CODE; OpenFile: PROCEDURE [fileName: STRING] = BEGIN error: ovD.ErrorCode; [error, fileH] _ crD.OpenFile[intC.user, fileName, update]; IF error # ovD.ok THEN ERROR CantMessWithFile; error _ crD.UFileTruncate[0, 0, fileH]; IF error # ovD.ok THEN ERROR CantMessWithFile; currentPage _ charsInBuffer _ 0; IF buffer = NIL THEN buffer _ gsD.GetMemoryPages[1]; END; -- of OpenFile -- CloseFile: PROCEDURE = BEGIN error: ovD.ErrorCode; IF charsInBuffer # 0 THEN BEGIN error _ crD.WritePages[buffer, charsInBuffer, currentPage, fileH]; IF error # ovD.ok THEN ERROR CantMessWithFile; END; [error] _ crD.CloseFile[fileH]; fileH _ NIL; IF error # ovD.ok THEN ERROR CantMessWithFile; END; -- of CloseFile -- WriteChar: PROCEDURE [c: CHARACTER] = BEGIN error: ovD.ErrorCode; IF charsInBuffer = maxChars THEN BEGIN error _ crD.WritePages[buffer, maxChars, currentPage, fileH]; IF error # ovD.ok THEN ERROR CantMessWithFile; currentPage _ currentPage+1; charsInBuffer _ 0; END; buffer[charsInBuffer] _ c; charsInBuffer _ charsInBuffer+1; END; -- of WriteChar -- WriteString: PROCEDURE[s: STRING] = BEGIN i: CARDINAL; FOR i IN [0..s.length) DO WriteChar[s[i]]; ENDLOOP; END; -- of WriteString -- -- Message Formatting Procedures StuffOctal: PROCEDURE [value: UNSPECIFIED, s: STRING, start: CARDINAL, places: CARDINAL _ 6] = BEGIN FOR i: CARDINAL DECREASING IN [start..start+places) DO digit: CARDINAL; [value, digit] _ Inline.DIVMOD[value, 8]; s[i] _ LOOPHOLE[digit + 60B, CHARACTER]; ENDLOOP; END; -- of StuffOctal -- DumpCallStack: PROCEDURE = BEGIN OPEN ControlDefs; moduleName: STRING _ [20]; pcTemplate: STRING _ ", xxxxxx "L; localFrame: ControlLink _ FrameOps.MyLocalFrame[].returnlink; THROUGH [0..100) DO SELECT localFrame.tag FROM frame => BEGIN OPEN f:localFrame.frame; IF @f = NullFrame THEN EXIT; ModuleName.ControlLinkToModuleName[localFrame, moduleName]; WriteString[moduleName]; IF f.pc < 0 THEN StuffOctal[(-f.pc)*2+1,pcTemplate,2] ELSE StuffOctal[(f.pc)*2,pcTemplate,2]; WriteString[pcTemplate]; localFrame _ f.returnlink; END; ENDCASE => BEGIN WriteString["Stack end "L]; ModuleName.ControlLinkToModuleName[localFrame, moduleName]; WriteString[moduleName]; WriteChar[Ascii.CR]; EXIT; END; ENDLOOP; WriteChar[Ascii.CR]; END; -- of DumpCallStack -- WriteGoryDetails: PROCEDURE = BEGIN OPEN SegmentDefs; s: STRING _ " (nnn#nnn#) with "L; rest: STRING _ "MDS: nn Banks: nnnnnn"L; ucode: STRING _ " code: nnnnnn"L; me: PupDefs.PupAddress; WriteString[" "L]; WriteString[ SELECT memConfig.AltoType FROM AltoI => "Alto I"L, AltoII => "Alto II"L, AltoIIXM => "Alto II XM"L, D0 => "Dolphin"L, Dorado => "Dorado"L, ENDCASE => "IBM 360/15"L]; PupDefs.GetPupAddress[@me, "ME"L]; StuffOctal[me.net, s, 2, 3]; StuffOctal[me.host, s, 6, 3]; WriteString[s]; IF memConfig.AltoType < D0 THEN WriteString[SELECT memConfig.controlStore FROM Ram0 => "Ram only "L, RamandRom => "2K Rom "L, Ram3k => "3K Ram "L, ENDCASE => "Paper tape "L]; IF memConfig.xmMicroCode THEN WriteString["XMcode "L]; IF memConfig.useXM THEN WriteString["using XM "L]; StuffOctal[memConfig.mdsBank, rest, 5, 2]; StuffOctal[memConfig.banks, rest, 15]; WriteString[rest]; IF memConfig.AltoType < D0 THEN {StuffOctal[memConfig.mesaMicrocodeVersion, ucode, 8]; WriteString[ucode]}; END; -- of WriteGoryDetails -- Oops: PROCEDURE = BEGIN exD.FlashExceptionsRegion[]; UNTIL UserWants[] = terminate DO ENDLOOP; -- Die[]; END; -- of Oops -- Die: PROCEDURE = BEGIN dsD.DCBorg^ _ LOOPHOLE[0]; -- keep display tidy ImageDefs.StopMesa[]; END; -- of Die -- UserWants: PROCEDURE RETURNS[{tryIt,terminate}] = BEGIN mouseButton: POINTER TO UNSPECIFIED = LOOPHOLE[177030B]; redBlue: UNSPECIFIED = 4+2; yellow: UNSPECIFIED = 1; UNTIL Inline.BITAND[mouseButton^,yellow] = 0 DO IF Inline.BITAND[mouseButton^,redBlue] = 0 THEN RETURN[terminate]; ENDLOOP; RETURN[tryIt]; END; -- of UserWants -- Catcher: PROCEDURE [msg: UNSPECIFIED, signal: SIGNAL[UNSPECIFIED], frame: ControlDefs.FrameHandle] = BEGIN i: CARDINAL; savedCursor: ARRAY [0 .. 15] OF CARDINAL; pCursor: POINTER TO ARRAY [0 .. 15] OF CARDINAL = LOOPHOLE[431B]; errorCursor: ARRAY [0 .. 15] OF CARDINAL = [34034B, 42042B, 101102B, 101202B, 101204B, 42210B, 34160B, 0, 176174B, 101202B, 101200B, 176174B, 100002B, 100202B, 100174B, 0]; moduleName: STRING _ [20]; twoCRs: STRING _ " "L; headerPart: STRING _ "Subject: Error Report To: "L; bodyPart: STRING _ "Please replace this paragraph with a brief description of what you were doing when Laurel broke, then ""Deliver"" this message. (Be sure to include the last command you invoked.) After the message is delivered, you can continue to use Laurel as usual."L; parityErrorMessage: STRING _ "Parity error at ??????."L; -- 28 spaces required after msg^ signalMessage: STRING _ "Signal xxxxxx in "L; msgMessage: STRING _ "msg xxxxxx, msg^ "L; SELECT (recursionDepth _ recursionDepth+1) FROM 0 => NULL; 1 => BEGIN exceptionString: STRING _ [exD.maxExceptionStringLength]; pCursor^ _ errorCursor; exD.GetExceptionString[exD.recursiveTrouble, exceptionString]; String.AppendString[exceptionString, intC.bugReportee]; exD.AppendExceptionString[exD.mustEndSession, exceptionString]; exD.DisplayExceptionStringOnLine[exceptionString, 1]; exD.DisplayExceptionStringOnLine[oldSignalMessage, 2]; Oops[]; END; ENDCASE => DO ENDLOOP; savedCursor _ pCursor^; pCursor^ _ errorCursor; SELECT signal FROM LOOPHOLE[TrapDefs.PhantomParityError, SIGNAL[UNSPECIFIED]], TrapDefs.ParityError => BEGIN IF signal = TrapDefs.ParityError THEN StuffOctal[msg, parityErrorMessage, 16]; exD.DisplayExceptionStringOnLine[parityErrorMessage, 1]; exD.DisplayExceptionLine[exD.tryToContinue, 2]; exD.FlashExceptionsRegion[]; IF UserWants[] = terminate THEN Die[]; pCursor^ _ savedCursor; recursionDepth _ -1; exD.ClearExceptionsRegion[]; intC.timeMayBeBogus _ TRUE; RETURN; --resume the parity error END; exD.SysBugSignal => IF ~LOOPHOLE[msg, BOOLEAN] THEN Oops[]; LOOPHOLE[DiskDefs.UnrecoverableDiskError, SIGNAL[UNSPECIFIED]] => BEGIN exD.DisplayExceptionLine[exD.unrecDiskError, 1]; exD.DisplayExceptionLine[exD.cannotProceed, 2]; Oops[]; END; ENDCASE; --remember this instance of signalMessage for possible recursive error oldSignalMessage _ signalMessage; --prepare signal message StuffOctal[signal, signalMessage, 7]; ModuleName.ControlLinkToModuleName[LOOPHOLE[signal], moduleName]; StuffOctal[msg, msgMessage, 4]; IF LOOPHOLE[msg, CARDINAL] > 1400B THEN FOR i _ 17, i + 7 WHILE i < 39 DO StuffOctal[LOOPHOLE[msg + (i - 17) / 7, POINTER]^, msgMessage, i]; ENDLOOP; exD.DisplayExceptionLine[exD.systemError, 1]; exD.DisplayExceptionLine[exD.autoErrorReport, 2]; exD.FlashExceptionsRegion[]; IF UserWants[] = terminate THEN Die[]; dsD.SetCursor[hourGlass]; OpenFile["Laurel.BugReport$"L]; WriteString[headerPart]; WriteString[intC.bugReportee]; WriteString[twoCRs]; WriteString[bodyPart]; WriteString[twoCRs]; WriteString[intC.versionHouse.text]; WriteGoryDetails[]; WriteString[twoCRs]; WriteString[signalMessage]; WriteString[moduleName]; WriteChar[Ascii.CR]; WriteString[msgMessage]; WriteString[twoCRs]; DumpCallStack[]; CloseFile[]; IF intC.imageFileName # NIL THEN BEGIN OpenFile["Rem.cm"L]; WriteString[intC.imageFileName]; WriteString["/b"L]; WriteChar[Ascii.CR]; CloseFile[]; END; Die[]; END; -- of Catcher -- END. -- of BackStop --z20461q(529)\f1