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 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[];
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;
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: 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];
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.