SoftcardToolQuadIOImpl.mesa
Copyright Ó 1987 by Xerox Corporation. All rights reserved.
Don Curry, March 16, 1987 5:11:02 pm PST
Willie-Sue, April 3, 1987 2:43:54 pm PST
DIRECTORY
AMBridge USING [SomeRefFromTV, TVForReferent],
AMTypes USING [TV],
Buttons USING [Create, ReLabel],
Convert USING [CardFromRope],
DebuggerDefs -- using lots -- ,
DragOpsCross USING [StackedStatusWord],
DragOpsCrossUtils USING [CardToWord],
FS USING [Error, FileInfo, StreamOpen],
Interpreter USING [Evaluate],
IO,
Labels USING [Create, Set],
List USING [CompareProc, Sort],
Process USING [Detach, Milliseconds, PauseMsec],
Rope,
SoftcardOps,
SoftcardToolPrivate,
SymTab USING [Create, Ref, Store],
ViewerTools USING [GetContents, MakeNewTextViewer, SetSelection];
SoftcardToolQuadIOImpl: CEDAR MONITOR
IMPORTS
AMBridge, Interpreter,
Buttons, Convert, DragOpsCrossUtils, FS, IO, Labels, List, Process, Rope, SymTab, ViewerTools,
SoftcardOps, SoftcardToolPrivate,
DD: DebuggerDefs
EXPORTS SoftcardToolPrivate =
BEGIN OPEN SoftcardToolPrivate;
Word: TYPE = CARD32;
STREAM: TYPE = IO.STREAM;
ROPE: TYPE = Rope.ROPE;
Memory: TYPE = REF MemoryRec;
MemoryRec: TYPE = RECORD [
sym: SymTab.Ref, wds: REF MemWords, sortedSyms: REF SortedSyms,
lowestAddr: Word ← 0,
highestAddr: Word ← 0];
MemWords: TYPE = RECORD [SEQUENCE size: CARDINAL OF MemWord];
MemWord: TYPE = RECORD [addr, value: Word];
SortedSyms: TYPE = RECORD [SEQUENCE size: CARDINAL OF SymbolAddr];
SymbolAddr: TYPE = REF SymbolAddrRec;
SymbolAddrRec: TYPE = RECORD [sym: ROPE, addr: Word];
quadMemory: Memory;
quadFileNameText: Viewer;
interpretWhatText, showInterpretResult: Viewer;
debuggerWatcherButton, autoDumpDebuggerButton, autoRestartDebuggerButton: Viewer;
watcherWait: Process.Milliseconds ← 100;
watchingDebugger: BOOLFALSE;
autoDumpDebuggerState: BOOLFALSE;
autoRestartDebugger: BOOLFALSE;
debuggerWatchAddr: CARD32 = DD.debugBase + DD.debuggerProceed;
dumpBaseAddr: CARD32 = DD.debugBase;
numToDump: CARD16 = DD.ifuRegBase + 2*DD.IFUStackSize;
debuggerWatchSCAddr: CARD32 =
 SoftcardToolPrivate.DragonToSoftcardAddr[debuggerWatchAddr];
