<> <> <> DIRECTORY Basics, Commander, CommandTool, Convert USING [Error, CardFromRope, IntFromRope], FS, IO, Process, RefText, Rope, ViewerClasses USING [Viewer], ViewerIO USING [CreateViewerStreams], ViewerOps USING [FindViewer, OpenIcon], VM, MDADefs, MDDefs, MDGlobalVars, MDUtils; MicroDDebugging: CEDAR PROGRAM IMPORTS Basics, Commander, CommandTool, Convert, FS, IO, Process, RefText, Rope, ViewerIO, ViewerOps, VM, MDGlobalVars, MDUtils = BEGIN ROPE: TYPE = Rope.ROPE; STREAM: TYPE = IO.STREAM; Viewer: TYPE = ViewerClasses.Viewer; realToImagAddr: LONG POINTER TO CARDINAL; <> BlockType: TYPE = MACHINE DEPENDENT { mbEnd(0), -- end of MB file mbData(1), -- store memory data and increment location mbMemory(2), -- set memory number and location mbFixup(3), -- forward reference fixup mbMemoryName(4), -- correlate memory name and number mbAddress(5), -- define address symbol mbUndefined(6) -- external reference }; MBHeader: TYPE = MACHINE DEPENDENT RECORD[ blank: BYTE, -- used in Midas MB files, but not in normal ones type: BlockType -- block type ]; MBData: TYPE = MACHINE DEPENDENT RECORD[ sourceLine: CARDINAL, -- source line number value: CARDINAL -- left-adjusted data starts here ]; MBMemory: TYPE = MACHINE DEPENDENT RECORD[ memNum: CARDINAL, -- memory number location: CARDINAL -- first location in memory <> ]; MBFixup: TYPE = MACHINE DEPENDENT RECORD[ memNum: CARDINAL, -- memory number location: CARDINAL, -- location in memory firstBit: BYTE, -- field to be stored into lastBit: BYTE, value: CARDINAL -- value to be stored ]; MBMemoryName: TYPE = MACHINE DEPENDENT RECORD[ memoryNum: CARDINAL, -- memory number width: CARDINAL -- memory width <> ]; MBAddress: TYPE = MACHINE DEPENDENT RECORD[ memNum: CARDINAL, -- memory number value: CARDINAL -- address value <> ]; MBUndefined: TYPE = MACHINE DEPENDENT RECORD[ memNum: CARDINAL, -- memory number location: CARDINAL, -- location in memory firstBit: BYTE, -- field to be stored into lastBit: BYTE <> ]; maxMemoryNum: CARDINAL = 50; finished: ROPE = "\n ~~~~~~~ Finished ~~~~~~~\n"; -- * * * * * * * * * * * * * * ** * * * * * * * * * * * * * * InFile: TYPE = REF InFileRec; InFileRec: TYPE = RECORD [ -- Input file descriptor next: InFile, name: ROPE, -- -> complete file name string stream: STREAM, startAddr: INTEGER _ -1 -- microcode starting address for this overlay ]; herald: ROPE = "\n * * * * * MicroD Debugging of May 6, 1986 * * * * * *"; mdd: ROPE = "MicroD Debugging"; textLine: REF TEXT _ NEW[TEXT[RefText.line]]; IMsize: CARDINAL = 4096; -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Fa: Commander.CommandProc = { argV: CommandTool.ArgumentVector _ CommandTool.Parse[cmd]; tsStream: STREAM _ NIL; addr, bl: CARDINAL; ai: INT; tsStream _ TSStream[mdd]; addr _ Convert.CardFromRope[argV[1] ! Convert.Error => { addr _ 17777B; CONTINUE} ]; IF addr = 17777B THEN RETURN; tsStream.PutF[" Following aLinks from %bb\n %bb", IO.card[addr], IO.card[addr]]; bl _ addr; ai _ addr; DO ii: INT; TRUSTED { bl _ MDUtils.IMPtr[bl].links.aLink }; ii _ bl; tsStream.PutF[" => %bb (%g)", IO.card[bl], IO.int[ii-ai]]; IF bl = addr THEN EXIT; ENDLOOP; tsStream.PutChar['\n]; }; Fb: Commander.CommandProc = { argV: CommandTool.ArgumentVector _ CommandTool.Parse[cmd]; tsStream: STREAM _ NIL; addr, bl: CARDINAL; ai: INT; tsStream _ TSStream[mdd]; addr _ Convert.CardFromRope[argV[1] ! Convert.Error => { addr _ 17777B; CONTINUE} ]; IF addr = 17777B THEN RETURN; tsStream.PutF[" Following bLinks from %bb\n %bb", IO.card[addr], IO.card[addr]]; bl _ addr; ai _ addr; DO ii: INT; TRUSTED { bl _ MDUtils.IMPtr[bl].word2.W2AddrAndbLink }; ii _ bl; tsStream.PutF[" => %bb (%g)", IO.card[bl], IO.int[ii-ai]]; IF bl = addr THEN EXIT; ENDLOOP; tsStream.PutChar['\n]; }; Fg: Commander.CommandProc = { argV: CommandTool.ArgumentVector _ CommandTool.Parse[cmd]; tsStream: STREAM _ NIL; addr, bl: CARDINAL; ai: INT; tsStream _ TSStream[mdd]; addr _ Convert.CardFromRope[argV[1] ! Convert.Error => { addr _ 17777B; CONTINUE} ]; IF addr = 17777B THEN RETURN; tsStream.PutF[" Following groupLinks from %bb\n %bb", IO.card[addr], IO.card[addr]]; bl _ addr; ai _ addr; DO ii: INT; TRUSTED { bl _ MDUtils.IMPtr[bl].word1.W1AddrAndGroupLink }; ii _ bl; tsStream.PutF[" => %bb (%g)", IO.card[bl], IO.int[ii-ai]]; IF bl = addr THEN EXIT; ENDLOOP; tsStream.PutChar['\n]; }; Cpr: Commander.CommandProc = { argV: CommandTool.ArgumentVector _ CommandTool.Parse[cmd]; tsStream: STREAM _ NIL; start: INT _ 0; num: INT _ 64; -- one page worth notUsed, dif: INT _ 0; tsStream _ TSStream[mdd]; FOR i: NAT IN [1..argV.argc) DO this: ROPE _ argV[i]; n: INT _ -1; n _ Convert.IntFromRope[this ! Convert.Error => { num _ -1; CONTINUE} ]; IF n = -1 THEN LOOP; IF i = 1 THEN start _ n ELSE IF i = 2 THEN num _ n; ENDLOOP; tsStream.PutF["*** Start: %bb, num: %g\n\n", IO.int[start], IO.int[num] ]; FOR j: INT IN [start..start+num) DO TRUSTED { md: CARDINAL = (MDGlobalVars.realToImagAddrs+j)^; IF md = 177777B THEN { notUsed _ notUsed + 1; LOOP }; -- not yet assigned IF md = (realToImagAddr+j)^ THEN LOOP; dif _ dif + 1; tsStream.PutF["Addr: %b, MicroD: %b, .mbFile: %b\n", IO.card[j], IO.card[(MDGlobalVars.realToImagAddrs+j)^], IO.card[(realToImagAddr+j)^]]; }; ENDLOOP; tsStream.PutF[" %bb unassigned locations, %g mismatches\n", IO.int[notUsed], IO.int[dif]]; tsStream.PutRope[finished]; }; Wb: Commander.CommandProc = { argV: CommandTool.ArgumentVector _ CommandTool.Parse[cmd]; tsStream: STREAM _ NIL; wBuf: LONG POINTER TO CARDINAL; xSub: LONG POINTER TO CARDINAL; start: CARDINAL; tsStream _ TSStream[mdd]; FOR i: NAT IN [1..argV.argc) DO this: ROPE _ argV[i]; n: INT _ -1; n _ Convert.IntFromRope[this ! Convert.Error => { n _ -1; CONTINUE} ]; IF n = -1 THEN LOOP; IF i = 1 THEN wBuf _ LOOPHOLE[n] ELSE IF i = 2 THEN start _ n; ENDLOOP; tsStream.PutF[ "*** WBuf: %bb, baseAddr: %bb\n\n", IO.card[LOOPHOLE[wBuf]], IO.card[start] ]; xSub _ wBuf; TRUSTED { UNTIL xSub^ = 0 DO sub: MDADefs.SubPage = LOOPHOLE[xSub]; tsStream.PutF["%bB:", IO.card[xSub^]]; FOR j: CARDINAL IN [0..sub.subPageHeader.length) DO tsStream.PutF[" %bB", IO.card[(xSub+SIZE[MDADefs.SubPageHeader]+j)^ - start]]; ENDLOOP; tsStream.PutChar['\n]; xSub _ LOOPHOLE[xSub + SIZE[MDADefs.SubPageHeader] + sub.subPageHeader.length]; ENDLOOP; }; }; Ras: Commander.CommandProc = { DoIt[cmd, TRUE] }; Cas: Commander.CommandProc = { DoIt[cmd, FALSE] }; DoIt: PROC[cmd: Commander.Handle, readOnly: BOOL] = { argV: CommandTool.ArgumentVector _ CommandTool.Parse[cmd]; tsStream: STREAM _ NIL; inFileQ, lastInFile: InFile _ NIL; lastSwitchWasI: BOOL _ TRUE; tsStream _ TSStream[mdd]; tsStream.PutRope[herald]; FOR i: NAT IN [1..argV.argc) DO this: ROPE _ argV[i]; IF this.Fetch[0] = '- THEN { -- switch SELECT this.Fetch[1] FROM 'I, 'i => lastSwitchWasI _ TRUE; 'O, 'o => lastSwitchWasI _ FALSE; ENDCASE => tsStream.PutF[" **** Undefined local switch: %g\n", IO.char[this.Fetch[1]] ]; } ELSE -- filename IF lastSwitchWasI THEN { -- inFile name: ROPE _ CommandTool.FileWithSearchRules[this, ".mb", cmd, FALSE]; thisFile: InFile _ NEW[InFileRec _ [name: name]]; IF inFileQ = NIL THEN inFileQ _ lastInFile _ thisFile ELSE {lastInFile.next _ thisFile; lastInFile _ thisFile}; }; ENDLOOP; IF inFileQ = NIL THEN { tsStream.PutRope["**** No input file(s) specified\n"]; RETURN }; TRUSTED {Process.Detach[FORK DoRead[inFileQ, tsStream, readOnly] ] }; }; DoRead: PROC[inFileQ: InFile, tsStream: STREAM, readOnly: BOOL ] = { IF realToImagAddr = NIL THEN { buf: LONG POINTER _ VM.AddressForPageNumber[VM.SimpleAllocate[VM.PagesForWords[IMsize]].page]; realToImagAddr _ LOOPHOLE[buf]; }; FOR i: CARDINAL IN [0..IMsize) DO TRUSTED { (realToImagAddr+i)^ _ 177777B }; ENDLOOP; FOR inF: InFile _ inFileQ, inF.next UNTIL inF = NIL DO BEGIN msg: ROPE; readStream: STREAM; readStream _ FS.StreamOpen[inF.name ! FS.Error => { tsStream.PutRope[error.explanation]; GOTO cant} ]; tsStream.PutRope[msg _ IO.PutFR["\n\n ******* Reading %g\n\n", IO.rope[inF.name]] ]; ReadMBFile[readStream, tsStream]; readStream.Close[]; EXITS cant => NULL; END; ENDLOOP; IF ~readOnly THEN TRUSTED { FOR i: CARDINAL IN [0..IMsize) DO IF (MDGlobalVars.realToImagAddrs+i)^ = (realToImagAddr+i)^ THEN LOOP; tsStream.PutF["Addr: %b, MicroD: %b, .mbFile: %b\n", IO.card[i], IO.card[(MDGlobalVars.realToImagAddrs+i)^], IO.card[(realToImagAddr+i)^]]; ENDLOOP; }; tsStream.PutRope[finished]; }; -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ReadMBFile: PROC[readStream, tsStream: STREAM] = { memNum: CARDINAL _ 0; addr, addrValue: CARDINAL _ 0; blockType: BlockType; memoryWidths: ARRAY [0..maxMemoryNum) OF CARDINAL _ ALL[0]; imMemNo: CARDINAL _ 177777B; imName: ROPE = "IM"; DO [] _ readStream.GetChar[]; -- the blank byte blockType _ LOOPHOLE[readStream.GetChar[]]; SELECT blockType FROM mbEnd => RETURN; mbData => { sourceLine: CARDINAL _ GetWord[readStream]; n: WORD; <> FOR i: CARDINAL IN [0..memoryWidths[memNum]) DO n _ GetWord[readStream]; <> ENDLOOP; IF memNum = imMemNo THEN { offset: WORD _ Basics.BITAND[n, 7777B]; TRUSTED {(realToImagAddr+offset)^ _ addr }; }; addr _ addr + 1; <> }; mbMemory => { memNum _ GetWord[readStream]; addr _ GetWord[readStream]; <> <> }; mbFixup => { tsStream.PutRope["\n ****Fixup block encountered in MB file\n"]; RETURN }; mbMemoryName => { newMemoryNum: CARDINAL _ GetWord[readStream]; width: CARDINAL _ GetWord[readStream]; val: WORD _ LOOPHOLE[(width + 15)]; ReadName[readStream, textLine]; IF imName.Equal[RefText.TrustTextAsRope[textLine], FALSE] THEN imMemNo _ newMemoryNum; IF newMemoryNum > maxMemoryNum THEN { tsStream.PutF["New MemoryNum %g is out of bounds\n", IO.card[newMemoryNum]]; RETURN }; memoryWidths[newMemoryNum] _ Basics.BITSHIFT[val, -4]; <> }; mbAddress => { memNo: WORD _ GetWord[readStream]; addrValue _ GetWord[readStream]; ReadName[readStream, textLine]; <> <> }; mbUndefined => { tsStream.PutRope["***** Undefined symbol block encountered in MB file\n"]; RETURN }; ENDCASE => { bt: Basics.LongNumber; bt.ll _ LOOPHOLE[blockType, BYTE]; tsStream.PutRope[IO.PutFR[ "*** Unknown block type (%g) in MB file\n", IO.card[LOOPHOLE[bt]]] ]; RETURN }; ENDLOOP; }; -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ReadName: PROC[in: STREAM, buffer: REF TEXT] = { <> i: INTEGER _ 0; DO char: CHAR _ in.GetChar[]; IF char = '\000 THEN { IF in.GetIndex[] MOD 2 = 1 THEN [] _ in.GetChar[]; -- stream is word (16-bit) oriented EXIT; }; buffer[i] _ char; i _ i + 1; ENDLOOP; buffer.length _ i; }; -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GetWord: PROC[in: STREAM] RETURNS[CARDINAL] = { num: Basics.ShortNumber; num.hi _ LOOPHOLE[in.GetChar[]]; num.lo _ LOOPHOLE[in.GetChar[]]; RETURN[LOOPHOLE[num, CARDINAL]]; }; -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TSStream: PROC[name: ROPE] RETURNS [IO.STREAM] = { v: ViewerClasses.Viewer _ ViewerOps.FindViewer[name]; out: IO.STREAM _ ViewerIO.CreateViewerStreams[name, v].out; IF v#NIL THEN IF v.iconic THEN ViewerOps.OpenIcon[v]; RETURN[out]; }; -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GetIndex: PROC[strm: STREAM] RETURNS[INT] = { RETURN[strm.GetIndex[]] }; -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Commander.Register["Fal", Fa, "Follow alinks"]; Commander.Register["Fbl", Fb, "Follow blinks"]; Commander.Register["Fgl", Fg, "Follow grouplinks"]; Commander.Register["Wb", Wb, "Show WorkingBuffer"]; Commander.Register["Cpr", Cpr, "Compares its own realToImagAddr to MDGlobalVarsImpl.realToImagAddr"]; Commander.Register["Ras", Ras, "Reads a MicroBinary file into its own realToImagAddr"]; Commander.Register["Cas", Cas, "Compares a MicroBinary file with that in MDGlobalVarsImpl.realToImagAddr"]; END.