<> <> <> <> DIRECTORY AMBridge USING [SomeRefFromTV, TVForReferent], AMTypes USING [TV], Buttons USING [Create], Convert USING [CardFromRope], FS USING [Error, FileInfo, StreamOpen], Interpreter USING [Evaluate], IO, Labels USING [Create, Set], Rope, SoftcardOps, SoftcardToolPrivate, SymTab USING [Create, Ref, Store], ViewerTools USING [GetContents, MakeNewTextViewer, SetSelection]; SoftcardToolQuadIOImpl: CEDAR PROGRAM IMPORTS AMBridge, Interpreter, Buttons, Convert, FS, IO, Labels, Rope, SymTab, ViewerTools, SoftcardOps, SoftcardToolPrivate 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]; MemWords: TYPE = RECORD [SEQUENCE size: CARDINAL OF MemWord]; MemWord: TYPE = RECORD [addr, value: Word]; quadMemory: Memory; quadFileNameText: Viewer; interpAddrWhatText, showInterpAddr: Viewer; BuildQuadIOButtons: PUBLIC PROC[topViewer, sibx: Viewer] RETURNS[sib: Viewer] = { sib _ sibx; <> 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]]; <> sib _ Buttons.Create[ info: [ name: " Interpret ", parent: topViewer, wx: leftEdge, wy: sib.wy+sib.wh+betweenHeight, 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: InterpAddrWhatProc ]; <<>> sib _ interpAddrWhatText _ ViewerTools.MakeNewTextViewer[ info: [parent: topViewer, wx: sib.wx+sib.ww+xFudge+6, wy: sib.wy, ww: 200, wh: entryHeight, border: FALSE, scrollable: FALSE]]; sib _ Labels.Create[ info: [ name: " address: ", parent: topViewer, wx: sib.wx+sib.ww+xFudge, wy: sib.wy, wh: entryHeight, border: FALSE, scrollable: FALSE], font: labelFont ]; sib _ showInterpAddr _ Labels.Create[ info: [ name: " ", parent: topViewer, wx: sib.wx+sib.ww+xFudge, wy: sib.wy, wh: entryHeight, border: FALSE, scrollable: FALSE] ]; RETURN[sib]; }; 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 _ DragonToSoftcardAddr[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 }; 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 > 256 DO SoftcardOps.WriteMultipleLong[256, PushAddrVal]; numLeft _ numLeft - 256; 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] }; InterpAddrProc: ClickProc = { what: ROPE = ViewerTools.GetContents[interpAddrWhatText]; rp: ROPE; addr: CARD32; ok: BOOL; IF what.Length[] = 0 THEN { TSOutPutRope["\n Please fill in the Interpret waht field\n"]; RETURN }; [ok, addr] _ InterpAddr[what, quadMemory]; IF ok = FALSE THEN { Labels.Set[showInterpAddr, " ??? "]; RETURN; }; Labels.Set[showInterpAddr, rp _ IO.PutFR["0%xH", [cardinal[addr]]] ]; TSOutPutF["Expression \"%g\" has dragon address %g\n", [rope[what]], [rope[rp]] ]; }; InterpAddrWhatProc: ClickProc = { ViewerTools.SetSelection[interpAddrWhatText, NIL] }; ReadQuadFile: PROC[fileName: ROPE] RETURNS[mem: Memory] = { quadFile: STREAM _ FS.StreamOpen[fileName]; count: INT _ 0; list: LIST OF MemWord _ NIL; 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[]; [] _ 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; }; InterpAddr: PUBLIC PROC[addRope: ROPE, mem: Memory] RETURNS[ok: BOOL, addr: Word] = { result: AMTypes.TV; errorRope: ROPE; noResult: BOOL; refCard: REF; [result, errorRope, noResult] _ Interpreter.Evaluate[addRope, NIL, LIST[mem.sym]]; IF noResult THEN { addr _ 0; TSOutPutF["\n*****Could not interpret \"%g\" - quitting\n", [rope[addRope]] ]; 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[addRope]] ]; RETURN[FALSE, 0]; }; }; 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]]} }; END.