dumpBaseSCAddr: CARD32 = SoftcardToolPrivate.DragonToSoftcardAddr[dumpBaseAddr];
debuggerState: SoftcardOps.SeqLong;
BuildQuadIOButtons: PUBLIC PROC[topViewer, sibx: Viewer] RETURNS[sib: Viewer] = {
sib ← sibx;
Load Quad file (dragon code)
sib ← Buttons.Create[
info: [ name: " LoadQuadFile ", parent: topViewer,
 wx: leftEdge, wy: sib.wy+sib.wh+betweenHeight, wh: entryHeight,
 border: TRUE, scrollable: FALSE],
font: activeFont, proc: LoadQuadFileProc ];
sib ← Buttons.Create[
info: [ name: " fileName: ", parent: topViewer,
 wx: sib.wx+sib.ww+xFudge, wy: sib.wy, wh: entryHeight,
 border: FALSE, scrollable: FALSE],
font: selectFont, proc: QuadFileNameProc ];
sib ← quadFileNameText ← ViewerTools.MakeNewTextViewer[
info: [parent: topViewer, wx: sib.wx+sib.ww+xFudge+6, wy: sib.wy,
 ww: 300, wh: entryHeight, border: FALSE, scrollable: FALSE]];
DebuggerWatcher for dragon code
watchingDebugger ← FALSE;
sib ← Labels.Create[
info: [ name: " Debugger ", parent: topViewer,
 wx: leftEdge, wy: sib.wy+sib.wh+betweenHeight, wh: entryHeight,
 border: FALSE, scrollable: FALSE],
font: labelFont ];
sib ← debuggerWatcherButton ← Buttons.Create[
info: [ name: " WatcherOff ", parent: topViewer,
 wx: sib.wx+sib.ww+xFudge, wy: sib.wy, wh: entryHeight,
 border: TRUE, scrollable: FALSE],
font: selectFont, proc: DebuggerWatcherProc ];
autoDumpDebuggerState ← FALSE;
sib ← autoDumpDebuggerButton ← Buttons.Create[
info: [ name: " AutoDumpOff ", parent: topViewer,
 wx: sib.wx+sib.ww+xFudge, wy: sib.wy, wh: entryHeight,
 border: TRUE, scrollable: FALSE],
font: selectFont, proc: AutoDumpDebuggerProc ];
autoRestartDebugger ← FALSE;
sib ← autoRestartDebuggerButton ← Buttons.Create[
info: [ name: " AutoRestartOff ", parent: topViewer,
 wx: sib.wx+sib.ww+xFudge, wy: sib.wy, wh: entryHeight,
 border: TRUE, scrollable: FALSE],
font: selectFont, proc: AutoRestartDebuggerProc ];
sib ← Buttons.Create[
info: [ name: " DumpAllState ", parent: topViewer,
 wx: sib.wx+sib.ww+xFudge, wy: sib.wy, wh: entryHeight,
 border: TRUE, scrollable: FALSE],
font: activeFont, proc: DumpAllDebuggerStateProc ];
sib ← Buttons.Create[
info: [ name: " Restart ", parent: topViewer,
 wx: sib.wx+sib.ww+xFudge, wy: sib.wy, wh: entryHeight,
 border: TRUE, scrollable: FALSE],
font: activeFont, proc: RestartDebuggerProc ];
DebuggerState for dragon code
sib ← Buttons.Create[
info: [ name: " ShowMinState ", parent: topViewer,
 wx: leftEdge+40, wy: sib.wy+sib.wh+betweenHeight, wh: entryHeight,
 border: TRUE, scrollable: FALSE],
font: activeFont, proc: MinStateProc ];
sib ← Buttons.Create[
info: [ name: " EUStack ", parent: topViewer,
 wx: sib.wx+sib.ww+xFudge, wy: sib.wy, wh: entryHeight,
 border: TRUE, scrollable: FALSE],
font: activeFont, proc: EUStackProc ];
sib ← Buttons.Create[
info: [ name: " IFUStack ", parent: topViewer,
 wx: sib.wx+sib.ww+xFudge, wy: sib.wy, wh: entryHeight,
 border: TRUE, scrollable: FALSE],
font: activeFont, proc: IFUStackProc ];
sib ← Buttons.Create[
info: [ name: " EUAuxRegs ", parent: topViewer,
 wx: sib.wx+sib.ww+xFudge, wy: sib.wy, wh: entryHeight,
 border: TRUE, scrollable: FALSE],
font: activeFont, proc: EUAuxRegsProc ];
sib ← Buttons.Create[
info: [ name: " EUConstRegs ", parent: topViewer,
 wx: sib.wx+sib.ww+xFudge, wy: sib.wy, wh: entryHeight,
 border: TRUE, scrollable: FALSE],
font: activeFont, proc: EUConstRegsProc ];
Interpret symbol for dragon code
sib ← Buttons.Create[
info: [ name: " InterpSym ", parent: topViewer,
 wx: leftEdge, wy: sib.wy+sib.wh+betweenHeight, wh: entryHeight,
 border: TRUE, scrollable: FALSE],
font: activeFont, proc: InterpSymbolProc ];
sib ← Buttons.Create[
info: [ name: " InterpAddr ", parent: topViewer,
 wx: sib.wx+sib.ww+xFudge, wy: sib.wy, wh: entryHeight,
 border: TRUE, scrollable: FALSE],
font: activeFont, proc: InterpAddrProc ];
sib ← Buttons.Create[
info: [ name: " what: ", parent: topViewer,
 wx: sib.wx+sib.ww+xFudge, wy: sib.wy, wh: entryHeight,
 border: FALSE, scrollable: FALSE],
font: selectFont, proc: InterpretWhatProc ];
sib ← interpretWhatText ← ViewerTools.MakeNewTextViewer[
info: [parent: topViewer, wx: sib.wx+sib.ww+xFudge, wy: sib.wy,
 ww: 400, wh: entryHeight, border: FALSE, scrollable: FALSE]];
sib ← Labels.Create[
info: [ name: " result: ", parent: topViewer,
 wx: leftEdge+40, wy: sib.wy+sib.wh+betweenHeight, wh: entryHeight,
 border: FALSE, scrollable: FALSE],
font: labelFont ];
sib ← showInterpretResult ← Labels.Create[
info: [ name: " ",
 parent: topViewer,
 wx: sib.wx+sib.ww+xFudge, wy: sib.wy, wh: entryHeight,
 border: FALSE, scrollable: FALSE]
];
RETURN[sib];
};
wordsPerCall: CARD16 ← 1024;
LoadQuadFileProc: ClickProc = {
fName: ROPE ← ViewerTools.GetContents[quadFileNameText];
fullName: ROPE;
numLeft: CARD16 ← 0;
indexThisRound, pushIndex: CARD16 ← 0;
PushAddrVal: PROC RETURNS[addr: SoftcardOps.Addr, value: CARD32] = {
addr ← ByteAddrToSoftcardAddr[quadMemory.wds[pushIndex].addr];
value ← quadMemory.wds[pushIndex].value;
pushIndex ← pushIndex + 1;
};
IF fName.Length[] = 0 THEN {
TSOutPutRope["\n**** Please fill in the name of a quad file\n"];
RETURN
};
IF fName.Find["."] < 0 THEN fName ← fName.Concat[".quad"];
fullName ← FS.FileInfo[name: fName, remoteCheck: FALSE, wDir: regDir
! FS.Error => {
TSOutPutRope[error.explanation];
TSOutPutChar['\n];
GOTO nogood } ].fullFName;
quadMemory ← ReadQuadFile[fullName];
IF quadMemory = NIL THEN RETURN;  -- some error, already reported
numLeft ← quadMemory.wds.size;
WHILE numLeft > wordsPerCall DO
SoftcardOps.WriteMultipleLong[wordsPerCall, PushAddrVal];
numLeft ← numLeft - wordsPerCall;
ENDLOOP;
IF numLeft > 0 THEN SoftcardOps.WriteMultipleLong[numLeft, PushAddrVal];
TSOutPutF["\n\tQuadFile %g (%g instructions) has been loaded\n\n",
[rope[fullName]], [cardinal[quadMemory.wds.size]] ];
EXITS
nogood => NULL;
};
QuadFileNameProc: ClickProc =
{ ViewerTools.SetSelection[quadFileNameText, NIL] };
DebuggerWatcherProc: ClickProc = {
IF DebuggerWatching[changeState: TRUE] THEN
Buttons.ReLabel[debuggerWatcherButton, " WatcherOff "]
ELSE Buttons.ReLabel[debuggerWatcherButton, " WatcherOn "]
};
DebuggerWatching: ENTRY PROC[changeState: BOOL] RETURNS[BOOL] = {
IF ~changeState THEN RETURN[watchingDebugger];
watchingDebugger ← ~watchingDebugger;
RETURN[~watchingDebugger]; -- if changeState return previous value
};
AutoDumpDebuggerProc: ClickProc = {
IF AutoDumpDebuggerState[changeState: TRUE] THEN
Buttons.ReLabel[autoDumpDebuggerButton, " AutoDumpOff "]
ELSE Buttons.ReLabel[autoDumpDebuggerButton, " AutoDumpOn "]
};
AutoDumpDebuggerState: ENTRY PROC[changeState: BOOL] RETURNS[BOOL] = {
IF ~changeState THEN RETURN[autoDumpDebuggerState];
autoDumpDebuggerState ← ~autoDumpDebuggerState;
RETURN[~autoDumpDebuggerState]; -- if changeState still return previous value
};
AutoRestartDebuggerProc: ClickProc = {
IF AutoRestart[changeState: TRUE] THEN
Buttons.ReLabel[autoRestartDebuggerButton, " AutoRestartOff "]
ELSE Buttons.ReLabel[autoRestartDebuggerButton, " AutoRestartOn "]
};
AutoRestart: ENTRY PROC[changeState: BOOL] RETURNS[BOOL] = {
IF ~changeState THEN RETURN[autoRestartDebugger];
autoRestartDebugger ← ~autoRestartDebugger;
RETURN[~autoRestartDebugger]; -- if changeState still return previous value
};
TheWatcherProc: PROC = {
alreadyReported: BOOLFALSE;
DO
BEGIN ENABLE SoftcardOps.SCError => GOTO scError;
IF ~DebuggerWatching[changeState: FALSE] THEN {
alreadyReported ← FALSE;
Process.PauseMsec[watcherWait];
LOOP;
};
IF SoftcardOps.ReadLong[debuggerWatchSCAddr] = 0 THEN {
alreadyReported ← FALSE;
Process.PauseMsec[watcherWait];
LOOP;
};
IF ~alreadyReported THEN {
TSOutPutRope["\n\n***** Debugger is in wait loop\n"];
alreadyReported ← TRUE;
debuggerState ← SoftcardOps.DumpLong[dumpBaseSCAddr, numToDump];
IF AutoDumpDebuggerState[changeState: FALSE] THEN DumpMinState[];
IF AutoRestart[changeState: FALSE] THEN RestartDebugger[]
ELSE {
ShowDebuggerWaiting[];
alreadyReported ← FALSE;
UNTIL IsDebuggerRestarted[] DO Process.PauseMsec[watcherWait]; ENDLOOP;
LOOP;
};
};
Process.PauseMsec[watcherWait];
EXITS
scError => Process.PauseMsec[10*watcherWait];
END;
ENDLOOP;
};
debuggerIsRestarted: BOOLFALSE;
RestartDebugger: ENTRY PROC = {
ENABLE UNWIND => NULL;
SoftcardOps.WriteLong[debuggerWatchSCAddr, 0];
debuggerIsRestarted ← TRUE;
};
ShowDebuggerWaiting: ENTRY PROC =
{ debuggerIsRestarted ← FALSE };
IsDebuggerRestarted: ENTRY PROC RETURNS[BOOL] =
{ RETURN[debuggerIsRestarted] };
DumpAllDebuggerStateProc: ClickProc = { DumpAllDebuggerState[] };
RestartDebuggerProc: ClickProc = {
RestartDebugger[];
TSOutPutRope["\tRestarted the debugger\n"];
};
DumpAllDebuggerState: PROC = {
IF debuggerState = NIL THEN { TSOutPutRope[noState]; RETURN };
TSOutPutRope["Dumping the entire debugger state\n"];
ShowEUState[];
DumpIFUStack[];
DumpWords["EUStack:", DD.euRegBase, 126];
DumpWords["EUConstRegs:", DD.euRegBase+euConst, DD.EUConstants];
DumpWords["EUAuxRegs:", DD.euRegBase+euAux, DD.EUAuxRegs];
};
noState: ROPE = "\n**** No debugger state to dump\n";
euMar: CARD16 = 130;
euField: CARD16 = 131;
euConst: CARD16 = 132;
euAux: CARD16 = 144;
MinStateProc: ClickProc = { DumpMinState[] };
DumpMinState: PROC = {
youngest: CARD16 ← debuggerState[DD.debuggerFrame]; -- youngest is debugger call
IF debuggerState = NIL THEN { TSOutPutRope[noState]; RETURN };
ShowEUState[];
TSOutPutRope["\nThe top few stack entries:\n"];
TSOutPutF["\t[s]: %xH, [s-1]: %xH, [s-2]: %xH, [s-3]: %xH, [s-4]: %xH\n",
[cardinal[debuggerState[DD.euRegBase+126]]],
[cardinal[debuggerState[DD.euRegBase+125]]],
[cardinal[debuggerState[DD.euRegBase+124]]],
[cardinal[debuggerState[DD.euRegBase+123]]],
[cardinal[debuggerState[DD.euRegBase+122]]]
];
OneIFUStackEntry["\nYoungestIFU:", IF youngest = 0 THEN youngest ELSE youngest-1];
};
ShowEUState: PROC = {
field: SoftcardOps.FieldDesc = LOOPHOLE[debuggerState[DD.euRegBase+euField]];
TSOutPutRope["\nDumping minimum EU state\n"];
TSOutPutF["\topCode: %xH, alphaBeta: %xH, s: %xH, carry: %xH\n",
[cardinal[debuggerState[DD.debuggerOpcode]]],
[cardinal[debuggerState[DD.debuggerAlphaBeta]]],
[cardinal[debuggerState[DD.debuggerS]]],
[cardinal[debuggerState[DD.debuggerCarry]]]
];
TSOutPutF["\teuMAR: %xH, euField: [insert: %g, mask: %g, shift: %g]\n",
[cardinal[debuggerState[DD.euRegBase+euMar]]],
[cardinal[field.insert]],
[cardinal[field.mask]],
[cardinal[field.shift]]
];
};
IFUStackProc: ClickProc = { DumpIFUStack[] };
DumpIFUStack: PROC = {
nFrames: CARD32 = debuggerState[DD.debuggerFrame];
IF debuggerState = NIL THEN { TSOutPutRope[noState]; RETURN };
TSOutPutF["\nDumping %g frames in the IFU stack\n", [cardinal[nFrames]] ];
FOR i: CARD32 IN [0..nFrames) DO
OneIFUStackEntry[IO.PutFR[" [%g]:", [cardinal[i+1]] ], i];
ENDLOOP;
};
OneIFUStackEntry: PROC[rp: ROPE, i: CARD32] = {
statusWord: DragOpsCross.StackedStatusWord =
LOOPHOLE[DragOpsCrossUtils.CardToWord[debuggerState[DD.ifuRegBase+2*i]] ];
pc: CARD32 = debuggerState[DD.ifuRegBase+2*i+1];
sym: ROPE;
ok: BOOL;
[ok, sym] ← InterpretAddrAsSym[pc, quadMemory, FALSE];
TSOutPutF["%g status[userMode: %g, trapsEnabled: %g, lBase: %xH]\n",
[rope[rp]], [boolean[statusWord.userMode]], [boolean[statusWord.trapsEnabled]],
[cardinal[statusWord.lBase]] ];
TSOutPutF["\t\tpc: %xH", [cardinal[pc]] ];
IF ok THEN TSOutPutF[" (%g)", [rope[sym]] ];
TSOutPutChar['\n];
};
EUStackProc: ClickProc = { DumpWords["EUStack:", DD.euRegBase, 126] };
DumpWords: PROC[rp: ROPE, first: CARD32, num: CARD16] = {
seq: SoftcardOps.SeqLong = debuggerState;
addr: CARD32 ← 0;
count: CARD16 ← num;
index: CARD16 ← first;
format: ROPE = " %04x";
TSOutPutF["\nDumping %g words of %g\n", [cardinal[num]], [rope[rp]] ];
WHILE count >= 8 DO
TSOutPutF["%xH:", [cardinal[addr+index-first]] ];
FOR i: CARD16 IN [0..8) DO
TSOutPutF[format, [cardinal[seq[index+i]]] ];
ENDLOOP;
TSOutPutChar['\n];
index ← index + 8;
count ← count - 8;
ENDLOOP;
IF count # 0 THEN {
TSOutPutF["%xH:", [cardinal[addr+index-first]] ];
FOR i: CARD16 IN [0..count) DO
TSOutPutF[format, [cardinal[seq[index+i]]] ];
ENDLOOP;
TSOutPutChar['\n];
};
};
EUAuxRegsProc: ClickProc =
{ DumpWords["EUAuxRegs:", DD.euRegBase+euAux, DD.EUAuxRegs] };
EUConstRegsProc: ClickProc =
{ DumpWords["EUConstRegs:", DD.euRegBase+euConst, DD.EUConstants] };
InterpSymbolProc: ClickProc = {
what: ROPE = ViewerTools.GetContents[interpretWhatText];
rp: ROPE;
addr: CARD32;
ok: BOOL;
IF what.Length[] = 0 THEN {
TSOutPutRope["\n Please fill in the Interpret \"what\" field\n"];
RETURN
};
[ok, addr] ← InterpretSymAsAddr[what, quadMemory];
IF ok = FALSE THEN {
Labels.Set[showInterpretResult, " ??? "];
RETURN;
};
Labels.Set[showInterpretResult, rp ← IO.PutFR["0%xH", [cardinal[addr]]] ];
TSOutPutF["Expression \"%g\" has dragon byte address %g\n",
[rope[what]], [rope[rp]] ];
};
InterpAddrProc: ClickProc = {
what: ROPE = ViewerTools.GetContents[interpretWhatText];
ok: BOOL;
rp: ROPE;
addr: CARD32;
[ok, addr] ← CheckedGetAsCard[interpretWhatText, "Interpret \"what\"", LAST[CARD32]];
IF ~ok THEN RETURN;
[ok, rp] ← InterpretAddrAsSym[addr, quadMemory, TRUE];
Labels.Set[showInterpretResult, rp];
IF ok THEN
TSOutPutF["The symbol for dragon byte address \"%g\" is : %g\n",
 [rope[what]], [rope[rp]] ];
};
InterpretWhatProc: ClickProc =
{ ViewerTools.SetSelection[interpretWhatText, NIL] };
ReadQuadFile: PROC[fileName: ROPE] RETURNS[mem: Memory] = {
quadFile: STREAMFS.StreamOpen[fileName];
count: INT ← 0;
list: LIST OF MemWord ← NIL;
symList: LIST OF SymbolAddr ← NIL;
numSyms: CARD16 ← 0;
mem ← NEW[MemoryRec ← [sym: SymTab.Create[]]];
DO
Skip: PROC [source: STREAM, c: CHAR] RETURNS[BOOL] ~ {
ch: CHAR;
[] ← source.SkipWhitespace[];
IF (ch ← source.GetChar[]) # c THEN {
TSOutPutF[" Bad char %g (expected %g) at pos %g in quadFile %g - quitting\n",
[character[c]], [character[ch]], [integer[source.GetIndex[]]], [rope[fileName]] ];
RETURN[FALSE];
};
RETURN[TRUE];
};
tokenKind: IO.TokenKind;
token: ROPE;
addr, value: Word;
[tokenKind, token] ← quadFile.GetCedarTokenRope[! IO.EndOfStream => EXIT];
SELECT tokenKind FROM
tokenDECIMAL,
tokenOCTAL,
tokenHEX => {
addr ← Convert.CardFromRope[token];
value ← 0;
IF ~Skip[quadFile, '/] THEN {
quadFile.Close[];
RETURN[NIL];
};
THROUGH [0..4) DO value ← value*100H + quadFile.GetCard[] ENDLOOP;
list ← CONS[[addr, value], list];
count ← count+1
};
tokenID => {
IF ~Skip[quadFile, '=] THEN {
quadFile.Close[];
RETURN[NIL];
};
addr ← quadFile.GetCard[];
symList ← CONS[NEW[SymbolAddrRec ← [token, addr]], symList];
numSyms ← numSyms + 1;
[] ← SymTab.Store[mem.sym, token, TVFromRef[NEW[Word ← addr]]]
};
tokenEOF => EXIT;
ENDCASE => {
TSOutPutF["\n****Unknown tokenKind in quadFile %g at pos %g - quitting\n",
[rope[fileName]], [integer[quadFile.GetIndex[]]] ];
quadFile.Close[];
RETURN[NIL];
};
ENDLOOP;
quadFile.Close[];
mem.wds ← NEW[MemWords[count]];
FOR i: INT DECREASING IN [0..count) DO
mem.wds[i] ← list.first;
list ← list.rest
ENDLOOP;
mem.lowestAddr ← mem.wds[0].addr;
mem.highestAddr ← mem.wds[count-1].addr;
IF numSyms # 0 THEN {
MySort: List.CompareProc = {
sa1: SymbolAddr = NARROW[ref1];
sa2: SymbolAddr = NARROW[ref2];
IF sa1.addr < sa2.addr THEN RETURN[less];
IF sa1.addr = sa2.addr THEN RETURN[equal];
RETURN[greater];
};
TRUSTED { symList ← LOOPHOLE[List.Sort[LOOPHOLE[symList], MySort] ] };
mem.sortedSyms ← NEW[SortedSyms[numSyms]];
FOR i: CARD16 IN [0..numSyms) DO
mem.sortedSyms[i] ← symList.first;
symList ← symList.rest;
ENDLOOP;
};
};
InterpretSymAsAddr: PROC[rp: ROPE, mem: Memory] RETURNS[ok: BOOL, addr: Word] = {
result: AMTypes.TV;
errorRope: ROPE;
noResult: BOOL;
refCard: REF;
[result, errorRope, noResult] ← Interpreter.Evaluate[rp, NIL, LIST[mem.sym]];
IF noResult THEN {
addr ← 0;
TSOutPutF["\n*****Could not interpret \"%g\" - quitting\n", [rope[rp]] ];
RETURN[FALSE, addr]};
refCard ← RefFromTV[result];
WITH refCard SELECT FROM
word: REF Word => {RETURN[TRUE, word^]};
card: REF LONG CARDINAL => {RETURN[TRUE, card^]};
int: REF INT => {
IF int^ < 0 THEN RETURN[FALSE, 0];
RETURN[TRUE, int^]
};
ENDCASE => {
TSOutPutF["\n*****Unknown variant for \"%g\" - quitting\n", [rope[rp]] ];
RETURN[FALSE, 0];
};
};
InterpretAddrAsSym: PROC[addr: CARD32, mem: Memory, verbose: BOOL]
RETURNS[ok: BOOL, rp: ROPE] = {
sortedSyms: REF SortedSyms;
num: CARD16;
ok ← FALSE;
rp ← " ??? ";
IF mem = NIL THEN RETURN;
sortedSyms ← mem.sortedSyms;
num ← IF sortedSyms = NIL THEN 0 ELSE sortedSyms.size;
IF addr < mem.lowestAddr THEN {
IF verbose THEN TSOutPutF["***%xH is smaller than any address (%xH)\n",
[cardinal[addr]], [cardinal[mem.lowestAddr]] ];
RETURN
};
IF addr > mem.highestAddr THEN {
IF verbose THEN TSOutPutF["***%xH is larger than any address (%xH)\n",
[cardinal[addr]], [cardinal[mem.highestAddr]] ];
RETURN
};
IF sortedSyms = NIL THEN {
IF verbose THEN TSOutPutRope["\t*****Loaded file had no symbols\n"];
RETURN;
};
IF addr < sortedSyms[0].addr THEN {
diff: CARD32 = sortedSyms[0].addr - addr;
RETURN[TRUE, IO.PutFR["%g-%xH", [rope[sortedSyms[0].sym]], [cardinal[diff]]] ];
};
IF addr > sortedSyms[num-1].addr THEN {
diff: CARD32 = addr - sortedSyms[num-1].addr;
RETURN[TRUE, IO.PutFR["%g+%xH", [rope[sortedSyms[num-1].sym]], [cardinal[diff]]] ];
};
FOR i: CARD16 IN [0..num) DO
diff: CARD32;
IF addr > sortedSyms[i].addr THEN LOOP;
IF addr = sortedSyms[i].addr THEN RETURN[TRUE, sortedSyms[i].sym];
diff ← addr - sortedSyms[i-1].addr;
RETURN[TRUE, IO.PutFR["%g+%xH", [rope[sortedSyms[i-1].sym]], [cardinal[diff]]] ];
ENDLOOP;
};
TVFromRef: PROC [ref: REF] RETURNS [AMTypes.TV] = TRUSTED
{ RETURN [AMBridge.TVForReferent[ref]] };
RefFromTV: PROC [tv: REF] RETURNS [REF] = {
IF tv = NIL THEN RETURN [NIL];
IF ~ISTYPE [tv, AMTypes.TV] THEN ERROR;
TRUSTED {RETURN [AMBridge.SomeRefFromTV[tv]]}
};
ByteAddrToSoftcardAddr: PUBLIC PROC[addr: CARD32] RETURNS[softAddr: CARD32] = {
softAddr ← 100000H+(addr MOD 100000H)/2;
};
start code
TRUSTED { Process.Detach[FORK TheWatcherProc] };
END.