DIRECTORY AmpersandContext USING[CreateAnAmpersandContext, MakeNodeFromNode, StripAMNode], Atom USING [GetPName], BasicTime USING[Now], CCTypes USING[CCError, CCErrorCase, CreateCedarCompilerContext, CreateNodeFromRefAny], CedarCode USING[GetNodeRepresentation, GetTypeOfNode, LoadThroughIndirectNode, SelectFieldFromNode, StoreThroughIndirectNode], CirioBackstop USING[Protect], CirioBreakAccess USING[CirioBreakSet, CreateCirioBreakSet, ClearAllBreaks, ClearBreakAtAbsAddr, ClearBreakAtIndex, ListBreaks, SetBreakAtAbsAddr, BreakSetBroken], CirioDeltaFace USING[IsDMachine], CirioNub USING [Error], CirioNubAccess USING[CreateRemoteNub, DbgMsgNone, DbgMsgNoHandlerRequest, DbgMsgHandlerRequest, DbgMsgAbort, DbgMsgBadProceedRequest, DbgMsgBreakRequest, DbgMsgClientRequest, DbgMsgExit, DbgMsgProceed, DestroyNub, Error, FileEntry, GetFileEntry, GetThreads, Handle, IssueThreadCommand, KillWorld, LookupSymEntryByName, LookupSymEntryByValue, LookupSymEntryByID, Null, PCInfo, PCtoInfo, Read32BitsAsCard, SchedStateFree, SchedStateReady, SchedStateRun, SchedStateWaitML, SchedStateWaitCV, SchedStateHandlee, SetDBStat, SymEntry, ThreadInfo, WaitSig], CirioTargets USING[Target], CirioTypes USING[CirioAddress, CirioAddressBody, CompilerContext, Node, Type], Commander USING[CommandProc, Register], CommandTool USING[ArgumentVector, Parse], Convert USING[CardFromRope, RopeFromCard], FileNames USING[CurrentWorkingDirectory], IO USING[card, char, Close, Error, PutF, PutFR, PutRope, RopeFromROS, ROS, rope, STREAM], LoadStateAccess USING[CreateLoadStateHandle, LoadStateHandle], LocalCirio USING[Connection, ExtractCcFromConnection, GetConnection, nilBreakDest], NewAmpersandProcs USING[Handle, HandleBody, InstallItems], NewRMTW USING[CedarModuleSet, CreateCedarModuleSet, CreateRemoteMimosaTargetWorld, FlushUnknownFileCache, FlushUnknownSymbolCache, FlushUnknownTypeCodes, RemoteMimosaTargetWorld, ResetSearchPaths], ObjectFiles USING[CreateParsed, GetLineNumForPC, GetPCForLineNum, Module, ModuleFromParsedAndPC, Parsed], OneCasabaParser USING[ParserTable], PBasics USING[BITLSHIFT, BITOR, BITRSHIFT], PFS USING [AbsoluteName, RopeFromPath, PathFromRope], PFSNames USING [PATH, Equal], Process USING [Detach, PauseMsec, priorityBackground, SetPriority], RemoteCirio USING[ThreadProperty], Rope USING[Cat, Concat, Equal, FromChar, Length, Map, Substr, ROPE], SourceFileOpsExtras USING [FullOpenSource, Position], StackCirio USING[FrameDiagnosticInfo, InterpretTextLine, NoteFileCacheFlush, OpenDummyStack, OpenStack, QuickGenPossibleModuleNames, ResetStack, ShowCurrentFrame, ShowQuickSummary, Stack, WalkStack, WalkStackToCProcedure], SystemInterface USING [ShowReport, CloseFileSet, CirioFile, CreateFileSet, FileSet, GetCirioFileFromDebuggee]; RemoteCirioImpl: CEDAR MONITOR LOCKS connection USING connection: Connection IMPORTS AmpersandContext, Atom, BasicTime, CCTypes, CedarCode, CirioBackstop, CirioBreakAccess, CirioDeltaFace, CirioNub, CirioNubAccess, Commander, CommandTool, Convert, FileNames, IO, LoadStateAccess, LocalCirio, NewAmpersandProcs, NewRMTW, ObjectFiles, PBasics, PFS, PFSNames, Process, Rope, SourceFileOpsExtras, StackCirio, SystemInterface EXPORTS RemoteCirio = BEGIN OPEN ObjF: ObjectFiles, LSA: LoadStateAccess; DebugFlag: BOOLEAN _ FALSE; CC: TYPE = CirioTypes.CompilerContext; CCE: ERROR[case: CCTypes.CCErrorCase, msg: Rope.ROPE _ NIL] _ CCTypes.CCError; Connection: TYPE = REF ConnectionBody; ConnectionBody: PUBLIC TYPE = MONITORED RECORD[ open: BOOLEAN, doradoWorkingDirectory: Rope.ROPE, serverName: Rope.ROPE, searchDirectories: LIST OF PFSNames.PATH, tsOut: IO.STREAM, -- WARNING: this field is very transient. It is only valid during an interpretation of an expression, and was placed here for the convenience of ampersand routines and (local target wrld) user routines called through the interpreter. ampersandContext1: CirioTypes.Node, ampersandContext2: CirioTypes.Node, cc, localCc: CC, localConnection: LocalCirio.Connection, rmtw: NewRMTW.RemoteMimosaTargetWorld, cedarModules: NewRMTW.CedarModuleSet, nub: CirioNubAccess.Handle, target: CirioTargets.Target, daemon: PROCESS, daemonKillFlag: BOOLEAN, breaks: CirioBreakAccess.CirioBreakSet, fileSet: SystemInterface.FileSet, lsh: LoadStateAccess.LoadStateHandle, aph: NewAmpersandProcs.Handle, cParserTable: OneCasabaParser.ParserTable, remoteWorldRunning: BOOLEAN _ TRUE, dbxActive: BOOLEAN _ FALSE, currentThread: CARD _ 0, threads: REF ThreadSet]; ThreadSet: TYPE = RECORD[SEQUENCE nThreads: CARDINAL OF REF ThreadData]; ThreadData: TYPE = RECORD[ thread: REF CirioNubAccess.ThreadInfo, stack: StackCirio.Stack ]; OpenConnection: PUBLIC PROC[remoteName: Rope.ROPE, portNum: CARD, workingDirectories: LIST OF Rope.ROPE, reports: IO.STREAM] RETURNS[connection: Connection] = { outerMsg: Rope.ROPE _ CirioBackstop.Protect[Openit, reports]; Openit: PROC RETURNS[Rope.ROPE] ~ { connection _ FunctionalOpen[]; RETURN[NIL]}; FunctionalOpen: PROC RETURNS[Connection] ~ { nub: CirioNubAccess.Handle _ NIL; target: CirioTargets.Target _ NIL; fileSet: SystemInterface.FileSet; breaks: CirioBreakAccess.CirioBreakSet; searchDirs: LIST OF PFSNames.PATH _ NIL; lastSearchDir: LIST OF PFSNames.PATH _ NIL; defaultSearchDirs: LIST OF PFSNames.PATH _ LIST[ PFS.PathFromRope["/PCedar/Cirio/"], PFS.PathFromRope["/PCedar/CirioThings/"], PFS.PathFromRope["/PCedar/Atom/"], PFS.PathFromRope["/PCedar/Rope/"] ]; ClearBreaksForOpen: PROC RETURNS[Rope.ROPE] = { CirioBreakAccess.ClearAllBreaks[breaks]; RETURN[NIL]}; searchDirs _ LIST [PFS.PathFromRope["-compiled:/CirioCompiledData/"]]; lastSearchDir _ searchDirs; FOR thisDir: LIST OF Rope.ROPE _ workingDirectories, thisDir.rest WHILE thisDir # NIL DO lastSearchDir.rest _ LIST [PFS.AbsoluteName[PFS.PathFromRope[thisDir.first]]]; lastSearchDir _ lastSearchDir.rest; ENDLOOP; lastSearchDir.rest _ defaultSearchDirs; nub _ CirioNubAccess.CreateRemoteNub[debuggee: remoteName, port: portNum, timeoutMsec: 10000 !CirioNub.Error => { reports.PutF["Failed to open DebugNub connection to port %g on %g.\n", [cardinal[portNum]], [rope[remoteName]] ]; CONTINUE}]; IF nub=NIL THEN RETURN [NIL]; target _ NARROW[nub.target]; fileSet _ SystemInterface.CreateFileSet[]; breaks _ CirioBreakAccess.CreateCirioBreakSet[nub, "CirioThingsImpl", "CallDebugger"]; IF breaks.BreakSetBroken[] THEN reports.PutRope["You won't be able to set breakpoints in the debuggee, because I was unable to find CirioThingsImpl.CallDebugger in the debuggee. Are you sure you loaded an unoptimized version of CirioThingsImpl into the debuggee somewhere along the line?\n"]; { ENABLE UNWIND => { -- all attempts to give a report will be ignored finalMsg: Rope.ROPE _ CirioBackstop.Protect[ClearBreaksForOpen, reports]; CirioNubAccess.DestroyNub[nub]; SystemInterface.CloseFileSet[fileSet]; IF Rope.Length[finalMsg] # 0 THEN IO.PutF[reports, "%g\N", IO.rope[finalMsg]]; }; cc, lcc: CC; cedarModules: NewRMTW.CedarModuleSet; lsh: LoadStateAccess.LoadStateHandle; rmtw: NewRMTW.RemoteMimosaTargetWorld; ampersandContext1, ampersandContext2: CirioTypes.Node; aph: NewAmpersandProcs.Handle; connection: Connection; IF NOT CirioNubAccess.Null[nub, 7] THEN CCE[cirioError, "debuggee doesn't implement debug nub protocol version 7"]; cc _ CCTypes.CreateCedarCompilerContext[]; cedarModules _ NewRMTW.CreateCedarModuleSet[fileSet, remoteName]; NewRMTW.ResetSearchPaths[cedarModules, searchDirs, BasicTime.Now[]]; lsh _ LoadStateAccess.CreateLoadStateHandle[remoteName, nub, fileSet]; rmtw _ NewRMTW.CreateRemoteMimosaTargetWorld[remoteName, nub, cc, cedarModules, lsh, reports, TRUE]; aph _ NEW[NewAmpersandProcs.HandleBody_[ out: NIL, -- filled in during a line interpretation in StackCirioImpl rmtw: rmtw, cedarModules: cedarModules, nub: nub, fileSet: fileSet, lsh: lsh]]; connection_ NEW[ConnectionBody_[ open: TRUE, doradoWorkingDirectory: workingDirectories.first, serverName: remoteName, searchDirectories: searchDirs, cc: cc, localCc: lcc, localConnection: LocalCirio.GetConnection[LocalCirio.nilBreakDest, reports], rmtw: rmtw, cedarModules: cedarModules, nub: nub, target: target, daemon: NIL, daemonKillFlag: FALSE, breaks: breaks, fileSet: fileSet, lsh: lsh, aph: aph, cParserTable: NIL]]; connection.localCc _ LocalCirio.ExtractCcFromConnection[connection.localConnection]; connection.ampersandContext1 _ AmpersandContext.CreateAnAmpersandContext[connection.localCc]; connection.ampersandContext2 _ AmpersandContext.CreateAnAmpersandContext[connection.localCc]; ampersandContext1 _ connection.ampersandContext1; ampersandContext2 _ connection.ampersandContext2; NewAmpersandProcs.InstallItems[connection.ampersandContext2, aph, connection.localCc]; IF CirioDeltaFace.IsDMachine[] = FALSE THEN RETURN[connection]; IF TRUE THEN RETURN[connection]; InstallOneAmpersandItem[ampersandContext2, "&&H", CCTypes.CreateNodeFromRefAny[NEW[Connection _ connection], cc], cc]; InstallOneAmpersandItem[ampersandContext2, "&&RdCards", CCTypes.CreateNodeFromRefAny[NEW[PROC[a: CirioTypes.CirioAddress, nCards: CARD] _ RdCards], cc], cc]; InstallOneAmpersandItem[ampersandContext2, "&&RdHexCards", CCTypes.CreateNodeFromRefAny[NEW[PROC[a: CirioTypes.CirioAddress, nCards: CARD] _ RdHexCards], cc], cc]; InstallOneAmpersandItem[ampersandContext2, "&&RdBytes", CCTypes.CreateNodeFromRefAny[NEW[PROC[a: CirioTypes.CirioAddress, nBytes: CARD] _ RdBytes], cc], cc]; InstallOneAmpersandItem[ampersandContext2, "&&RdChars", CCTypes.CreateNodeFromRefAny[NEW[PROC[a: CirioTypes.CirioAddress, nChars: CARD] _ RdChars], cc], cc]; InstallOneAmpersandItem[ampersandContext2, "&&RdRope", CCTypes.CreateNodeFromRefAny[NEW[PROC[a: CirioTypes.CirioAddress, nChars: CARD _ 100] _ RdRope], cc], cc]; InstallOneAmpersandItem[ampersandContext2, "&&MkAddress", CCTypes.CreateNodeFromRefAny[NEW[PROC[byteAddress: CARD, h: Connection] RETURNS[CirioTypes.CirioAddress] _ MkAddress], cc], cc]; InstallOneAmpersandItem[ampersandContext2, "&&FrameDiagnosticInfo", CCTypes.CreateNodeFromRefAny[NEW[PROC[h: Connection] _ FrameDiagnosticInfo], cc], cc]; InstallOneAmpersandItem[ampersandContext2, "&&SetBreakAtAbsAddr", CCTypes.CreateNodeFromRefAny[NEW[PROC[h: Connection, absAddr: CARD32, mesaPos: SourceFileOpsExtras.Position, stopAll: BOOLEAN] _ SetBreakAtAbsAddr], cc], cc]; InstallOneAmpersandItem[ampersandContext2, "&&ListBreaks", CCTypes.CreateNodeFromRefAny[NEW[PROC[h: Connection] _ ListBreaks], cc], cc]; InstallOneAmpersandItem[ampersandContext2, "&&ClearBreakAtAbsAddr", CCTypes.CreateNodeFromRefAny[NEW[PROC[h: Connection, absAddr: CARD32] _ ClearBreakAtAbsAddr], cc], cc]; InstallOneAmpersandItem[ampersandContext2, "&&ClearBreakAtIndex", CCTypes.CreateNodeFromRefAny[NEW[PROC[h: Connection, index: CARD] _ ClearBreakAtIndex], cc], cc]; InstallOneAmpersandItem[ampersandContext2, "&&ClearAllBreaks", CCTypes.CreateNodeFromRefAny[NEW[PROC[h: Connection] _ ClearAllBreaks], cc], cc]; InstallOneAmpersandItem[ampersandContext2, "&&AddDir", CCTypes.CreateNodeFromRefAny[NEW[PROC[h: Connection, dirName: Rope.ROPE, reports: IO.STREAM] _ AddDir], cc], cc]; InstallOneAmpersandItem[ampersandContext2, "&&ListDir", CCTypes.CreateNodeFromRefAny[NEW[PROC[h: Connection] _ ListDir], cc], cc]; InstallOneAmpersandItem[ampersandContext2, "&&ClearDir", CCTypes.CreateNodeFromRefAny[NEW[PROC[h: Connection] _ ClearDir], cc], cc]; InstallOneAmpersandItem[ampersandContext2, "&&LookupSym", CCTypes.CreateNodeFromRefAny[NEW[PROC[h: Connection, name: Rope.ROPE, numToSkip: INT _ 0, externOnly: BOOL _ TRUE] RETURNS[CirioNubAccess.SymEntry] _ LookupSym], cc], cc]; InstallOneAmpersandItem[ampersandContext2, "&&LookupAddr", CCTypes.CreateNodeFromRefAny[NEW[PROC[h: Connection, val: CARD, numToSkip: INT _ 0] RETURNS[CirioNubAccess.SymEntry] _ LookupAddr], cc], cc]; InstallOneAmpersandItem[ampersandContext2, "&&LookupID", CCTypes.CreateNodeFromRefAny[NEW[PROC[h: Connection, symID: CARD] RETURNS[CirioNubAccess.SymEntry] _ LookupID], cc], cc]; InstallOneAmpersandItem[ampersandContext2, "&&LookupFile", CCTypes.CreateNodeFromRefAny[NEW[PROC[h: Connection, seqNum: CARD] RETURNS[entry: CirioNubAccess.FileEntry] _ LookupFile], cc], cc]; InstallOneAmpersandItem[ampersandContext2, "&&GetPCInfo", CCTypes.CreateNodeFromRefAny[NEW[PROC[h: Connection, absPC: CARD] RETURNS[CirioNubAccess.PCInfo] _ GetPCInfo], cc], cc]; InstallOneAmpersandItem[ampersandContext2, "&&GetRelPCForCLine", CCTypes.CreateNodeFromRefAny[NEW[PROC[dotOName: Rope.ROPE, cLineNum: CARD, h: Connection] RETURNS[CARD] _ GetRelPCForCLine], cc], cc]; InstallOneAmpersandItem[ampersandContext2, "&&GetCLineForRelPC", CCTypes.CreateNodeFromRefAny[NEW[PROC[dotOName: Rope.ROPE, relPC: CARD, h: Connection] RETURNS[CARD] _ GetCLineForRelPC], cc], cc]; InstallOneAmpersandItem[ampersandContext2, "&&DebugOn", CCTypes.CreateNodeFromRefAny[NEW[PROC[] _ DebugOn], cc], cc]; InstallOneAmpersandItem[ampersandContext2, "&&DebugOff", CCTypes.CreateNodeFromRefAny[NEW[PROC[] _ DebugOff], cc], cc]; RETURN[connection]}}; IF outerMsg#NIL THEN reports.PutF["debug connection not opened with %g (port %g) because of uncaught error (%g).\n", [rope[remoteName]], [cardinal[portNum]], [rope[outerMsg]] ]; RETURN}; FlushUnknownFileCache: PUBLIC ENTRY PROC[connection: Connection, reports: IO.STREAM] = BEGIN ENABLE UNWIND => NULL; IF NOT connection.open THEN RETURN; NewRMTW.FlushUnknownFileCache[connection.cedarModules, BasicTime.Now[]]; NewRMTW.FlushUnknownSymbolCache[connection.rmtw, BasicTime.Now[], reports]; NewRMTW.FlushUnknownTypeCodes[connection.rmtw]; IF connection.threads # NIL THEN FOR ti: CARDINAL IN [0..connection.threads.nThreads) DO td: REF ThreadData _ connection.threads[ti]; StackCirio.NoteFileCacheFlush[td.stack]; ENDLOOP; END; CloseConnection: PUBLIC ENTRY PROC[connection: Connection, reports: IO.STREAM] = { ENABLE UNWIND => NULL; InerCloseConnection[connection, reports]}; InerCloseConnection: INTERNAL PROC[connection: Connection, reports: IO.STREAM] = { ClearBreaksForClose: PROC RETURNS[Rope.ROPE] = {CirioBreakAccess.ClearAllBreaks[connection.breaks]; RETURN[NIL]}; finalMsg: Rope.ROPE _ NIL; IF connection = NIL OR NOT connection.open THEN RETURN; StopBreakCheckDaemon[connection, reports]; connection.open _ FALSE; finalMsg _ CirioBackstop.Protect[ClearBreaksForClose, reports]; CirioNubAccess.DestroyNub[connection.nub]; SystemInterface.CloseFileSet[connection.fileSet]; IF Rope.Length[finalMsg] # 0 THEN IO.PutF[reports, "%g\N", IO.rope[finalMsg]]; }; DestroyRemoteWorld: PUBLIC ENTRY PROC[connection: Connection] = BEGIN ENABLE UNWIND => NULL; IF NOT connection.open THEN RETURN; CirioNubAccess.KillWorld[connection.nub]; connection.open _ FALSE; CirioNubAccess.DestroyNub[connection.nub]; SystemInterface.CloseFileSet[connection.fileSet]; END; StopRemoteWorld: PUBLIC ENTRY PROC[connection: Connection, reports: IO.STREAM] RETURNS[nThreads: CARD] = BEGIN ENABLE UNWIND => NULL; IF NOT CirioNubAccess.SetDBStat[connection.nub, -2, 5000] THEN CCE[cirioError]; nThreads _ AcquireThreadInfo[connection, reports]; connection.remoteWorldRunning _ FALSE; RETURN[nThreads]; END; AcquireThreadInfo: PROC[connection: Connection, reports: IO.STREAM] RETURNS[nThreads: CARD] = BEGIN threads: LIST OF REF CirioNubAccess.ThreadInfo; threadX: CARD _ 0; threads _ CirioNubAccess.GetThreads[connection.nub, 0, 100]; nThreads _ 0; FOR ths: LIST OF REF CirioNubAccess.ThreadInfo _ threads, ths.rest WHILE ths # NIL DO nThreads _ nThreads+1 ENDLOOP; connection.threads _ NEW[ThreadSet[nThreads]]; FOR ths: LIST OF REF CirioNubAccess.ThreadInfo _ threads, ths.rest WHILE ths # NIL DO td: REF ThreadData _ connection.threads[threadX] _ NEW[ThreadData]; td.thread _ ths.first; td.stack _ StackCirio.OpenStack[ ampersandContext1: connection.ampersandContext1, ampersandContext2: connection.ampersandContext2, cc: connection.cc, rmtw: connection.rmtw, cedarModules: connection.cedarModules, nub: connection.nub, target: connection.target, fileSet: connection.fileSet, breaks: connection.breaks, lsh: connection.lsh, aph: connection.aph, cParserTable: connection.cParserTable, hotFramePC: ths.first.pc, hotFrameSP: ths.first.stackPointer, skipKFrames: 0, ShowSource: SourceFileOpsExtras.FullOpenSource, reports: reports]; threadX _ threadX + 1; ENDLOOP; RETURN[nThreads]; END; FindThreadsWithProperty: PUBLIC ENTRY PROC[connection: Connection, property: RemoteCirio.ThreadProperty, reports: IO.STREAM] RETURNS[LIST OF -- threadIndex -- CARD] = BEGIN ENABLE UNWIND => NULL; IF NOT connection.open THEN CCE[cirioError]; IF connection.remoteWorldRunning THEN CCE[cirioError]; BEGIN newThreads: LIST OF CARD _ NIL; lastNewThread: LIST OF CARD _ NIL; IO.PutF[reports, "\N\Tchecking thread with index "]; FOR x: CARD IN [0..connection.threads.nThreads) DO IF ThreadSatisfies[connection.threads[x], property, reports] THEN BEGIN cell: LIST OF CARD _ LIST[x]; IF newThreads = NIL THEN newThreads _ cell ELSE lastNewThread.rest _ cell; lastNewThread _ cell; END; ENDLOOP; IO.PutF[reports, "\N"]; RETURN[newThreads]; END; END; ThreadSatisfies: PROC[thread: REF ThreadData, property: RemoteCirio.ThreadProperty, reports: IO.STREAM] RETURNS[BOOLEAN] = BEGIN WITH property SELECT FROM tp: any RemoteCirio.ThreadProperty => RETURN[TRUE]; tp: callingDebugger RemoteCirio.ThreadProperty => RETURN[thread.thread.dbgMsg # 0]; tp: ready RemoteCirio.ThreadProperty => RETURN[thread.thread.schedState = CirioNubAccess.SchedStateReady OR thread.thread.schedState = CirioNubAccess.SchedStateRun]; tp: context RemoteCirio.ThreadProperty => BEGIN found: BOOLEAN _ FALSE; -- tentative CheckName: PROC[name: PFSNames.PATH] RETURNS[--stop-- BOOLEAN] = BEGIN found _ Rope.Equal[PFS.RopeFromPath[name], tp.name, FALSE]; RETURN[found]; END; IO.PutF[reports, "%g ", IO.card[thread.thread.index]]; StackCirio.QuickGenPossibleModuleNames[thread.stack, CheckName, reports]; IF found THEN IO.PutF[reports, "(bingo )"]; RETURN[found]; END; ENDCASE => CCE[cirioError]; END; GetThreadTitleText: PUBLIC ENTRY PROC[connection: Connection, threadIndex: CARD] RETURNS[Rope.ROPE] = BEGIN ENABLE UNWIND => NULL; RETURN[ConstructThreadTitleText[connection, threadIndex]]; END; ConstructThreadTitleText: PROC[connection: Connection, threadIndex: CARD] RETURNS[Rope.ROPE] = BEGIN threadData: REF ThreadData _ connection.threads[threadIndex]; remoteIndex: CARD _ threadData.thread.index; schedStateText: Rope.ROPE _ RopeForSchedState[threadData.thread.schedState]; dbgMsgText: Rope.ROPE _ RopeForDbgMsg[threadData.thread.dbgMsg]; freezeText: Rope.ROPE _ IF threadData.thread.frozen THEN " (frozen)" ELSE NIL; RETURN[IO.PutFR["%g: (%g) (%g)%g (%g)", IO.card[remoteIndex], IO.card[threadData.thread.priority], IO.rope[schedStateText], IO.rope[freezeText], IO.rope[dbgMsgText]]]; END; ThreadIndexFromID: PUBLIC PROC[ID: CARD, connection: Connection] RETURNS [index: CARD _ LAST[CARD]] ~ { FOR i: CARDINAL IN [0..connection.threads.nThreads) DO IF connection.threads[i].thread.index = ID THEN RETURN[i]; ENDLOOP; }; ThreadIDFromIndex: PUBLIC PROC[index: CARD, connection: Connection] RETURNS [ID: CARD _ LAST[CARD]] ~ { IF index < connection.threads.nThreads THEN RETURN[connection.threads[index].thread.index]; }; ShowQuickSummary: PUBLIC ENTRY PROC[connection: Connection, threadIndex: CARD, stopFlag: REF BOOLEAN, on: IO.STREAM, long: BOOL] = BEGIN ENABLE UNWIND => NULL; threadData: REF ThreadData _ connection.threads[threadIndex]; IO.PutF[on, "quick summary for thread with index %g\N", IO.card[connection.threads[threadIndex].thread.index]]; IO.PutF[on, "\Tdebug message = %g\N", IO.rope[RopeForDbgMsg[threadData.thread.dbgMsg]]]; StackCirio.ShowQuickSummary[threadData.stack, stopFlag, on, long]; END; GetThreadDebuggingBanner: PUBLIC ENTRY PROC[connection: Connection, threadIndex: CARD, reports: IO.STREAM] RETURNS[Rope.ROPE] = BEGIN ENABLE UNWIND => NULL; inner: PROC RETURNS[Rope.ROPE] = BEGIN RETURN[IO.PutFR["debugging thread with index %g", IO.card[connection.threads[threadIndex].thread.index]]]; END; RETURN[CirioBackstop.Protect[inner, reports]]; END; AbortThread: PUBLIC ENTRY PROC[connection: Connection, threadIndex: CARD, reports: IO.STREAM] RETURNS[newThreadTitleText: Rope.ROPE] = BEGIN ENABLE UNWIND => NULL; inner: PROC RETURNS[Rope.ROPE] = BEGIN RETURN[IssueFullThreadCommand[connection, threadIndex, TRUE, FALSE, TRUE, -3]]; END; RETURN[CirioBackstop.Protect[inner, reports]]; END; KillThread: PUBLIC ENTRY PROC[connection: Connection, threadIndex: CARD, reports: IO.STREAM] RETURNS[newThreadTitleText: Rope.ROPE] = BEGIN ENABLE UNWIND => NULL; inner: PROC RETURNS[Rope.ROPE] = BEGIN RETURN[IssueFullThreadCommand[connection, threadIndex, TRUE, FALSE, TRUE, -2]]; END; RETURN[CirioBackstop.Protect[inner, reports]]; END; FreezeThread: PUBLIC ENTRY PROC[connection: Connection, threadIndex: CARD, reports: IO.STREAM] RETURNS[newThreadTitleText: Rope.ROPE] = BEGIN ENABLE UNWIND => NULL; inner: PROC RETURNS[Rope.ROPE] = BEGIN RETURN[IssueFullThreadCommand[connection, threadIndex, TRUE, TRUE, FALSE, connection.threads[threadIndex].thread.dbgMsg]]; END; RETURN[CirioBackstop.Protect[inner, reports]]; END; ProceedThread: PUBLIC ENTRY PROC[connection: Connection, threadIndex: CARD, reports: IO.STREAM] RETURNS[newThreadTitleText: Rope.ROPE] = BEGIN ENABLE UNWIND => NULL; inner: PROC RETURNS[Rope.ROPE] = BEGIN RETURN[IssueFullThreadCommand[connection, threadIndex, TRUE, FALSE, TRUE, -1]]; END; RETURN[CirioBackstop.Protect[inner, reports]]; END; IssueFullThreadCommand: PROC[connection: Connection, threadIndex: CARD, setFreeze: BOOL, freeze: BOOLEAN, setMsg: BOOLEAN, msg: INT] RETURNS[--new title text-- Rope.ROPE] = BEGIN remoteIndex: CARD _ connection.threads[threadIndex].thread.index; IF NOT CirioNubAccess.IssueThreadCommand[connection.nub, remoteIndex, setFreeze, freeze, setMsg, msg] THEN CCE[cirioError]; BEGIN threads: LIST OF REF CirioNubAccess.ThreadInfo _ CirioNubAccess.GetThreads[connection.nub, 0, 100]; FOR ths: LIST OF REF CirioNubAccess.ThreadInfo _ threads, ths.rest WHILE ths # NIL DO IF ths.first.index = remoteIndex THEN -- here we are BEGIN connection.threads[threadIndex].thread _ ths.first; EXIT; END; ENDLOOP; RETURN[ConstructThreadTitleText[connection, threadIndex]]; END; END; DbxExamineThread: PUBLIC ENTRY PROC[connection: Connection, threadIndex: CARD, reports: IO.STREAM] RETURNS[nThreads: CARD] = BEGIN ENABLE UNWIND => NULL; IF NOT connection.remoteWorldRunning THEN BEGIN remoteIndex: CARD _ connection.threads[threadIndex].thread.index; connection.remoteWorldRunning _ TRUE; connection.dbxActive _ TRUE; connection.threads _ NIL; IF NOT CirioNubAccess.SetDBStat[connection.nub, remoteIndex, 5000] THEN CCE[cirioError]; WHILE NOT CirioNubAccess.SetDBStat[connection.nub, -2, 5000] DO ENDLOOP; nThreads _ AcquireThreadInfo[connection, reports]; connection.dbxActive _ FALSE; connection.remoteWorldRunning _ FALSE; RETURN[nThreads]; END ELSE CCE[cirioError]; END; ResumeRemoteWorldWithOnlyVP0: PUBLIC ENTRY PROC[connection: Connection] = BEGIN ENABLE UNWIND => NULL; IF NOT connection.remoteWorldRunning THEN BEGIN IF NOT CirioNubAccess.SetDBStat[connection.nub, -1, 5000] THEN CCE[cirioError]; connection.threads _ NIL; connection.remoteWorldRunning _ TRUE; END; END; ResumeRemoteWorld: PUBLIC ENTRY PROC[connection: Connection] = BEGIN ENABLE UNWIND => NULL; IF NOT connection.remoteWorldRunning THEN BEGIN IF NOT CirioNubAccess.SetDBStat[connection.nub, 0, 5000] THEN CCE[cirioError]; connection.threads _ NIL; connection.remoteWorldRunning _ TRUE; END; END; GetDummyStack: PUBLIC ENTRY PROC[connection: Connection, reports: IO.STREAM]RETURNS[StackCirio.Stack] = { ENABLE UNWIND => NULL; RETURN StackCirio.OpenDummyStack[ ampersandContext1: connection.ampersandContext1, ampersandContext2: connection.ampersandContext2, cc: connection.cc, rmtw: connection.rmtw, cedarModules: connection.cedarModules, nub: connection.nub, target: connection.target, fileSet: connection.fileSet, breaks: connection.breaks, lsh: connection.lsh, aph: connection.aph, cParserTable: connection.cParserTable, ShowSource: SourceFileOpsExtras.FullOpenSource, reports: reports]}; FocusOnThread: PUBLIC ENTRY PROC[connection: Connection, threadIndex: CARD, reports: IO.STREAM] RETURNS[newRemoteThreadIndex: CARD] = { ENABLE UNWIND => NULL; connection.currentThread _ IF threadIndex < connection.threads.nThreads THEN threadIndex ELSE 0; RETURN[connection.threads[connection.currentThread].thread.index]; }; GetStackForCurrentThread: PUBLIC ENTRY PROC[connection: Connection, reports: IO.STREAM] RETURNS[StackCirio.Stack] = BEGIN ENABLE UNWIND => NULL; threadData: REF ThreadData _ connection.threads[connection.currentThread]; RETURN[threadData.stack]; END; RopeForDbgMsg: PROC[msg: INT] RETURNS[Rope.ROPE] = BEGIN RETURN[SELECT msg FROM CirioNubAccess.DbgMsgNone => "None", CirioNubAccess.DbgMsgNoHandlerRequest => "NoHandlerRequest", CirioNubAccess.DbgMsgHandlerRequest => "HandlerRequest", CirioNubAccess.DbgMsgBadProceedRequest => "BadProceedRequest", CirioNubAccess.DbgMsgBreakRequest => "BreakRequest", CirioNubAccess.DbgMsgClientRequest => "ClientRequest", CirioNubAccess.DbgMsgProceed => "Proceed", CirioNubAccess.DbgMsgExit => "Kill", CirioNubAccess.DbgMsgAbort => "Abort", ENDCASE => "??"]; END; RopeForSchedState: PROC[state: CARD] RETURNS[Rope.ROPE] = BEGIN RETURN[SELECT state FROM CirioNubAccess.SchedStateFree => "Free", CirioNubAccess.SchedStateReady => "Ready", CirioNubAccess.SchedStateRun => "Run", CirioNubAccess.SchedStateWaitML => "MLWait", CirioNubAccess.SchedStateWaitCV => "CVWait", CirioNubAccess.SchedStateHandlee => "Handlee", ENDCASE => IO.PutFR["??: %g", IO.card[state]]]; END; InstallOneAmpersandItem: PROC[ampersandContext: CirioTypes.Node, name: Rope.ROPE, item: CirioTypes.Node, cc: CC] = BEGIN IF NOT Rope.Equal[Rope.Substr[name, 0, 2], "&&"] THEN ERROR ELSE BEGIN ampersandContextType: CirioTypes.Type _ CedarCode.GetTypeOfNode[ampersandContext]; indirect: CirioTypes.Node _ CedarCode.SelectFieldFromNode[name, ampersandContextType, ampersandContext, cc]; indirectType: CirioTypes.Type _ CedarCode.GetTypeOfNode[indirect]; encapsulatedItem: CirioTypes.Node _ AmpersandContext.MakeNodeFromNode[item, cc]; encapsulatedType: CirioTypes.Type _ CedarCode.GetTypeOfNode[encapsulatedItem]; CedarCode.StoreThroughIndirectNode[encapsulatedType, encapsulatedItem, indirectType, indirect, cc]; END END; ReadOneAmpersandItem: PROC[name: Rope.ROPE, nameScope: CirioTypes.Node, cc: CC] RETURNS[CirioTypes.Node] = BEGIN IF NOT Rope.Equal[Rope.Substr[name, 0, 2], "&&"] THEN ERROR ELSE BEGIN nameScopeType: CirioTypes.Type _ CedarCode.GetTypeOfNode[nameScope]; indirect: CirioTypes.Node _ CedarCode.SelectFieldFromNode[name, nameScopeType, nameScope, cc]; indirectType: CirioTypes.Type _ CedarCode.GetTypeOfNode[indirect]; encapsulatedItem: CirioTypes.Node _ CedarCode.LoadThroughIndirectNode[indirectType, indirect, cc]; RETURN[AmpersandContext.StripAMNode[encapsulatedItem]] END; END; ReadOneAmpersandInt: PROC[name: Rope.ROPE, defaultVal: INT, nameScope: CirioTypes.Node, cc: CC] RETURNS[INT] = BEGIN valNode: CirioTypes.Node _ NIL; valNode _ ReadOneAmpersandItem[name, nameScope, cc ! CCTypes.CCError => {valNode _ NIL; CONTINUE}]; IF valNode = NIL THEN RETURN[defaultVal] ELSE BEGIN val: REF INT _ NARROW[CedarCode.GetNodeRepresentation[valNode, cc]]; RETURN[val^]; END; END; AddSearchDirectory: PUBLIC PROC [connection: Connection, directoryPath: Rope.ROPE, reports: IO.STREAM] = BEGIN inner: PROC RETURNS[Rope.ROPE] = BEGIN AddDir[connection, directoryPath, reports]; IO.PutF[reports, " %g added to search directories\n", IO.rope[directoryPath]]; RETURN [NIL]; END; eMsg: Rope.ROPE; eMsg _ CirioBackstop.Protect[inner, reports]; IF eMsg # NIL THEN IO.PutF[reports, "%g\N", [rope[eMsg]]]; END; RemoveSearchDirectory: PUBLIC PROC [connection: Connection, directoryPath: Rope.ROPE, reports: IO.STREAM] = BEGIN inner: PROC RETURNS[Rope.ROPE] = BEGIN RemoveDir[connection, directoryPath, reports]; IO.PutF[reports, " %g removed from search directories\n", IO.rope[directoryPath]]; RETURN [NIL]; END; eMsg: Rope.ROPE; eMsg _ CirioBackstop.Protect[inner, reports]; IF eMsg # NIL THEN IO.PutF[reports, "%g\N", [rope[eMsg]]]; END; ListSearchDirectory: PUBLIC PROC [connection: Connection, reports: IO.STREAM] = BEGIN inner: PROC RETURNS[Rope.ROPE] = BEGIN ListDir[connection]; RETURN [" done"]; END; eMsg: Rope.ROPE; eMsg _ CirioBackstop.Protect[inner, reports]; IF eMsg # NIL THEN IO.PutF[reports, "%g\N", [rope[eMsg]]]; END; ClearSearchDirectory: PUBLIC PROC [connection: Connection, reports: IO.STREAM] = BEGIN inner: PROC RETURNS[Rope.ROPE] = BEGIN ClearDir[connection]; RETURN [" done"]; END; eMsg: Rope.ROPE; eMsg _ CirioBackstop.Protect[inner, reports]; IF eMsg # NIL THEN IO.PutF[reports, "%g\N", [rope[eMsg]]]; END; AddressData: TYPE = RECORD[byteAddress: CARD, h: Connection]; MkAddress: PROC[byteAddress: CARD, h: Connection] RETURNS[CirioTypes.CirioAddress] = BEGIN addressData: REF AddressData _ NEW[AddressData_[byteAddress, h]]; RETURN[NEW[CirioTypes.CirioAddressBody_[CirioAddressIsNil, ReadRemoteBits, WriteRemoteBits, FollowRemotePointer, AsCardForRemote, addressData]]]; END; ByteBitSize: CARD = 8; CardByteSize: CARD = 4; CirioAddressIsNil: PROC [data: CirioTypes.CirioAddress] RETURNS [BOOL] ~ { addressData: REF AddressData _ NARROW[data.data]; RETURN [addressData.byteAddress=0]}; ReadRemoteBits: PROC[byteOffset: INT _ 0, bitOffset: INT _ 0, bitSize: CARD, data: CirioTypes.CirioAddress] RETURNS[CARD] = BEGIN addressData: REF AddressData _ NARROW[data.data]; byteAddress: INT _ addressData.byteAddress + byteOffset + bitOffset/8; remainingBitOffset: INT _ bitOffset MOD 8; IF bitSize > 32 THEN CCE[operation]; BEGIN cardAddr: INT _ (byteAddress/CardByteSize)*CardByteSize; finalBitOffset: INT _ (byteAddress MOD CardByteSize )*ByteBitSize + remainingBitOffset; nextBitOffset: INT _ finalBitOffset+bitSize; IF nextBitOffset <= 32 THEN -- no word crossing BEGIN container: CARD _ CirioNubAccess.Read32BitsAsCard[[ addressData.h.nub, cardAddr, 0, FALSE, TRUE]]; RETURN[PBasics.BITRSHIFT[PBasics.BITLSHIFT[container, finalBitOffset], 32-bitSize]]; END ELSE -- splits across 4 byte boundary (I am not sure if this will even get tested in the near future, since the rumor is that Mimosa prevents such splits). BEGIN lContainer: CARD _ CirioNubAccess.Read32BitsAsCard[[ addressData.h.nub, cardAddr, 0, FALSE, TRUE]]; rContainer: CARD _ CirioNubAccess.Read32BitsAsCard[[ addressData.h.nub, cardAddr+1, 0, FALSE, TRUE]]; RETURN[PBasics.BITOR[ PBasics.BITLSHIFT[lContainer, finalBitOffset], PBasics.BITRSHIFT[rContainer, (32*2)-(finalBitOffset+bitSize)]]]; END; END; END; WriteRemoteBits: PROC[byteOffset: INT _ 0, bitOffset: INT _ 0, bitSize: CARD, data: CirioTypes.CirioAddress, bits: CARD] = BEGIN addressData: REF AddressData _ NARROW[data.data]; CCE[unimplemented]; END; FollowRemotePointer: PROC[byteOffset: INT _ 0, data: CirioTypes.CirioAddress] RETURNS[CirioTypes.CirioAddress] = BEGIN addressData: REF AddressData _ NARROW[data.data]; newAddressVal: CARD _ ReadRemoteBits[0, 0, 32, data]; RETURN[MkAddress[newAddressVal, addressData.h]]; END; AsCardForRemote: PROC[data: CirioTypes.CirioAddress] RETURNS[CARD] = BEGIN addressData: REF AddressData _ NARROW[data.data]; RETURN[addressData.byteAddress]; END; RdCards: PROC[a: CirioTypes.CirioAddress, nCards: CARD] = BEGIN CardsPerLine: CARD = 10; FOR x: CARD IN [0..(nCards+CardsPerLine-1)/CardsPerLine) DO n: CARD _ MIN[CardsPerLine, nCards - CardsPerLine*x]; textLine: IO.STREAM _ IO.ROS[]; IO.PutF[textLine, "\T"]; FOR I: CARD IN [0..n) DO oneCard: CARD _ a.readBits[CardsPerLine*4*x+4*I, 0, 32, a]; IO.PutF[textLine, " %g", IO.card[oneCard]]; ENDLOOP; SystemInterface.ShowReport[IO.RopeFromROS[textLine], $urgent]; ENDLOOP; END; RdHexCards: PROC[a: CirioTypes.CirioAddress, nCards: CARD] = BEGIN CardsPerLine: CARD = 10; FOR x: CARD IN [0..(nCards+CardsPerLine-1)/CardsPerLine) DO n: CARD _ MIN[CardsPerLine, nCards - CardsPerLine*x]; textLine: IO.STREAM _ IO.ROS[]; IO.PutF[textLine, "\T"]; FOR I: CARD IN [0..n) DO oneCard: CARD _ a.readBits[CardsPerLine*4*x+4*I, 0, 32, a]; IO.PutF[textLine, " %g", IO.rope[Convert.RopeFromCard[oneCard, 16]]]; ENDLOOP; SystemInterface.ShowReport[IO.RopeFromROS[textLine], $urgent]; ENDLOOP; END; RdBytes: PROC[a: CirioTypes.CirioAddress, nBytes: CARD] = BEGIN BytesPerLine: CARD = 20; FOR x: CARD IN [0..(nBytes+BytesPerLine-1)/BytesPerLine) DO n: CARD _ MIN[BytesPerLine, nBytes - BytesPerLine*x]; textLine: IO.STREAM _ IO.ROS[]; IO.PutF[textLine, "\T"]; FOR I: CARD IN [0..n) DO oneByte: CARD _ a.readBits[BytesPerLine*x+I, 0, 8, a]; IO.PutF[textLine, " %g", IO.rope[Convert.RopeFromCard[oneByte, 16]]]; ENDLOOP; SystemInterface.ShowReport[IO.RopeFromROS[textLine], $urgent]; ENDLOOP; END; RdChars: PROC[a: CirioTypes.CirioAddress, nChars: CARD] = BEGIN CharsPerLine: CARD = 20; FOR x: CARD IN [0..(nChars+CharsPerLine-1)/CharsPerLine) DO n: CARD _ MIN[CharsPerLine, nChars - CharsPerLine*x]; textLine: IO.STREAM _ IO.ROS[]; IO.PutF[textLine, "\T"]; FOR I: CARD IN [0..n) DO oneChar: CARD _ a.readBits[CharsPerLine*x+I, 0, 8, a]; IO.PutF[textLine, " %g", IO.char[VAL[BYTE[oneChar]]]]; ENDLOOP; SystemInterface.ShowReport[IO.RopeFromROS[textLine], $urgent]; ENDLOOP; END; RdRope: PROC[a: CirioTypes.CirioAddress, nChars: CARD _ 100] = BEGIN ropeBodyAddr: CirioTypes.CirioAddress _ a.followPointer[0, a]; ropeBodyContents: CARD _ ropeBodyAddr.readBits[0, 0, 32, ropeBodyAddr]; rope: Rope.ROPE _ NIL; SeeOneChar: PROC[c: CHAR] = {rope _ Rope.Cat[rope, Rope.FromChar[c]]}; GenCharsForRope[a.followPointer[0, a], 0, nChars, SeeOneChar]; SystemInterface.ShowReport[rope, $urgent]; END; Field: TYPE = RECORD[offset: INT, size: CARD]; GenCharsForRope: PROC[a: CirioTypes.CirioAddress, first: CARD, nChars: CARD, for: PROC[CHAR]] = BEGIN tagF: Field = [0, 1]; tag: CARD _ a.readBits[tagF.offset, 0, tagF.size, a]; ShowClient: PROC[c: CHAR] RETURNS[quit: BOOL] = {for[c]; RETURN[FALSE]}; SystemInterface.ShowReport[IO.PutFR["tag = %g", IO.rope[Convert.RopeFromCard[tag, 16]]], $urgent]; SELECT tag FROM 0 => -- we are looking at a text BEGIN lengthF: Field = [1, 15]; maxF: Field = [16, 16]; length: CARD _ a.readBits[0, lengthF.offset, lengthF.size, a]; max: CARD _ a.readBits[0, maxF.offset, maxF.size, a]; n: CARD _ IF first >= length THEN 0 ELSE MIN[length-first, nChars]; FOR I: CARD IN [0..n) DO byte: CARD _ a.readBits[4+first+I, 0, 8, a]; for[VAL[BYTE[byte]]]; ENDLOOP; END; 1 => -- we are looking at a node BEGIN sizeF: Field = [1, 31]; depthF: Field = [32, 30]; casesF: Field = [62, 2]; size: CARD _ a.readBits[0, sizeF.offset, sizeF.size, a]; depth: CARD _ a.readBits[0, depthF.offset, depthF.size, a]; cases: CARD _ a.readBits[0, casesF.offset, casesF.size, a]; n: CARD _ IF first >= size THEN 0 ELSE MIN[size-first, nChars]; IF n > 0 THEN SELECT cases FROM 0 => -- substr BEGIN baseF: Field = [64, 32]; startF: Field = [96, 32]; base: CirioTypes.CirioAddress _ a.followPointer[baseF.offset/8, a]; start: CARD _ a.readBits[0, startF.offset, startF.size, a]; [] _ Rope.Map[base: "??substr??", action: ShowClient]; GenCharsForRope[base, start, n, for]; END; 1 => -- concat BEGIN baseF: Field = [64, 32]; restF: Field = [96, 32]; posF: Field = [128, 32]; base: CirioTypes.CirioAddress _ a.followPointer[baseF.offset/8, a]; rest: CirioTypes.CirioAddress _ a.followPointer[restF.offset/8, a]; pos: CARD _ a.readBits[0, posF.offset, posF.size, a]; [] _ Rope.Map[base: "??concat??", action: ShowClient]; IF first < pos THEN BEGIN GenCharsForRope[base, first, MIN[pos-first, n], for]; IF n > pos-first THEN GenCharsForRope[rest, 0, n-pos+first, for]; END ELSE GenCharsForRope[rest, first-pos, n, for]; END; 2 => BEGIN baseF: Field = [64, 32]; replaceF: Field = [96, 32]; startF: Field = [128, 32]; oldPosF: Field = [160, 32]; newPosF: Field = [192, 32]; base: CirioTypes.CirioAddress _ a.followPointer[baseF.offset/8, a]; replace: CirioTypes.CirioAddress _ a.followPointer[replaceF.offset/8, a]; start: CARD _ a.readBits[0, startF.offset, startF.size, a]; oldPos: CARD _ a.readBits[0, oldPosF.offset, oldPosF.size, a]; newPos: CARD _ a.readBits[0, newPosF.offset, newPosF.size, a]; [] _ Rope.Map[base: "??replace??", action: ShowClient]; IF n > 0 AND first < start THEN BEGIN GenCharsForRope[base, first, MIN[n, start-first], for]; first _ start; n _ n-MIN[n, start-first]; END; IF n > 0 AND first < newPos THEN BEGIN GenCharsForRope[replace, first-start, MIN[n, newPos-first], for]; first _ newPos; n _ n - MIN[n, newPos-first]; END; IF n > 0 AND first < size THEN GenCharsForRope[base, first-newPos+oldPos, n, for]; END; 3 => [] _ Rope.Map[base: "??ObjectRope??", action: ShowClient]; ENDCASE => CCE[cirioError]; END; ENDCASE => CCE[cirioError]; END; FrameDiagnosticInfo: PROC[h: Connection] = BEGIN threadIndex: CARD _ h.currentThread; td: REF ThreadData _ h.threads[threadIndex]; StackCirio.FrameDiagnosticInfo[td.stack, h.tsOut]; END; SetBreakAtAbsAddr: PROC[h: Connection, absAddr: CARD32, mesaPos: SourceFileOpsExtras.Position, stopAll: BOOLEAN] = {CirioBreakAccess.SetBreakAtAbsAddr[h.breaks, absAddr, mesaPos, stopAll]}; ListBreaks: PROC[h: Connection] = {CirioBreakAccess.ListBreaks[h.breaks]}; ClearBreakAtAbsAddr: PROC[h: Connection, absAddr: CARD32] = {CirioBreakAccess.ClearBreakAtAbsAddr[h.breaks, absAddr]}; ClearBreakAtIndex: PROC[h: Connection, index: CARD] = {CirioBreakAccess.ClearBreakAtIndex[h.breaks, index]}; ClearAllBreaks: PROC[h: Connection] = {CirioBreakAccess.ClearAllBreaks[h.breaks]}; AddDir: PROC [h: Connection, dirName: Rope.ROPE, reports: IO.STREAM] = BEGIN properDirName: PFSNames.PATH _ PFS.PathFromRope[dirName]; prev: LIST OF PFSNames.PATH _ NIL; WHILE TRUE DO current: LIST OF PFSNames.PATH _ IF prev # NIL THEN prev.rest ELSE h.searchDirectories; IF current = NIL THEN EXIT; IF current.first.Equal[properDirName] THEN BEGIN IF prev = NIL THEN h.searchDirectories _ current.rest ELSE prev.rest _ current.rest; EXIT; END; prev _ current; ENDLOOP; h.searchDirectories _ CONS[properDirName, h.searchDirectories]; NewRMTW.ResetSearchPaths[h.cedarModules, h.searchDirectories, BasicTime.Now[]]; IF h.rmtw#NIL THEN NewRMTW.FlushUnknownSymbolCache[h.rmtw, BasicTime.Now[], reports]; IF h.threads # NIL THEN FOR ti: CARDINAL IN [0..h.threads.nThreads) DO td: REF ThreadData _ h.threads[ti]; StackCirio.NoteFileCacheFlush[td.stack]; ENDLOOP; END; RemoveDir: PROC [h: Connection, dirName: Rope.ROPE, reports: IO.STREAM] = BEGIN properDirName: PFSNames.PATH _ PFS.PathFromRope[dirName]; prev: LIST OF PFSNames.PATH _ NIL; WHILE TRUE DO current: LIST OF PFSNames.PATH _ IF prev # NIL THEN prev.rest ELSE h.searchDirectories; IF current = NIL THEN EXIT; IF current.first.Equal[properDirName] THEN BEGIN IF prev = NIL THEN h.searchDirectories _ current.rest ELSE prev.rest _ current.rest; EXIT; END; prev _ current; ENDLOOP; NewRMTW.ResetSearchPaths[h.cedarModules, h.searchDirectories, BasicTime.Now[]]; NewRMTW.FlushUnknownSymbolCache[h.rmtw, BasicTime.Now[], reports]; IF h.threads # NIL THEN FOR ti: CARDINAL IN [0..h.threads.nThreads) DO td: REF ThreadData _ h.threads[ti]; StackCirio.NoteFileCacheFlush[td.stack]; ENDLOOP; END; ListDir: PROC [h: Connection] = BEGIN searchDirectories: Rope.ROPE _ NIL; FOR paths: LIST OF PFSNames.PATH _ h.searchDirectories, paths.rest WHILE paths # NIL DO searchDirectories _ Rope.Cat[searchDirectories, PFS.RopeFromPath[paths.first], " "]; ENDLOOP; SystemInterface.ShowReport[IO.PutFR["%g", IO.rope[searchDirectories]], $urgent]; END; ClearDir: PROC [h: Connection] = BEGIN SystemInterface.ShowReport[IO.PutFR["Clearing search directory list"], $urgent]; SystemInterface.ShowReport[IO.PutFR["Was: "], $urgent]; ListDir[h]; h.searchDirectories _ NIL; NewRMTW.ResetSearchPaths[h.cedarModules, h.searchDirectories, BasicTime.Now[]]; END; LookupSym: PROC[h: Connection, name: Rope.ROPE, numToSkip: INT _ 0, externOnly: BOOL _ TRUE] RETURNS[CirioNubAccess.SymEntry] = {RETURN[CirioNubAccess.LookupSymEntryByName[h.nub, name, FALSE, externOnly, numToSkip]]}; LookupAddr: PROC[h: Connection, val: CARD, numToSkip: INT _ 0] RETURNS[CirioNubAccess.SymEntry] = {RETURN[CirioNubAccess.LookupSymEntryByValue[h.nub, val, numToSkip]]}; LookupID: PROC[h: Connection, symID: CARD] RETURNS[CirioNubAccess.SymEntry] = {RETURN[CirioNubAccess.LookupSymEntryByID[h.nub, symID]]}; LookupFile: PROC[h: Connection, seqNum: CARD] RETURNS[entry: CirioNubAccess.FileEntry] = {RETURN[CirioNubAccess.GetFileEntry[h.nub, seqNum]]}; GetPCInfo: PROC[h: Connection, absPC: CARD] RETURNS[CirioNubAccess.PCInfo] = {RETURN[CirioNubAccess.PCtoInfo[h.nub, absPC]]}; DebugOn: PROC = BEGIN DebugFlag _ TRUE; END; DebugOff: PROC = BEGIN DebugFlag _ FALSE; END; GetRelPCForCLine: PROC[dotOName: Rope.ROPE, cLineNum: CARD, h: Connection] RETURNS[CARD] = BEGIN dotOPath: PFSNames.PATH _ PFS.PathFromRope[dotOName]; file: SystemInterface.CirioFile _ SystemInterface.GetCirioFileFromDebuggee[h.fileSet, dotOPath, h.serverName]; IF file=NIL THEN CCE[cirioError, IO.PutFR["Couldn't access %g", [rope[dotOName]] ]]; {container: ObjF.Parsed _ ObjF.CreateParsed[file]; AcquireModule: PROC RETURNS[ObjF.Module] = BEGIN RETURN[ObjF.ModuleFromParsedAndPC[container, [[0, ""], 1]]]; END; dotO: ObjF.Module _ AcquireModule[]; relPC: CARD _ ObjF.GetPCForLineNum[dotO, cLineNum].relPC; RETURN[relPC];} END; GetCLineForRelPC: PROC[dotOName: Rope.ROPE, relPC: CARD, h: Connection] RETURNS[CARD] = BEGIN dotOPath: PFSNames.PATH _ PFS.PathFromRope[dotOName]; file: SystemInterface.CirioFile _ SystemInterface.GetCirioFileFromDebuggee[h.fileSet, dotOPath, h.serverName]; IF file=NIL THEN CCE[cirioError, IO.PutFR["Couldn't access %g", [rope[dotOName]] ]]; {container: ObjF.Parsed _ ObjF.CreateParsed[file]; AcquireModule: PROC RETURNS[ObjF.Module] = BEGIN RETURN[ObjF.ModuleFromParsedAndPC[container, [[0, ""], 1]]]; END; dotO: ObjF.Module _ AcquireModule[]; cLine: CARD _ ObjF.GetLineNumForPC[dotO, [[0, ""], relPC]]; RETURN[cLine];} END; keyName: Rope.ROPE _ "_CirioDebuggeeTestFrame_"; RemoteCirioTest: Commander.CommandProc = BEGIN args: CommandTool.ArgumentVector _ CommandTool.Parse[cmd]; serverName: Rope.ROPE _ args[1]; portNum: CARDINAL _ IF args.argc <= 2 THEN 4815 ELSE CARDINAL[Convert.CardFromRope[args[2]]]; reports: IO.STREAM _ IO.ROS[]; connection: Connection _ OpenConnection[serverName, portNum, LIST[FileNames.CurrentWorkingDirectory[]], reports]; remoteWorldStopped: BOOLEAN _ FALSE; CleanUp: PROC = BEGIN IF remoteWorldStopped THEN ResumeRemoteWorld[connection]; remoteWorldStopped _ FALSE; CloseConnection[connection, reports]; IO.Close[reports] END; BEGIN ENABLE UNWIND => CleanUp[]; TestInner: PROC = BEGIN nThreads: CARD _ StopRemoteWorld[connection, reports]; remoteWorldStopped _ TRUE; BEGIN interestingThreads: LIST OF CARD _ FindThreadsWithProperty[connection, [callingDebugger[]], cmd.out]; FOR ts: LIST OF CARD _ interestingThreads, ts.rest WHILE ts # NIL DO x: CARD _ ts.first; stack: StackCirio.Stack; [] _ FocusOnThread[connection, x, cmd.out]; stack _ GetStackForCurrentThread[connection, cmd.out]; [] _ StackCirio.ResetStack[stack, cmd.out]; IO.PutF[cmd.out, "searching thread %g\N", IO.rope[GetThreadTitleText[connection, x]]]; IF StackCirio.WalkStackToCProcedure[stack, keyName, "", cmd.out] THEN BEGIN nUnexpectedResults: CARD _ 0; BEGIN frameText: Rope.ROPE _ StackCirio.ShowCurrentFrame[stack, cmd.out]; IO.PutF[cmd.out, "\n\n%g\n\n", IO.rope[frameText]]; END; BEGIN frame1Tests: LIST OF TestDescriptor _ LIST[ ["key", "44444"], ["inner", "(invalid proc descriptor address)"], ["result", "237864", 0, uninitializedVar], ["b", "[a:6, b:7]"], ["w", "[x:[a:4, b:5], y:[u:6, v:7]]"], ["y", "failure due to illegal operation: y undefined"], ["action", "???"], ["foo", "test.(no name)(pc=D30C4Ch, descr at C7BCC0h, src=1412)", 18], ["bar", "???"], ["x", "10"], ["veryBad", "???"], ["CallDebugger", "failure due to illegal operation: CallDebugger undefined"]]; nUnexpectedResults _ ExamineOneFrame[connection, frame1Tests, cmd.out] + nUnexpectedResults; END; [] _ StackCirio.WalkStack[stack, 1, cmd.out]; BEGIN frameText: Rope.ROPE _ StackCirio.ShowCurrentFrame[stack, cmd.out]; IO.PutF[cmd.out, "\n\n%g\n\n", IO.rope[frameText]]; END; BEGIN frame2Tests: LIST OF TestDescriptor _ LIST[ ["c", "'a"], ["quit", "FALSE"], ["bool1", "FALSE"], ["bool2", "TRUE"], ["charA", "'A"], ["charB", "'b"], ["array1", "(7)[6, 8, 10, 12, 14, 16, 18]"], ["array2", "(6)[11, 13, 15, 17, 19, 21]"], ["refR", "^[a:7, b:8]"], ["bb", "[ref:^[ref:NIL, a:45, b:46], a:47, b:48]"], ["refSeq", "^[x:10, (5)[3, 7, 11, 15, 19]]"], ["refSeq2", "^[y:45, (7)[TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE]]"], ["ref2Seq2", "^[y:77, (32)[TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, ...]]"], ["b", "[a:6, b:7]"], ["w", "[x:[a:4, b:5], y:[u:6, v:7]]"], ["y", "failure due to illegal operation: y undefined"], ["action", "???"], ["foo", "test.(no name)(pc=D3217Ch, descr at C7BE90h, src=1412)", 18], ["bar", "???"], ["x", "10"], ["veryBad", "???"], ["CallDebugger", "failure due to illegal operation: CallDebugger undefined"]]; nUnexpectedResults _ ExamineOneFrame[connection, frame2Tests, cmd.out] + nUnexpectedResults; END; [] _ StackCirio.WalkStack[stack, 2, cmd.out]; BEGIN frameText: Rope.ROPE _ StackCirio.ShowCurrentFrame[stack, cmd.out]; IO.PutF[cmd.out, "\n\n%g\n\n", IO.rope[frameText]]; END; BEGIN frame3Tests: LIST OF TestDescriptor _ LIST[ ["a", "22222"], ["deep", "1606016"], ["rope", "failure due to internal Cirio error"], ["arg1", "1234"], ["arg2", "5678"], ["res1", "node?"], ["res2", "node?"], ["z", "8518320"], ["yy", "3807"], ["ll", "x"], ["mm", "f"], ["q", "(invalid proc descriptor address)"], ["b", "[a:6, b:7]"], ["w", "[x:[a:4, b:5], y:[u:6, v:7]]"], ["y", "failure due to illegal operation: y undefined"], ["action", "???"], ["foo", "test.(no name)(pc=D3217Ch, descr at C7BE90h, src=1412)", 18], ["bar", "???"], ["x", "10"], ["veryBad", "???"], ["CallDebugger", "failure due to illegal operation: CallDebugger undefined"]]; nUnexpectedResults _ ExamineOneFrame[connection, frame3Tests, cmd.out] + nUnexpectedResults; END; IF nUnexpectedResults = 0 THEN IO.PutF[cmd.out, "\N\NThere were NO unexpected results\N\N"] ELSE IO.PutF[cmd.out, "\N\NThere were %g unexpected results\N\N", IO.card[nUnexpectedResults]]; EXIT; END; ENDLOOP; END; END; TestInner[]; -- so that unwinds from aborts from breakpoints will be caught END; CleanUp[] END; TestDescriptor: TYPE = RECORD[ expression: Rope.ROPE, expectedResult: Rope.ROPE, compareNCharsOnly: CARD _ 0, validity: Validity _ valid]; Validity: TYPE = {valid, uninitializedVar, WRONG}; ExamineOneFrame: PROC[connection: Connection, tryThis: LIST OF TestDescriptor, reports: IO.STREAM] RETURNS[--nUnexpectedResults-- CARD] = BEGIN ResultDescriptor: TYPE = RECORD[ expression: Rope.ROPE, expectedResult: Rope.ROPE, actualResult: Rope.ROPE]; deltas: LIST OF ResultDescriptor _ NIL; lastDelta: LIST OF ResultDescriptor _ NIL; news: LIST OF TestDescriptor _ NIL; lastNew: LIST OF TestDescriptor _ NIL; nUnexpectedResults: CARD _ 0; stack: StackCirio.Stack _ GetStackForCurrentThread[connection, reports]; FOR tests: LIST OF TestDescriptor _ tryThis, tests.rest WHILE tests # NIL DO result: Rope.ROPE _ StackCirio.InterpretTextLine[stack, tests.first.expression, reports]; new: LIST OF TestDescriptor _ LIST[[tests.first.expression, result, tests.first.compareNCharsOnly, tests.first.validity]]; nChars: CARD _ IF tests.first.compareNCharsOnly > 0 THEN tests.first.compareNCharsOnly ELSE Rope.Length[tests.first.expectedResult]; IF news = NIL THEN news _ new ELSE lastNew.rest _ new; lastNew _ new; IO.PutF[reports, "for expression: %g we get\N\T%g\N", IO.rope[tests.first.expression], IO.rope[result]]; IF (tests.first.validity # uninitializedVar) AND NOT Rope.Equal[Rope.Substr[result, 0, nChars], Rope.Substr[tests.first.expectedResult, 0, nChars]] THEN BEGIN delta: LIST OF ResultDescriptor _ LIST[[tests.first.expression, tests.first.expectedResult, result]]; IO.PutF[reports, " THIS IS WRONG, we expected\N\T%g\N\N", IO.rope[tests.first.expectedResult]]; IF deltas = NIL THEN deltas _ delta ELSE lastDelta.rest _ delta; lastDelta _ delta; nUnexpectedResults _ nUnexpectedResults + 1; END; ENDLOOP; IO.PutF[reports, "\N\Nhere is a list of expressions with their actual results\N"]; FOR items: LIST OF TestDescriptor _ news, items.rest WHILE items # NIL DO IO.PutF[reports, "\T[\"%g\", \"%g\"", IO.rope[items.first.expression], IO.rope[items.first.expectedResult]]; IF items.first.compareNCharsOnly > 0 OR items.first.validity # valid THEN IO.PutF[reports, ", %g", IO.card[items.first.compareNCharsOnly]]; IF items.first.validity # valid THEN IO.PutF[reports, ", %g", IO.rope[SELECT items.first.validity FROM uninitializedVar => "uninitializedVar", WRONG => "WRONG", ENDCASE => ERROR]]; IO.PutF[reports, "],\N"]; ENDLOOP; IF deltas # NIL THEN BEGIN IO.PutF[reports, "\N\Nthere were unexpected results\N"]; FOR items: LIST OF ResultDescriptor _ deltas, items.rest WHILE items # NIL DO IO.PutF[reports, "\Texpression: %g\N", IO.rope[items.first.expression]]; IO.PutF[reports, "\Texpected result: %g\N", IO.rope[items.first.expectedResult]]; IO.PutF[reports, "\Tactual result: %g\N", IO.rope[items.first.actualResult]]; ENDLOOP; END ELSE IO.PutF[reports, "\N\Nthere were NO unexpected results\N\N"]; RETURN[nUnexpectedResults]; END; InstallBreakCheckDaemon: PUBLIC PROC [connection: Connection, reports: IO.STREAM] = BEGIN IO.PutF[reports, "Installing daemon for breakpoint hit ...\n"]; connection.daemonKillFlag _ FALSE; connection.daemon _ FORK BreakCheckDaemon[connection: connection, reports: reports]; Process.Detach[connection.daemon]; IO.PutF[reports, " fork finished.\n"]; END; StopBreakCheckDaemon: PUBLIC PROC [connection: Connection, reports: IO.STREAM] = BEGIN connection.remoteWorldRunning _ FALSE; IO.PutF[reports, "killing BreakCheckDaemon...\n"]; connection.daemonKillFlag _ TRUE; Process.PauseMsec[3000]; END; BreakCheckDaemon: PROC [connection: Connection, reports: IO.STREAM] = BEGIN whichError: Rope.ROPE _ "$unkown"; { Process.SetPriority[Process.priorityBackground]; DO IF connection.daemonKillFlag = TRUE THEN GOTO terminate; WHILE connection.remoteWorldRunning = FALSE DO Process.PauseMsec[2000]; IF connection.daemonKillFlag = TRUE THEN GOTO terminate; ENDLOOP; IF CirioNubAccess.WaitSig[h: connection.nub, timeoutMilliSec: 100 ! CirioNub.Error => { whichError _ Rope.Cat["CirioNub (", Atom.GetPName[code], ")"]; GOTO connectionError; }; CirioNubAccess.Error => { l: LIST OF ATOM _ codes; didAny: CARD _ 0; whichError _ Rope.Cat["CirioNubAccess: ", msg, " ("]; WHILE l # NIL DO IF didAny # 0 THEN whichError _ whichError.Concat[", "]; whichError _ whichError.Concat[Atom.GetPName[l.first]]; l _ l.rest; ENDLOOP; GOTO connectionError; };] = FALSE THEN IO.PutF[reports, "SIGINT: Debuggee needs attention.\n"! IO.Error => GOTO ret]; Process.PauseMsec[2000]; ENDLOOP; EXITS terminate => {IO.PutF[reports, "BreakCheckDaemon killed.\n"! IO.Error => CONTINUE];RETURN}; connectionError => { IO.PutF[reports, "connection lost! %g BreakCheckDaemon exited.\n", [rope[whichError]]]; connection.open _ FALSE; RETURN}; ret => RETURN; }; END; Commander.Register["RemoteCirioTest", RemoteCirioTest]; END.. %f RemoteCirioImpl.mesa Copyright Σ 1990, 1991, 1992 by Xerox Corporation. All rights reserved. Sturgis, April 20, 1990 2:29 pm PDT Last changed by Theimer on November 28, 1989 3:36:23 pm PST Last tweaked by Mike Spreitzer on July 24, 1992 6:20 pm PDT Linda Howe January 8, 1990 11:02:07 am PST Coolidge, July 29, 1990 1:51 pm PDT Laurie Horton, March 31, 1992 12:48 pm PST Philip James, February 3, 1992 10:41 am PST Udagawa, February 12, 1991 8:57 pm PST Debugging aids This variable can be set/reset by the ampersand routines &&DebugOn and &&DebugOff. Types Connections The caller is responsible for eventually calling CloseConnection. No subsequent connections can be made to the same pair until Close has been called. Note: closing the connection invalidates all RemoteAddresses held for connection.nub. Question: how much of the items constructed below can/should we reused? A remote world needs to have the navel examination in CreateRemoteMimosaTargetWorld succeed; that requires finding CirioThings/CirioRopeHelper.mob, Rope/Rope.mob, and Atom/AtomPrivate.mob (on August 17, 1991). Build the list of search directories, starting with the user supplied directories. Join the user supplied and default search directories. target _ CirioTargets.CreateTarget[nub]; We nest a block so that we can provide an unwind catch phrase to close the nub in the event of trouble before we hand responsibility to our caller. (We also close the file set and clear all breaks.) ampersandContext1 _ AmpersandContext.CreateAnAmpersandContext[cc]; ampersandContext2 _ AmpersandContext.CreateAnAmpersandContext[cc]; ampersandContext1: ampersandContext1, ampersandContext2: ampersandContext2, InstallBreakCheckDaemon[connection, reports]; disables the following ampersand routines. Should move any useful ones to NewAmpersandProcs. Threads WHILE NOT WaitSig[nub, 1000] DO ENDLOOP; also resets the thread data as needed. from [palain-uX]<>jaune>xrhome>DEVELOPMENT>INCLUDE>xr>Threads.h we have: XR_DB_MSG_PROCEED_REPLY (-1) XR_DB_MSG_EXIT_REPLY (-2) XR_DB_MSG_ABORT_REPLY (-3) now we have to reconstruct our thread info for this thread Stack Frames support Temporary access to C frame nodes etc. This procedure interfaces to RCTWImpl.GetCCAndFrameFromDotO. GetCFrameNode: PROC[serverName: Rope.ROPE, frameInfo: May4Exp.ProcedureFrameInfo, nub: CirioNubAccess.Handle, symbols: REF SymbolFinding.FoundSymbols] RETURNS[CC, CirioTypes.Node] = BEGIN cFrameInfo: RCTW.ProcedureFrameInfo _ NEW[RCTW.ProcedureFrameInfoBody_[ dotOLongName: frameInfo.dotOInfo.fileName, mTime: frameInfo.dotOInfo.mtime, size: frameInfo.dotOInfo.size, fmagic: frameInfo.dotOInfo.fmagic, smagic: frameInfo.dotOInfo.smagic, stamp: frameInfo.dotOInfo.stamp, codeBase: frameInfo.dotOInfo.textReloc, dataBase: frameInfo.dotOInfo.dataReloc, bssBase: frameInfo.dotOInfo.bssReloc, relativePC: frameInfo.relativePC, framePointer: frameInfo.framePointer, stackPointer: frameInfo.stackPointer]]; cc: CC; node: CirioTypes.Node; [cc, node] _ RCTW.GetCCAndFrameFromDotO[serverName, cFrameInfo, nub, symbols.embeddedDotO ! CCTypes.CCError => BEGIN cc _ NIL; node _ NIL; May4Exp.ShowReport[RopeForCCError[case, msg]]; CONTINUE END]; RETURN[cc, node]; END; ampersand support need to install a catch phrase for NARROW fault source and break positions Queries the user for a directory name and adds it to the front of the list of search directories. Set the search directory. Queries the user for a directory name and removes it from the list of search directories. Remove the search directory. List all current search directories. Clear all search directories. ampersand procedures experimental this is adapted from NewRMTWImplA.NRFBFReadBits perhaps we could define some common code somewhere? as per our charter, 32 bits at most here is where we do the read This procedure assumes that a is the address of a variable holding a rope. That is, the contents of the 32 bits at address a is (roughly) a pointer to a rope body. The field declarations in the following procedures must agree with Rope.RopeRep in the PCedar world (see [PCedar2.0]Rope.mesa) This procedure assumes that a is the address of a rope body. breakpoints (tentative, using ampersand procedures) properDirName: Rope.ROPE _ CirioDeltaFace.ConvertToLocalDirectoryFormat[dirName]; first, we remove any existing entry for the path now we install the path at the front of the list now we inform those who need to know first, we remove any existing entry for the path now we inform those who need to know now we inform those who need to know note: we need not do a NewRMTW.FlushUnknownSymbolCache[h.rmtw, BasicTime.Now[]], because that need only be called when new definition mobs become accessible, not when some become inaccessible. symbols misc dotOName1: Rope.ROPE _ CirioDeltaFace.ConvertFileNameToLocalFormat[dotOName]; range: ObjF.StabRange _ ObjF.AlternativeFindModuleStabRange[container, 1]; another Kludge range: ObjF.StabRange _ ObjF.AlternativeFindModuleStabRange[container, 1]; GetMesaPosForCLine: PROC[mesaFileName: Rope.ROPE, cLine: CARD, h: Connection] = BEGIN reports: IO.STREAM _ IO.ROS[]; cFileName: Rope.ROPE _ SystemInterface.MesaFileNameToCFileName[mesaFileName, reports]; reportsText: Rope.ROPE _ IO.RopeFromROS[reports]; IF Rope.Length[reportsText] # 0 THEN May4Exp.ShowReport[reportsText]; IF cFileName = NIL THEN CCE[cirioError]; BEGIN cFile: SystemInterface.CirioFile _ SystemInterface.GetCirioFile[h.fileSet, cFileName]; cFileInfo: May4Exp.CFileInfo _ May4Exp.CreateCFileInfo[cFile]; resultingMesaSourcePos: CARD _ May4Exp.LookupCLineNum[cFileInfo, cLine]; mesaFileStream: IO.STREAM; -- to test for the presence of the file May4Exp.ShowReport[IO.PutFR["corresponding position is %g in %g", IO.card[resultingMesaSourcePos], IO.rope[mesaFileName]]]; lets test to see if the mesa file is around mesaFileStream _ FS.StreamOpen[cFileName ! FS.Error => CONTINUE]; IF mesaFileStream = NIL THEN {May4Exp.ShowReport["unable to open mesa file"]; RETURN}; IO.Close[mesaFileStream]; SystemInterface.ShowSource[fileName: mesaFileName, index: resultingMesaSourcePos, feedBack: reports]; END; END; Misc support GetCurrentFrameInfo: PROC [connection: Connection, reports: IO.STREAM] RETURNS [dotOFileName: Rope.ROPE, procName: Rope.ROPE, relPC: CARD] = BEGIN ENABLE UNWIND => NULL; inner: PROC RETURNS[Rope.ROPE] = BEGIN td: REF ThreadData _ connection.threads[connection.currentThread]; IF td.currentFrameSymbols = NIL THEN td.currentFrameSymbols _ FindFrameSymbols[connection, td]; BEGIN embeddedDotOInfo: REF ObjectFiles.ModuleInfo _ ObjectFiles.GetModuleInfo[td.currentFrameSymbols.embeddedDotO]; frame: May4Exp.ProcedureFrameInfo _ td.currentFrame; dotOFileName1: Rope.ROPE; frameDotOFileName: Rope.ROPE _ frame.dotOInfo.fileName; loc: INT _ Rope.FindBackward[frameDotOFileName, "/"] + 1; dotOFileName _ Rope.Replace[base: frameDotOFileName, start: loc, with: LoadStateRootFileName[connection, frame]]; Convert to the standard file system format. dotOFileName _ SystemInterface.ConvertFileNameToLocalFormat[dotOFileName]; Find out which file system view we need for this file. dotOFileName1 _ SystemInterface.DetermineFileSystemView[dotOFileName, reports]; IF dotOFileName1 # NIL THEN BEGIN dotOFileName _ dotOFileName1; END ELSE BEGIN May4Exp.ShowReport[IO.PutFR["File %g can't be found.", IO.rope[dotOFileName]]]; CCE[cirioError]; END; procName _ frame.pcInfo.procName; relPC _ frame.relativePC - embeddedDotOInfo.startPC; RETURN [dotOFileName]; END; END; [] _ CirioBackstop.Protect[inner, reports]; RETURN; END; LoadStateRootFileName: PROC [connection: Connection, frame: May4Exp.ProcedureFrameInfo] RETURNS [dotOFileName: Rope.ROPE] = BEGIN frameDotOFileName: Rope.ROPE _ frame.dotOInfo.fileName; loc: INT _ Rope.FindBackward[frameDotOFileName, "/"] + 1; frameDotORootFileName: Rope.ROPE _ Rope.Substr[frameDotOFileName, loc]; rootDotOName: Rope.ROPE _ frame.pcInfo.guessedEmbeddedFileName; symEntryResult: CirioNubAccess.LookupSymEntryResult; symValue: CARD; numToSkip: INT; IF Rope.IsEmpty[rootDotOName] THEN RETURN [NIL]; symEntryResult _ LookupID[connection, frame.pcInfo.guessedEmbeddedFileSymID]; WITH symEntryResult SELECT FROM ser: REF CirioNubAccess.LookupSymEntryResultBody.case0 => symValue _ ser.symEntry.value; ENDCASE => CCE[cirioError, "Bad args to LookupID"]; IF Rope.Equal[frameDotORootFileName, rootDotOName] THEN dotOFileName _ rootDotOName ELSE BEGIN numToSkip _ -1; DO symEntryResult _ LookupAddr[connection, symValue, numToSkip]; WITH symEntryResult SELECT FROM ser: REF CirioNubAccess.LookupSymEntryResultBody.case0 => dotOFileName _ ser.symEntry.name; ENDCASE => CCE[cirioError, "Bad args to LookupAddr"]; IF NOT Rope.Equal[dotOFileName, rootDotOName] THEN EXIT; numToSkip _ numToSkip - 1; ENDLOOP; END; RETURN [dotOFileName]; END; Test driver use RemoteCirioTest menhir 4816 the subject is [Cirio]sturgis>test>test.mesa and lives in [Cirio]sturgis>SturgisLocalSun.df the test lists were last updated: December 12, 1989 2:03:22 pm PST open a block to so that unwind catches can cleanup (note: we need not lock a monitor, since only one thread has access to the connection data.) now we examine the frame now we perform the individual expression tests lets look at the next frame and examine now we perform the individual expression tests lets skip a frame and look at the following frame and examine now we perform the individual expression tests overall result: finally, lets end the test ELSE IO.PutF[reports, "W"]; main code Κ>Ί•NewlineDelimiter ™codešœ™K™HKšœ#™#K™;K™;K™*K™#K™*K™+K™&—K˜šΟk ˜ Kšœœ:˜PKšœœ ˜Kšœ œ˜KšœœI˜VKšœ œo˜~Kšœœ ˜KšœœŒ˜’Kšœœ ˜!Kšœ œ ˜Kšœœ‘˜₯Kšœ œ ˜Kšœ œ>˜NKšœ œ˜'Kšœ œ˜)Kšœœ˜*Kšœ œ˜)Kšœœ>œœ˜YKšœœ)˜>Kšœ œC˜SKšœœ#˜:KšœœΈ˜ΕKšœ œX˜iKšœœ˜#Kš œœ œœ œ˜+Kšœœ,˜5Kšœ œœ ˜Kšœœ6˜CKšœ œ˜"Kšœœ4œ˜DKšœœ˜5Kšœ œΞ˜ήKšœœY˜nK˜—šΟnœœ˜Kšœ œ˜-Kšœ―œQœK˜ΧKšœ˜—Kšœœžœœ˜3K˜™K˜šž œœœ˜K™R——K˜K™™Kšœœ˜&Kšœœ&œœ˜N—˜K™Kšœ œœ˜&š œœœ œœ˜/Kšœœ˜Kšœœ˜"Kšœœ˜Kšœœœ œ˜)KšœœœΟcκ˜όK˜#K˜#Kšœ œ˜K˜'Kšœ&˜&Kšœ%˜%Kšœ˜K˜Kšœœ˜Kšœœ˜Kšœ'˜'K˜!K˜%K˜Kšœ*˜*Kšœœœ˜#Kšœ œœ˜Kšœœ˜Kšœ œ ˜—K˜Kš œ œœœ œœœ ˜Hšœ œœ˜Kšœœ˜&K˜Kšœ˜K˜——™ ˜K™ƒK™G—šžœœœœ œœœœ œœœ˜ Kšœœ*˜=šžœœœœ˜#Kšœ˜Kšœœ˜ —šžœœœ˜,Kšœœ˜!Kšœœ˜"K˜!Kšœ'˜'Kš œ œœ œœ˜(Kš œœœ œœ˜+š œœœ œœ˜0Kšœ ˜#Kšœ&˜)Kšœ˜"Kšœ!˜$KšœΡ™Ρ—šžœœœœ˜/Kšœ(˜(Kšœœ˜ K˜—KšœR™RKšœ œœ0˜FKšœ˜š œ œœœ$œ œ˜XKšœœœœ˜NKšœ#˜#Kšœ˜—K˜Kšœ6™6Kšœ'˜'K˜šœ\˜\šœ˜Kšœq˜qKšœ˜ ——Kš œœœœœ˜Kšœ(™(Kšœ œ ˜K˜K˜*KšœV˜VKšœœ†˜₯K˜K™ΗKšœ˜šœœŸ0˜CKšœœ6˜IKšœ˜Kšœ&˜&Kšœœœœ˜NKšœ˜—Kšœ œ˜ Kšœ%˜%K˜%Kšœ&˜&K˜6Kšœ˜Kšœ˜KšœœœœH˜sKšœ*˜*KšœA˜AKšœD˜DK˜FKšœ^œ˜dK™BK™Bšœœ˜(KšœœŸ;˜EK˜ K˜K˜ K˜K˜ —šœ œ˜ Kšœœ˜ Kšœ1˜1K˜Kšœ˜K™%K™%Kšœ˜Kšœ ˜ KšœL˜LKšœ ˜ Kšœ˜K˜ K˜Kšœœ˜ Kšœœ˜K˜K˜K˜ K˜ Kšœœ˜—K˜KšœT˜TKšœ]˜]Kšœ]˜]Kšœ1˜1Kšœ1˜1K˜KšœV˜VK˜Kšœ-™-K˜Kšœœœœ ˜?K˜šœœœœ ˜ K™]—K™KšœOœ$˜vKšœUœœ%œ˜KšœXœœ%œ˜£KšœUœœ%œ˜KšœUœœ%œ˜KšœTœœ%œ˜‘Kš œWœœœœ1˜ΊKšœaœœ1˜šK˜Kš œ_œœœ2œ!˜ΰKšœXœœ(˜ˆKšœaœœœ#˜«Kšœ_œœœ!˜£Kšœ\œœ,˜Kš œTœœœ œœ˜¨KšœUœœ%˜‚KšœVœœ&˜„K˜KšœWœœœ œœœœ1˜εKš œXœœœ œœ2˜ΘKš œVœœœœ0˜²Kš œXœœœœ:˜ΏKš œWœœœœ/˜²K˜K˜Kš œ^œœœ œœœ ˜ΗKš œ^œœœ œœœ ˜ΔK˜KšœUœœ˜uKšœVœœ˜wK˜Kšœ˜—Kšœ œœ˜±Kšœ˜—K˜š žœœœœ"œœ˜VKš˜Kšœœœ˜Kšœœœœ˜#KšœH˜HKšœK˜KKšœ/˜/šœœ˜ šœœœ"˜7Kšœœ%˜,Kšœ(˜(Kšœ˜——Kšœ˜—K˜š žœœœœ"œœ˜RKšœœœ˜Kšœ*˜*—K˜š žœœœ"œœ˜Ršžœœœœ˜.Kšœ5œœ˜B—Kšœœœ˜Kš œœœœœœ˜7Kšœ*˜*Kšœœ˜Kšœ?˜?Kšœ*˜*K˜1Kšœœœœ˜NKšœ˜—K˜šžœœœœ˜?Kš˜Kšœœœ˜Kšœœœœ˜#Kšœ)˜)Kšœœ˜Kšœ*˜*K˜1Kšœ˜—K˜—™K™šžœœœœ"œœœ œ˜hKš˜Kšœœœ˜Kšœœœœ™(Kšœœ4œœ ˜OKšΟt2˜2Kšœ œ˜&Kšœ ˜Kšœ˜—K˜š žœœ"œœœ œ˜]Kš˜Kšœ œœœ˜/Kšœ œ˜Kšœ<˜Kš˜Kšœœœ˜šœœ˜)Kš˜Kšœœ3œœ ˜NKšœœ˜Kšœ œ˜%Kšœ˜—Kšœ˜—K˜—™ K˜šž œœœœ"œœœ˜iKšœœœ˜šœ˜!Kšœ0˜0Kšœ0˜0Kšœ˜Kšœ˜Kšœ&˜&Kšœ˜Kšœ˜Kšœ˜K˜Kšœ˜K˜Kšœ&˜&Kšž œ%˜/Kšœ˜——K˜šž œœœœ&œ œœœœ˜‡Kšœœœ˜Kšœœ+œ œ˜`Kšœ<˜BKšœ˜—K˜šžœœœœ"œœœ˜sKš˜Kšœœœ˜Kšœ œ;˜JKšœ˜Kšœ˜K˜—K˜™K™š ž œœœœœ˜2Kš˜šœœ˜Kšœ$˜$Kšœ<˜˜>Kšœ4˜4Kšœ6˜6Kšœ*˜*Kšœ$˜$Kšœ&˜&Kšœ ˜—Kšœ˜—K˜š žœœœœœ˜9Kš˜šœœ˜Kšœ(˜(Kšœ*˜*Kšœ&˜&Kšœ,˜,Kšœ,˜,Kšœ.˜.Kšœœœ˜/—šœ˜K˜————K™™&K˜Kšœ=™=š ž œœœNœœœ™΅Kš™šœ œœœ™GKšœ*™*Kšœ ™ Kšœ™Kšœ"™"Kšœ"™"Kšœ ™ Kšœ'™'Kšœ'™'Kšœ%™%Kšœ!™!Kšœ%™%Kšœ'™'—Kšœœ™šœ œH™Yšœ™Kš™Kšœœ™ Kšœœ™ Kšœ.™.Kš™Kšœ™——Kšœ ™K™Kšœ™——K˜šžœœ/œœ˜rKš˜šœœ+œ˜;š˜Kš˜KšœR˜RKšœl˜lK˜BK˜PK˜NK˜cKš˜——Kšœ˜—K˜šœ™K™Kš žœœ œ"œœ˜jKš˜šœœ+œ˜;š˜Kš˜K˜DK˜^K˜BK˜bKšœ0˜6Kšœ˜——Kšœ˜K˜Kšžœœ œœ"œœœ˜nKš˜Kšœœ˜šœ2˜2Kšœ œœ˜0—šœ œœœ ˜(š˜Kš˜šœœœœ/˜DKšœ/™/—Kšœ˜ Kšœ˜——Kšœ˜—K™K™K™™š žœœœ.œ œœ˜iK™aKš˜K˜šœœœœ˜ Kš˜™Kšœ+˜+Kšœ4œ˜N—Kšœœ˜ Kšœ˜—K˜Kšœ œ˜Kšœ-˜-Kšœœœœ%˜:Kšœ˜K˜—š žœœœ.œ œœ˜lK™YKš˜K˜šœœœœ˜ Kš˜™Kšœ.˜.Kšœ8œ˜R—Kšœœ˜ Kšœ˜—K˜Kšœ œ˜Kšœ-˜-Kšœœœœ%˜:Kšœ˜K˜—š žœœœ#œœ˜OK™$Kš˜K˜šœœœœ˜ Kš˜Kšœ˜Kšœ ˜Kšœ˜—K˜Kšœ œ˜Kšœ-˜-Kšœœœœ%˜:Kšœ˜K˜—š žœœœ#œœ˜PK™Kš˜K˜šœœœœ˜ Kš˜Kšœ˜Kšœ ˜Kšœ˜—K˜Kšœ œ˜Kšœ-˜-Kšœœœœ%˜:Kšœ˜K˜——™K™K™ K˜Kšœ œœœ˜=K˜šž œœœœ˜TKš˜Kšœ œœ˜AKšœœ‡˜‘Kšœ˜—K˜Kšž œœ˜Kšž œœ˜K˜K˜šžœœ!œœ˜JKšœ œœ ˜1Kšœ˜$—˜K™/K™3—šžœœ œœœ!œœ˜{Kš˜Kšœ œœ ˜1Kšœ œ6˜FKšœœ œ˜*K™K™#Kšœœœ ˜$K˜™Kš˜Kšœ œ+˜8Kšœœœ1˜WKšœœ˜,K˜šœœŸ˜/Kš˜šœ œ$˜3Kšœ˜K˜ K˜Kšœ˜Kšœ˜—Kšœ  œ  œ*˜TKš˜—šœœŸ–˜œKš˜šœ œ$˜4Kšœ˜K˜ K˜Kšœ˜Kšœ˜—šœ œ$˜4Kšœ˜K˜ K˜Kšœ˜Kšœ˜—šœ œ˜Kšœ œ˜.Kšœ œ0˜A—Kšœ˜—Kšœ˜—K˜Kšœ˜K™—š žœœ œœœ'œ˜zKš˜Kšœ œœ ˜1Kšœ˜Kšœ˜—K˜šžœœ œ%œ˜pKš˜Kšœ œœ ˜1Kšœœ"˜5Kšœ*˜0Kšœ˜—K˜šžœœ œœ˜DKš˜Kšœ œœ ˜1Kšœ˜ Kšœ˜—K˜K˜K˜šžœœ%œ˜9Kš˜Kšž œœ˜šœœœ+˜;Kšœœœ(˜5Kš œ œœœœ˜Kšœ˜š œžœœœ˜Kšœ œ.˜;Kšœœ˜+Kšœ˜—Kšœœ!˜>Kšœ˜—Kšœ˜—K˜šž œœ%œ˜Kšœ˜—Kšœ˜—K˜K˜šžœœ%œ˜9Kš˜Kšž œœ˜šœœœ+˜;Kšœœœ(˜5Kš œ œœœœ˜Kšœ˜š œžœœœ˜Kšœ œ)˜6Kšœœ*˜EKšœ˜—Kšœœ!˜>Kšœ˜—šœ˜K˜——šžœœ%œ˜9Kš˜Kšž œœ˜šœœœ+˜;Kšœœœ(˜5Kš œ œœœœ˜Kšœ˜š œžœœœ˜Kšœ œ)˜6Kšœœœœ ˜6Kšœ˜—Kšœœ!˜>Kšœ˜—Kšœ˜—˜KšœJ™JK™X—šžœœ%œ ˜>Kš˜Kšœ>˜>Kšœœ1˜GKšœ œœ˜šž œœœ˜K˜*—Kšœ>˜>K˜*Kšœ˜—K˜K˜Kš œœœ œœ˜.K˜K˜K˜˜Kšœ„™„—˜Kšœ<™<—š žœœ$œ œœœ˜_Kš˜K˜Kšœœ,˜5š ž œœœœœ˜/Kšœ œœ˜K˜—Kšœœœ0˜cšœ˜šœŸ˜ Kš˜K˜K˜Kšœœ2˜>Kšœœ,˜5Kš œœœœœœ˜CK˜š œžœœœ˜Kšœœ"˜,Kšœœœ ˜Kšœ˜—Kšœ˜—šœŸ˜ Kš˜K˜K˜K˜Kšœœ.˜8Kšœœ0˜;Kšœœ0˜;Kš œœœœœœ˜?šœ˜ šœ˜šœŸ ˜Kš˜Kšœ˜Kšœ˜KšœC˜CKšœœ0˜;Kšœ6˜6K˜%Kšœ˜—šœŸ ˜Kš˜Kšœ˜Kšœ˜Kšœ˜KšœC˜CKšœC˜CKšœœ,˜5Kšœ6˜6šœ ˜Kš˜Kšœœ˜5Kšœœ,˜AKš˜—šœ˜K˜)—Kšœ˜—šœ˜Kš˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜KšœC˜CKšœI˜IKšœœ1˜Kšœœ,™HKšœœœŸ'™BK™Kšœœ-œœ™{K™™+šœœ™(Kšœœ œ™—K™šœœ™Kšœ1œ™9—Kšœ™—K™Kšœe™eKšœ™—Kšœ™—K˜K˜—™ K˜K˜š’œœ#œœœœœ œ™ŒKš™Kšœœœ™šœœœœ™ Kš™Kšœœ;™BK™Kšœœœ;™_™Kš™KšœœY™nKšœ4™4Kšœœ™Kšœœ™7Kšœœ1™9Kšœq™q™+KšœJ™J—™6KšœO™Ošœœœ™Kš™Kšœ™Kš™—šœ™Kš™Kšœœ"œ™OKšœ ™Kšœ™——K™Kšœ!™!Kšœ4™4K™Kšœ™Kšœ™—Kšœ™—Kšœ+™+Kšœ™Kšœ™—K˜š’œœ=œœ™{Kš™Kšœœ™7Kšœœ1™9Kšœœ'™GKšœœ(™?Kšœ4™4Kšœ œ™Kšœ œ™Kšœœœœ™0KšœM™Mšœœ™KšœœP™XKšœœ%™3—šœ1œ™8Kšœ™—šœ™Kš™K™š™Kšœ=™=šœœ™KšœœS™[Kšœœ'™5—Kšœœ(œœ™8K™Kšœ™—Kšœ™—Kšœ™Kšœ™——K™™ K˜Kšœœ˜0K˜™K™K™K™9K™;K™K™B—K˜šžœ˜(Kš˜Kšœ:˜:Kšœœ ˜ Kš œ œœœœœ ˜]Kš œ œœœœ˜Kšœ=œ0˜qKšœœœ˜$K˜šžœœ˜Kš˜Kšœœ˜9Kšœœ˜Kšœ%˜%Kšœ˜Kšœ˜K˜—™2K™\Kš˜Kšœœ˜K˜šž œœ˜Kš˜Kšœ œ(˜6šœœ˜Kš˜KšœœœœE˜eK˜š œœœœœœ˜DKšœœ ˜K˜K˜Kšœ+˜+K˜6K˜+K˜Kšœ(œ*˜V˜K˜—šœ?˜EKš˜Kšœœ˜K˜K™™Kš˜Kšœœ/˜CKšœœ˜3Kšœ˜—K™™.Kš˜šœ œœœ˜+KšœΊ˜Ί—K˜\Kšœ˜—K˜™K˜-—K˜™ Kš˜Kšœœ/˜CKšœœ˜3Kšœ˜—K˜™.Kš˜šœ œœœ˜+KšœΩ˜Ω—K˜\Kšœ˜—K˜™1K˜-—K˜™ Kš˜Kšœœ/˜CKšœœ˜3Kšœ˜—K˜™.Kš˜šœ œœœ˜+Kšœι˜ι—K˜\Kšœ˜—K˜™Kšœœœ:˜[Kšœœœ;œ˜a—K˜™Kšœ˜—Kšœ˜—Kšœ˜—Kšœ˜—Kšœ˜K˜—Kšœ Ÿ>˜KKšœ˜—Kšœ ˜ Kšœ˜—K˜šœœœ˜Kšœœ˜Kšœœ˜Kšœœ˜K˜—K˜Kšœ œœ˜2K˜šžœœ"œœœœœŸœœ˜‰Kš˜šœœœ˜ Kšœœ˜Kšœœ˜Kšœœ˜—Kšœœœœ˜'Kšœ œœœ˜*Kšœœœœ˜#Kšœ œœœ˜&Kšœœ˜˜HK˜—š œœœ&œ œ˜LKšœ œH˜YKšœœœœX˜zKš œœœ#œœ)˜„Kšœœœ œ˜6K˜Kšœ4œœ˜hšœ+œœ`˜˜Kš˜Kšœœœœ?˜eKšœ9œ#˜`Kšœ œœœ˜@K˜K˜,Kšœ˜—Kšœ˜—K˜KšœP˜Rš œœœ#œ œ˜IKšœ$œœ#˜lšœ#œ˜IKšœœ&˜A—šœ˜$šœœœ˜AK˜'Kšœ ˜Kšœœ˜——Kšœ˜Kšœ˜—K˜šœ œ˜Kš˜Kšœ6˜8š œœœ'œ œ˜MKšœ%œ˜HKšœ*œ#˜QKšœ(œ!˜MKšœ˜—Kš˜—Kšœœœ;˜CKšœ˜Kšœ˜—K˜š žœœœ#œœ˜SKš˜Kšœ=˜?Kšœœ˜"Kšœœ<˜TKšœ"˜"Kšœ$˜&Kšœ˜—K˜š žœœœ#œœ˜QKš˜Kšœ œ˜&Kšœ0˜2Kšœœ˜!Kšœ˜Kšœ˜K˜—šžœœ#œœ˜FKšœ˜Kšœœ ˜"Kšœ˜Kšœ0˜0š˜Kšœœœœ ˜8šœ!œ˜.Kšœ˜Kšœœœœ ˜8Kšœ˜—šœ@˜Bšœ˜šœ˜Kšœ>˜>Kšœ˜—šœ˜Kšœœœœ ˜Kšœœ˜K˜5šœœ˜šœ ˜K˜%—Kšœ7˜7K˜ Kšœ˜—Kšœœ˜&——Kšœ6œ œ˜N—šœ™Kšœ™—Kšœ˜Kšœ˜—š˜Kš œœ-œ œœ˜[šœ˜Kšœjœœ˜{—Kšœœ˜—K˜Kšœ˜——K˜K˜Kšœ ™ ˜Kšœ7˜7K˜—Kšœ˜—…—ΘΠ,π