LocalCirioImpl.mesa
Copyright Ó 1990, 1991, 1992 by Xerox Corporation. All rights reserved.
Sturgis, April 20, 1990 3:25 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:14 pm PDT
Linda Howe January 3, 1990 4:09:35 pm PST
Coolidge, July 18, 1990 10:21 am PDT
Laurie Horton, March 31, 1992 12:48 pm PST
Philip James, February 24, 1992 11:42 am PST
Udagawa, February 12, 1991 9:03 pm PST
Willie-s, July 27, 1992 5:48 pm PDT
DIRECTORY
AmpersandContext USING[CreateAnAmpersandContext, MakeNodeFromNode, StripAMNode],
BasicTime USING[Now],
CCTypes USING[CC, CCError, CCErrorCase, CreateCedarCompilerContext, LocalCedarTargetWorld, LocalCedarTargetWorldBody, RegisterLocalCedarTargetWorld],
CedarCode USING[GetNodeRepresentation, GetTypeOfNode, LoadThroughIndirectNode, SelectFieldFromNode, StoreThroughIndirectNode],
CirioBackstop USING[Protect],
CirioBreakAccess USING[CirioBreakSet, CreateCirioBreakSet, ClearAllBreaks, ClearBreakAtAbsAddr, ClearBreakAtIndex, ListBreaks, QuaBreakSet, SetBreakAtAbsAddr],
CirioDeltaFace USING[CallerInfo, GetCallersSPandPC],
CirioNubAccess USING[CreateSameWorldNub, DestroyNub, FileEntry, GetFileEntry, Handle, LookupSymEntryByName, LookupSymEntryByValue, LookupSymEntryByID, PCInfo, PCtoInfo, Read32BitsAsCard, SymEntry],
CirioTargets USING[Target],
CirioTypes USING[CC, CompilerContext, Node, Type],
Commander USING[CommandProc, Register],
IO USING[PutF1, PutFR1, rope, STREAM],
LoadStateAccess USING[CreateLoadStateHandle, GetLoadedModuleInfoFromAbsPC, LoadedModuleInfo, LoadStateHandle],
LocalCirio USING[BreakDest, nilBreakDest],
LocalCirioWorld USING[],
NewAmpersandProcs USING[Handle, HandleBody, InstallItems],
NewRMTW USING[CedarModuleSet, CreateCedarModuleSet, CreateRemoteMimosaTargetWorld, FlushUnknownFileCache, FlushUnknownSymbolCache, FlushUnknownTypeCodes, FrameNodeInfo, GetLoadedModuleInfo, GetNodeForCedarFrame, LoadedModuleInfo, RawFrameInfo, RemoteMimosaTargetWorld, ResetSearchPaths, ShowReportByLevel],
ObjectFiles USING[CreateParsed, GetLineNumForPC, GetPCForLineNum, Module, ModuleFromParsedAndPC, Parsed],
OneCasabaParser USING[ParserTable],
PFS USING [RopeFromPath, PathFromRope],
PFSNames USING [PATH, Equal],
RefTab,
Rope USING[Cat, Equal, Substr, ROPE],
RopeHash USING[FromRope],
SourceFileOps USING [OpenSource, Position],
StackCirio USING[OpenDummyStack, OpenStack, ResetStack, Stack],
SystemInterface USING [ShowReport, FileSet, CirioFile, CloseFileSet, CreateFileSet, GetCirioFile];
LocalCirioImpl: CEDAR MONITOR
LOCKS connection USING connection: Connection
IMPORTS AmpersandContext, BasicTime, CCTypes, CedarCode, CirioBackstop, CirioBreakAccess, CirioDeltaFace, CirioNubAccess, Commander, IO, LoadStateAccess, NewAmpersandProcs, NewRMTW, ObjectFiles, PFS, PFSNames, RefTab, Rope, RopeHash, SourceFileOps, StackCirio, SystemInterface
EXPORTS LocalCirio, LocalCirioWorld =
BEGIN OPEN ObjF: ObjectFiles, LSA: LoadStateAccess;
Debugging aids
DebugFlag: BOOLEAN ¬ FALSE;
This variable can be set/reset by the ampersand routines &&DebugOn and &&DebugOff.
Types
ROPE: TYPE = Rope.ROPE;
CC: TYPE = CirioTypes.CompilerContext;
CCE: ERROR[case: CCTypes.CCErrorCase, msg: ROPE ¬ NIL] ¬ CCTypes.CCError;
BreakDest: TYPE = LocalCirio.BreakDest;
nilBreakDest: BreakDest = LocalCirio.nilBreakDest;
ConnectionList: TYPE ~ LIST OF Connection;
Connection: TYPE = REF ConnectionBody;
ConnectionBody: PUBLIC TYPE = MONITORED RECORD[
open: BOOLEAN,
forRemote: BOOLEAN, -- true if created to provide local ampersand vars for a remoteCirio
searchDirectories: REF LIST OF PFSNames.PATH,
searchDirectoryLock: Connection,
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.
aph: NewAmpersandProcs.Handle,
ampersandContext1: CirioTypes.Node,
ampersandContext2: CirioTypes.Node,
cc: CC,
breakDest: BreakDest,
rmtw: NewRMTW.RemoteMimosaTargetWorld,
cedarModules: NewRMTW.CedarModuleSet,
nub: CirioNubAccess.Handle,
target: CirioTargets.Target,
breaks: CirioBreakAccess.CirioBreakSet,
fileSet: SystemInterface.FileSet,
lsh: LoadStateAccess.LoadStateHandle,
cParserTable: OneCasabaParser.ParserTable,
dbxActive: BOOLEAN ¬ FALSE];
Connections
thisWorldLock: Connection ¬ NEW[ConnectionBody];
serves as a monitor lock for the following
commonFileSet: SystemInterface.FileSet ¬ NIL;
commonCedarModules: NewRMTW.CedarModuleSet ¬ NIL;
commonNub: CirioNubAccess.Handle ¬ NIL;
commonTarget: CirioTargets.Target ¬ NIL;
commonBreaks: RefTab.Ref--BreakDest -> CirioBreakAccess.CirioBreakSet-- ¬ RefTab.Create[equal: BDEqual, hash: BDHash];
commonlsh: LoadStateAccess.LoadStateHandle ¬ NIL;
commonSearchDirectories: REF LIST OF PFSNames.PATH ¬ NIL;
commonSearchDirectoryLock: Connection ¬ NIL;
availConnections: RefTab.Ref--BreakDest -> ConnectionList-- ¬ RefTab.Create[equal: BDEqual, hash: BDHash];
Note: we delay creating any worlds until all modules have been started, because the nominal creation code will be calling procedures in those modules.
There are more than one world so that we can have multiple independent cirios active at one time, e.g. if an error is raised during an interpreted procedure call, while at the same time avoiding monitor deadlocks.
However, they will all share common CedarModuleSet, CirioNubAccess.Handle, CirioBreakAccess.CirioBreakSet (per break dest), SystemInterface.FileSet, and LoadStateAccess.LoadStateHandle. I assume these modules will suitably protect themselves, and that none of them will be holding a monitor lock during an interpreted procedure call.
RecreateThisWorldCirioConnection: Commander.CommandProc =
BEGIN
inner: ENTRY PROC[connection: Connection] = {InstallNewConnectionComponents[cmd.out]};
inner[thisWorldLock];
END;
"thisWorldLock" must be held during a call to this procedure
InstallNewConnectionComponents: PROC[reports: IO.STREAM] =
BEGIN
ENABLE UNWIND => {
commonFileSet ¬ NIL;
commonCedarModules ¬ NIL;
commonCedarModules ¬ NIL;
commonBreaks ¬ RefTab.Create[equal: BDEqual, hash: BDHash];
commonlsh ¬ NIL;
commonSearchDirectories ¬ NIL;
commonSearchDirectoryLock ¬ NIL};
IF commonNub # NIL THEN CirioNubAccess.DestroyNub[commonNub];
IF commonFileSet # NIL THEN SystemInterface.CloseFileSet[commonFileSet];
commonFileSet ¬ SystemInterface.CreateFileSet[];
commonCedarModules ¬ NewRMTW.CreateCedarModuleSet[commonFileSet];
commonNub ¬ CirioNubAccess.CreateSameWorldNub[];
commonTarget ← CirioTargets.CreateTarget[commonNub];
commonTarget ¬ NARROW[commonNub.target];
commonBreaks.Erase[];
commonlsh ¬ LoadStateAccess.CreateLoadStateHandle["sameWorld", commonNub, commonFileSet];
commonSearchDirectories ¬ NEW[LIST OF PFSNames.PATH ¬ NIL];
commonSearchDirectoryLock ¬ NEW[ConnectionBody];
availConnections.Erase[];
END;
connection param must be "thisWorldLock"
TryForExistingConnection: ENTRY PROC[connection: Connection, breakDest: BreakDest] RETURNS[Connection] =
BEGIN
rbd: REF BreakDest ~ NEW [BreakDest ¬ breakDest];
acl: ConnectionList ~ NARROW[availConnections.Fetch[rbd].val];
IF acl#NIL THEN {
first: Connection ~ acl.first;
IF first.open THEN RETURN WITH ERROR CCE[cirioError, "Locking failure for a local connection"];
first.open ¬ TRUE;
[] ¬ availConnections.Store[rbd, acl.rest];
RETURN [first]}
ELSE RETURN[NIL];
END;
BuildCommon: PROC[cc: CC, breakDest: BreakDest, reports: IO.STREAM, setCTC: BOOL, wdirs: LIST OF ROPE] RETURNS[Connection] =
BEGIN
connection param must be "thisWorldLock"
designed not to do anything dangerous while the lock is held
simply collects common stuff into some records
makeProtoConnection: ENTRY PROC[connection: Connection] RETURNS[Connection] =
BEGIN
rbd: REF BreakDest ~ NEW [BreakDest ¬ breakDest];
bs: CirioBreakAccess.CirioBreakSet;
IF commonFileSet = NIL THEN InstallNewConnectionComponents[reports];
IF (bs ¬ CirioBreakAccess.QuaBreakSet[commonBreaks.Fetch[rbd].val].it) = NIL THEN {
bs ¬ CirioBreakAccess.CreateCirioBreakSet[commonNub, breakDest.fileNameStem, breakDest.breakProcName];
[] ¬ commonBreaks.Store[rbd, bs]};
BEGIN
aph: NewAmpersandProcs.Handle ¬ NEW[NewAmpersandProcs.HandleBody¬[
out: NIL, -- only valid during a text line interpretation in StackCirio
rmtw: NIL,
cedarModules: commonCedarModules,
nub: commonNub,
target: commonTarget,
fileSet: commonFileSet,
lsh: commonlsh]];
pc: Connection ¬ NEW[ConnectionBody¬[
open: TRUE,
forRemote: FALSE,
searchDirectories: commonSearchDirectories,
searchDirectoryLock: commonSearchDirectoryLock,
aph: aph,
ampersandContext1: NIL,
ampersandContext2: NIL,
cc: cc,
breakDest: breakDest,
rmtw: NIL,
cedarModules: commonCedarModules,
nub: commonNub,
target: commonTarget,
breaks: bs,
fileSet: commonFileSet,
lsh: commonlsh,
cParserTable: NIL]];
RETURN[pc]
END;
END;
pc: Connection ¬ makeProtoConnection[thisWorldLock];
lctw: CCTypes.LocalCedarTargetWorld ¬ NEW[CCTypes.LocalCedarTargetWorldBody¬[
createNodeFromRefAny: NIL,
createFrameNodeForSelf: LCTWCreateFrameNodeForSelf,
data: pc]];
Add the directories in REVERSE ORDER because AddDir adds to the front of the list!!
AddDir[pc, "[PCedar2.0]<Cirio>", reports];
AddDir[pc, "[PCedar2.0]<CirioThings>", reports];
AddDir[pc, "[PCedar2.0]<Atom>", reports];
AddDir[pc, "[PCedar2.0]<Rope>", reports];
AddDir[pc, "-compiled:/CirioCompiledData", reports];
We include these directories so that examination of "navel" will procede correctly for a released Cirio. This is done before CreateRemoteMimosaTargetWorld so that the studying of CirioRopeHelper done therein will succeed on first try. The following files are needed (on August 17, 1991):
CirioThings/CirioRopeHelper.mob
Cirio/CCTypesImpl.mob
Cirio/CirioTypes.mob
Cirio/NewAmpersandProcs.mob
Cirio/NewAmpersandProcsImpl.mob
Rope/Rope.mob
Atom/AtomPrivate.mob
EnsureDirs[pc, wdirs, reports];
pc.ampersandContext1 ¬ AmpersandContext.CreateAnAmpersandContext[cc];
pc.ampersandContext2 ¬ AmpersandContext.CreateAnAmpersandContext[cc];
pc.rmtw ¬ NewRMTW.CreateRemoteMimosaTargetWorld["sameWorld", pc.nub, cc, pc.cedarModules, pc.lsh, reports, setCTC];
pc.aph.rmtw ¬ pc.rmtw;
CCTypes.RegisterLocalCedarTargetWorld[lctw, pc.cc];
all local connections register themselves with their cc
BUT, outside the monitor lock
RETURN[pc];
END;
GetConnection: PUBLIC PROC[breakDest: BreakDest, reports: IO.STREAM, workingDirectories: LIST OF ROPE] RETURNS[Connection] = {
ENABLE SystemInterface.ShowReport =>
{NewRMTW.ShowReportByLevel[reports, msgText, priority];
IO.PutF[reports, "%g\N", IO.rope[msgText]];
RESUME};
note: connection argument will be thisWorldLock
ans: Connection ¬ TryForExistingConnection[thisWorldLock, breakDest];
IF ans # NIL THEN EnsureDirs[ans, workingDirectories, reports]
ELSE {
cc: CC ¬ CCTypes.CreateCedarCompilerContext[];
ans ¬ BuildCommon[cc, breakDest, reports, TRUE, workingDirectories];
NewAmpersandProcs.InstallItems[ans.ampersandContext2, ans.aph, ans.cc];
};
RETURN [ans]};
EnsureDirs: PROC [c: Connection, wdirs: LIST OF ROPE, reports: IO.STREAM] ~ {
IF wdirs#NIL THEN {
EnsureDirs[c, wdirs.rest, reports];
AddDir[c, wdirs.first, reports, FALSE]};
RETURN};
ExtractCcFromConnection: PUBLIC PROC [c: Connection] RETURNS [CirioTypes.CC]
~ {RETURN [c.cc]};
this procedure is exported to LocalCirioWorld, and is called by RemoteCirioImpl to permit construction of ampersand routines.
parallels GetConnection, except that registration is with supplied cc, we always create a connection, we let the caller install the ampersand procs, and breakpoints cannot be set through this connection.
CreateAndRegisterNominalLocalCirioTW: PUBLIC PROC[cc: CCTypes.CC, reports: IO.STREAM] =
BEGIN
ENABLE SystemInterface.ShowReport =>
{NewRMTW.ShowReportByLevel[reports, msgText, priority];
IO.PutF[reports, "%g\N", IO.rope[msgText]];
RESUME};
connection: Connection ¬ BuildCommon[cc, nilBreakDest, reports, FALSE, NIL];
connection.forRemote ¬ TRUE;
END;
in this case, "self" is the caller of this procedure
This procedure duplicates assorted activity in StackCirioImpl
LCTWCreateFrameNodeForSelf: PROC[lctw: CCTypes.LocalCedarTargetWorld, cc: CCTypes.CC] RETURNS[CirioTypes.Node] =
BEGIN
connection: Connection ¬ NARROW[lctw.data];
ourInfo: CirioDeltaFace.CallerInfo ¬ CirioDeltaFace.GetCallersSPandPC[connection.nub];
note: In CirioDeltaFace.GetCallersSPandPC, "caller" refers to the caller of CirioDeltaFace.GetCallersSPandPC, i.e., ourselves. In LCTWCreateFrameNodeForSelf, "self" refers to the caller of LCTWCreateFrameNodeForSelf, i.e., our caller.
note: in the following var names, "caller" refers to the same frame as "Self" in our procedure name, that is, our caller.
ourSP: CARD ¬ ourInfo.callersStackPointer;
the nomenclature is such that ourInfo.callersStackPointer is really our stack pointer.
callerPC: CARD ¬ CirioNubAccess.Read32BitsAsCard[[connection.nub, ourSP+(15*4), 0, FALSE, TRUE]];
callerLedo: REF LSA.LoadedModuleInfo ¬ LSA.GetLoadedModuleInfoFromAbsPC[connection.lsh, callerPC];
callerLoadedCedarModule: REF NewRMTW.LoadedModuleInfo ¬ NewRMTW.GetLoadedModuleInfo[connection.cedarModules, callerLedo];
ourFP: CARD ¬ CirioNubAccess.Read32BitsAsCard[[connection.nub, ourSP+(14*4), 0, FALSE, TRUE]];
This constant (14*4) exists in several places. They should be combined.
callerSP: CARD ¬ ourFP;
callerFP: CARD ¬ CirioNubAccess.Read32BitsAsCard[[connection.nub, callerSP+(14*4), 0, FALSE, TRUE]];
This constant (14*4) exists in several places. They should be combined.
callerRawFrameInfo: REF NewRMTW.RawFrameInfo ¬ NEW[NewRMTW.RawFrameInfo ¬ [
callerPC,
callerFP,
callerSP]];
callerInfo: REF NewRMTW.FrameNodeInfo;
IF callerLoadedCedarModule=NIL THEN CCE[cirioError, "Cirio can't NewRMTW.GetLoadedModuleInfo for itself"];
callerInfo ¬ NewRMTW.GetNodeForCedarFrame[connection.rmtw, callerLoadedCedarModule, callerRawFrameInfo];
RETURN[callerInfo.node];
END;
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];
END;
ReleaseConnection: PUBLIC ENTRY PROC[connection: Connection, reports: IO.STREAM] =
BEGIN ENABLE UNWIND => NULL;
renamed: Connection ¬ connection;
to be visible inside putBack
putBack has to reuse the identifier: connection so as to be able to lock
PutBack: PROC[connection: Connection] = {
ENABLE UNWIND => NULL;
rbd: REF BreakDest ~ NEW [BreakDest ¬ renamed.breakDest];
acl: ConnectionList ¬ NARROW[availConnections.Fetch[rbd].val];
acl ¬ CONS[renamed, acl];
[] ¬ availConnections.Store[rbd, acl];
RETURN};
IF NOT connection.open THEN RETURN WITH ERROR CCE[cirioError, "some fool released a local connection that wasn't open"];
connection.open ¬ FALSE;
IF NOT connection.forRemote THEN PutBack[thisWorldLock];
RETURN; END;
DoUnderMonitorLock: PUBLIC ENTRY PROC[connection: Connection, toDo: PROC] =
BEGIN
ENABLE UNWIND => NULL;
toDo[];
END;
Stack examination
GetStackForSelf: PUBLIC ENTRY PROC[connection: Connection, reports: IO.STREAM]RETURNS[StackCirio.Stack] =
BEGIN
callerInfo: CirioDeltaFace.CallerInfo¬ CirioDeltaFace.GetCallersSPandPC[connection.nub];
stack: StackCirio.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: callerInfo.callersPC,
hotFrameSP: callerInfo.callersStackPointer,
skipKFrames: 1,
ShowSource: SourceFileOps.OpenSource,
reports: reports];
frameIndex: CARD ¬ StackCirio.ResetStack[stack, reports];
RETURN[stack]
END;
GetDummyStack: PUBLIC ENTRY PROC[connection: Connection, reports: IO.STREAM]RETURNS[StackCirio.Stack] =
BEGIN
stack: StackCirio.Stack ¬ 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: SourceFileOps.OpenSource,
reports: reports];
RETURN[stack]
END;
InstallOneAmpersandItem: PROC[ampersandContext: CirioTypes.Node, name: 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, 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, defaultVal: INT, nameScope: CirioTypes.Node, cc: CC] RETURNS[INT] =
BEGIN
valNode: CirioTypes.Node ¬ NIL;
valNode ¬ ReadOneAmpersandItem[name, nameScope, cc
! CCE => {valNode ¬ NIL; CONTINUE}];
IF valNode = NIL THEN RETURN[defaultVal]
ELSE
BEGIN
val: REF INT ¬ NARROW[CedarCode.GetNodeRepresentation[valNode, cc]];
need to install a catch phrase for NARROW fault
RETURN[val­];
END;
END;
source and break positions
AddSearchDirectory: PUBLIC PROC [connection: Connection, dirName: ROPE, reports: IO.STREAM] =
BEGIN
inner: PROC RETURNS[ROPE] =
BEGIN
Set the search directory.
AddDir[connection, dirName, reports];
IO.PutF1[reports, " %g added to search directories\n", IO.rope[dirName]];
RETURN [NIL];
END;
eMsg: ROPE;
eMsg ¬ CirioBackstop.Protect[inner, reports];
IF eMsg # NIL THEN IO.PutF1[reports, "%g\N", [rope[eMsg]]];
END;
RemoveSearchDirectory: PUBLIC PROC [connection: Connection, dirName: ROPE, reports: IO.STREAM] =
BEGIN
inner: PROC RETURNS[ROPE] =
BEGIN
Remove the search directory.
RemoveDir[connection, dirName, reports];
IO.PutF1[reports, " %g removed from search directories\n", IO.rope[dirName]];
RETURN [NIL];
END;
eMsg: ROPE;
eMsg ¬ CirioBackstop.Protect[inner, reports];
IF eMsg # NIL THEN IO.PutF1[reports, "%g\N", [rope[eMsg]]];
END;
ListSearchDirectory: PUBLIC PROC [connection: Connection, reports: IO.STREAM] =
BEGIN
inner: PROC RETURNS [ROPE] =
BEGIN
List the set of search directories
ListDir[connection];
RETURN [NIL]
END;
eMsg: ROPE;
eMsg ¬ CirioBackstop.Protect[inner, reports];
IF eMsg # NIL THEN IO.PutF1[reports, "%g\N", [rope[eMsg]]];
END;
ClearSearchDirectory: PUBLIC PROC [connection: Connection, reports: IO.STREAM] =
BEGIN
inner: PROC RETURNS [ROPE] =
BEGIN
Clear the set of search directories
ClearDir[connection];
RETURN [NIL]
END;
eMsg: ROPE;
eMsg ¬ CirioBackstop.Protect[inner, reports];
IF eMsg # NIL THEN IO.PutF1[reports, "%g\N", [rope[eMsg]]];
END;
breakpoints (tentative, using ampersand procedures)
SetBreakAtAbsAddr: PROC[h: Connection, absAddr: CARD32, mesaPos: SourceFileOps.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, reports: IO.STREAM, toFront: BOOL ¬ TRUE] = {
inner: ENTRY PROC[connection: Connection] = {
ENABLE UNWIND => NULL;
properDirName: ROPE ← CirioDeltaFace.ConvertToLocalDirectoryFormat[dirName];
dirPath: PFSNames.PATH ¬ PFS.PathFromRope[dirName];
prev: LIST OF PFSNames.PATH ¬ NIL;
first, we remove any existing entry for the path
WHILE TRUE DO
current: LIST OF PFSNames.PATH ¬ IF prev # NIL THEN prev.rest ELSE h.searchDirectories­;
IF current = NIL THEN EXIT;
SELECT TRUE FROM
NOT dirPath.Equal[current.first] => NULL;
toFront => {
IF prev = NIL THEN h.searchDirectories­ ¬ current.rest ELSE prev.rest ¬ current.rest;
EXIT;
};
ENDCASE => RETURN--already present--;
prev ¬ current;
ENDLOOP;
now we install the path at the front of the list
h.searchDirectories­ ¬ CONS[dirPath, h.searchDirectories­];
now we inform those who need to know
NewRMTW.ResetSearchPaths[h.cedarModules, h.searchDirectories­, BasicTime.Now[]];
IF h.rmtw#NIL THEN NewRMTW.FlushUnknownSymbolCache[h.rmtw, BasicTime.Now[], reports];
};
inner[h.searchDirectoryLock];
};
RemoveDir: PROC [h: Connection, dirName: ROPE, reports: IO.STREAM] =
BEGIN
inner: ENTRY PROC[connection: Connection] =
BEGIN
ENABLE UNWIND => NULL;
dirPath: PFSNames.PATH ¬ PFS.PathFromRope[dirName];
prev: LIST OF PFSNames.PATH ¬ NIL;
first, we remove any existing entry for the path
WHILE TRUE DO
current: LIST OF PFSNames.PATH ¬ IF prev # NIL THEN prev.rest ELSE h.searchDirectories­;
IF current = NIL THEN EXIT;
IF dirPath.Equal[current.first] THEN
BEGIN
IF prev = NIL THEN h.searchDirectories­ ¬ current.rest ELSE prev.rest ¬ current.rest;
EXIT;
END;
prev ¬ current;
ENDLOOP;
now we inform those who need to know
NewRMTW.ResetSearchPaths[h.cedarModules, h.searchDirectories­, BasicTime.Now[]];
NewRMTW.FlushUnknownSymbolCache[h.rmtw, BasicTime.Now[], reports];
END;
inner[h.searchDirectoryLock];
END;
ListDir: PROC [h: Connection] =
BEGIN
inner: ENTRY PROC[connection: Connection] =
BEGIN
ENABLE UNWIND => NULL;
searchDirectories: 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.PutFR1["%g", IO.rope[searchDirectories]], $urgent];
END;
inner[h.searchDirectoryLock];
END;
ClearDir: PROC [h: Connection] =
BEGIN
inner: ENTRY PROC[connection: Connection] =
BEGIN
ENABLE UNWIND => NULL;
SystemInterface.ShowReport["Clearing search directory list", $urgent];
SystemInterface.ShowReport["Was: ", $urgent];
ListDir[h];
h.searchDirectories­ ¬ NIL;
now we inform those who need to know
NewRMTW.ResetSearchPaths[h.cedarModules, h.searchDirectories­, BasicTime.Now[]];
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.
END;
inner[h.searchDirectoryLock];
END;
symbols
these procedures are expected to become ampersand procedures. During the interpreted call on them the connection will be locked, so there is no need to lock it here. In fact, that would cause a monitor deadlock.
LookupSym: PROC[h: Connection, name: 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]]};
misc
DebugOn: PROC =
BEGIN
DebugFlag ¬ TRUE;
END;
DebugOff: PROC =
BEGIN
DebugFlag ¬ FALSE;
END;
GetRelPCForCLine: PROC[dotOName: PFSNames.PATH, cLineNum: CARD, h: Connection] RETURNS[CARD] =
BEGIN
file: SystemInterface.CirioFile ¬ SystemInterface.GetCirioFile[h.fileSet, dotOName];
container: ObjF.Parsed ¬ ObjF.CreateParsed[file];
AcquireModule: PROC RETURNS[ObjF.Module] =
BEGIN
stabRange ← ObjF.AlternativeFindModuleStabRange[container, 1];
RETURN[ObjF.ModuleFromParsedAndPC[container, [[0, ""], 1]]];
END;
dotO: ObjF.Module ¬ AcquireModule[];
relPC: CARD ¬ ObjF.GetPCForLineNum[dotO, cLineNum].relPC;
RETURN[relPC];
END;
another Kludge
GetCLineForRelPC: PROC[dotOName: PFSNames.PATH, relPC: CARD, h: Connection] RETURNS[CARD] =
BEGIN
file: SystemInterface.CirioFile ¬ SystemInterface.GetCirioFile[h.fileSet, dotOName];
container: ObjF.Parsed ¬ ObjF.CreateParsed[file];
AcquireModule: PROC RETURNS[ObjF.Module] =
BEGIN
stabRange ← ObjF.AlternativeFindModuleStabRange[container, 1];
RETURN[ObjF.ModuleFromParsedAndPC[container, [[0, ""], 1]]];
END;
dotO: ObjF.Module ¬ AcquireModule[];
cLine: CARD ¬ ObjF.GetLineNumForPC[dotO, [[0, ""], relPC]];
RETURN[cLine];
END;
BDEqual: PROC [key1, key2: REF ANY] RETURNS [BOOL] ~ {
bd1: REF BreakDest ~ NARROW[key1];
bd2: REF BreakDest ~ NARROW[key2];
RETURN [bd1.fileNameStem.Equal[bd2.fileNameStem] AND bd1.breakProcName.Equal[bd2.breakProcName]]};
BDHash: PROC [key: REF ANY] RETURNS [CARDINAL] ~ {
bd: REF BreakDest ~ NARROW[key];
RETURN [RopeHash.FromRope[bd.fileNameStem] + RopeHash.FromRope[bd.breakProcName]]};
main code
Commander.Register["RecreateThisWorldCirioConnection", RecreateThisWorldCirioConnection];
END..