MicroDDebugging.mesa:
Copyright © 1986 by Xerox Corporation. All rights reserved.
Willie-Sue, July 29, 1987 4:32:25 pm PDT

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;
block types
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
name starts here - memory name
];
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
name starts here - memory name
];
MBAddress: TYPE = MACHINE DEPENDENT RECORD[
memNum: CARDINAL,  -- memory number
value: CARDINAL   -- address value
name starts here - address symbol name
];
MBUndefined: TYPE = MACHINE DEPENDENT RECORD[
memNum: CARDINAL, -- memory number
location: CARDINAL,  -- location in memory
firstBit: BYTE,   -- field to be stored into
lastBit: BYTE
name starts here - external symbol name
];
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 TEXTNEW[TEXT[RefText.line]];
IMsize: CARDINAL = 4096;
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Fa: Commander.CommandProc = {
argV: CommandTool.ArgumentVector ← CommandTool.Parse[cmd];
tsStream: STREAMNIL;
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: STREAMNIL;
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: STREAMNIL;
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: STREAMNIL;
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: STREAMNIL;
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: STREAMNIL;
inFileQ, lastInFile: InFile ← NIL;
lastSwitchWasI: BOOLTRUE;
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 CARDINALALL[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;
tsStream.PutRope[IO.PutFR["addr %4b: ", IO.int[addr]] ];
FOR i: CARDINAL IN [0..memoryWidths[memNum]) DO
n ← GetWord[readStream];
tsStream.PutF[" %06b", IO.card[n]];
ENDLOOP;
IF memNum = imMemNo THEN {
offset: WORD ← Basics.BITAND[n, 7777B];
TRUSTED {(realToImagAddr+offset)^ ← addr };
};
addr ← addr + 1;
tsStream.PutChar['\n];
};
mbMemory => {
memNum ← GetWord[readStream];
addr ← GetWord[readStream];
tsStream.PutRope[
IO.PutFR["\n**memNo: %g, addr: %b\n", IO.card[memNum], IO.card[addr]]];
};
mbFixup => {
tsStream.PutRope["\n ****Fixup block encountered in MB file\n"];
RETURN
};
mbMemoryName => {
newMemoryNum: CARDINAL ← GetWord[readStream];
width: CARDINAL ← GetWord[readStream];
val: WORDLOOPHOLE[(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];
tsStream.PutRope[IO.PutFR[" Memory: %g\n", IO.text[textLine]] ];
};
mbAddress => {
memNo: WORD ← GetWord[readStream];
addrValue ← GetWord[readStream];
ReadName[readStream, textLine];
tsStream.PutF[" %g:\t%b (%g)\n",
IO.text[textLine], IO.card[addrValue], IO.card[memNo] ];
};
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] = {
Converts from the MB name format to a normal 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.