DIRECTORY Basics USING[Comparison], BasicTime USING[earliestGMT, GMT, Now, Period], CirioNubAccess USING[CreateRemoteNub, DestroyNub, Handle], Commander USING[CommandProc, Register], CommanderOps USING[NextArgument, NumArgs], CommandTool USING[ArgumentVector, Parse], Convert USING[CardFromRope, Error], ObjectFiles USING[BracketNest, BracketPair, CreateParsed, FileSegmentPC, FindVersionStamp, GetBracketNestForPC, GetLineNumForPC, GetModuleInfo, GetObjectFile, GetPCForLineNum, GetPCRange, Module, ModuleFromParsedAndPC, ModuleInfo, Parsed, PCRange, VersionStampInfo], IO USING[card, EndOf, GetLine, PutF, PutFLR, PutFR, rope, STREAM], List USING[Sort], LoadStateAccess USING[BasicPCInfo, CreateLoadStateHandle, GetBasicPCInfo, GetLoadedModuleInfoFromAbsPC, GetLoadedModuleInfoFromStemName, GetRopeForBasicPCInfo, GetRopeListForBasicPCInfo, GetRopeListForLoadedModuleInfo, LoadedModuleInfo, LoadStateHandle], MobAccess USING[ComputeSourceVersionStamp, CreateMobCookie, MobCookie, MobError, ReadMobVersionStamp, ReadSourceVersionStamp], MobDefs USING[NullVersion, VersionStamp], MobObjectFiles USING[CreateJointMobParsedInfo, JointMobParsedInfo], MorePfsNames, NewRMTW USING[CedarBreakAddress, CedarSourcePosition, LoadedModuleInfo], PFS, PFSNames, RMTWBackdoor, RMTWPrivate USING [NameParts], PBasics USING[BITXOR, LongNumber], RefTab USING[Create, Fetch, Key, Ref, Store], Rope, RopeParts, RuntimeError USING[BoundsFault], SourceFileOpsExtras, SystemInterface USING[CirioFile, CirioFileInfo, CloseFileSet, CreateFileSet, FileSet, GenCirioFilesForInfo, GenVersionMapFilesForInfo, GetCirioFile, GetFileInfo, GetNameOfFile, GetStreamForFile, ReleaseStreamForFile, ShowReport, VersionStampToUniqueID], UserProfile USING [Token]; RMTWModules: CEDAR MONITOR LOCKS modules USING modules: CedarModuleSet IMPORTS BasicTime, CirioNubAccess, Commander, CommanderOps, CommandTool, Convert, IO, List, LoadStateAccess, MobAccess, MobObjectFiles, MorePfsNames, ObjectFiles, PBasics, PFS, PFSNames, RefTab, Rope, RopeParts, RuntimeError, SourceFileOpsExtras, SystemInterface, UserProfile EXPORTS NewRMTW, RMTWBackdoor, RMTWPrivate = BEGIN OPEN LSA:LoadStateAccess, ObjF:ObjectFiles, MA:MobAccess, MOF:MobObjectFiles, MPfsN:MorePfsNames, RMTWPrivate; ROPE: TYPE ~ Rope.ROPE; PATH: TYPE ~ PFSNames.PATH; CirioFile: TYPE = SystemInterface.CirioFile; CedarModuleSet: TYPE = REF CedarModuleSetBody; CedarModuleSetBody: PUBLIC TYPE = MONITORED RECORD[ fileSet: SystemInterface.FileSet, searchPaths: LIST OF PATH, otherDirectories: LIST OF PATH, remoteServer: Rope.ROPE, table: RefTab.Ref, loadedTable: RefTab.Ref, flushTime: BasicTime.GMT, vsHash: VSHashTable, defMobs: VSHashTable]; CedarModule: TYPE = REF CedarModuleHandle; CedarModuleHandle: TYPE = REF CedarModuleBody; CedarModuleBody: TYPE = RECORD[ moduleSet: CedarModuleSet, mobStamp: REF MobDefs.VersionStamp, sourceStamp: REF MobDefs.VersionStamp, possiblePrincipalDirectories: LIST OF PATH, originalPossibleNameStems: LIST OF PATH, possibleNameStems: LIST OF PATH, failureTime: BasicTime.GMT, mesaSourceFailed: BOOLEAN, mobFileFailed: BOOLEAN, mobFailed: BOOLEAN, cSourceFailed: BOOLEAN, jmpiFailed: BOOLEAN, moduleFailed: BOOLEAN, wholeFailed: BOOLEAN, loadedJmpiFailed: BOOLEAN, mesaSource: CirioFile, jmpi: MOF.JointMobParsedInfo, mobFile: CirioFile, mob: MA.MobCookie, cInfo: CFileInfo, module: ObjF.Module, whole: ObjF.Parsed, loadedJmpi: MOF.JointMobParsedInfo, loadedModule: ObjF.Module, loadedWhole: ObjF.Parsed, loadedModuleInfo: REF LoadStateAccess.LoadedModuleInfo]; CreateCedarModuleSet: PUBLIC PROC[fileSet: SystemInterface.FileSet, remoteServer: Rope.ROPE _ NIL] RETURNS[CedarModuleSet] = BEGIN table: RefTab.Ref _ RefTab.Create[]; loadedTable: RefTab.Ref _ RefTab.Create[]; vsHash: VSHashTable _ CreateVSHashTable[]; defMobs: VSHashTable _ CreateVSHashTable[]; RETURN[NEW[CedarModuleSetBody_[ , fileSet, NIL, NIL, remoteServer, table, loadedTable, BasicTime.Now[], vsHash, defMobs]]]; END; ResetSearchPaths: PUBLIC ENTRY PROC[modules: CedarModuleSet, searchPaths: LIST OF PATH, flushTime: BasicTime.GMT] = BEGIN ENABLE UNWIND => NULL; modules.searchPaths _ searchPaths; modules.flushTime _ flushTime; END; FlushUnknownFileCache: PUBLIC ENTRY PROC[modules: CedarModuleSet, flushTime: BasicTime.GMT] = BEGIN ENABLE UNWIND => NULL; modules.flushTime _ flushTime; END; CedarSourcePosition: TYPE = NewRMTW.CedarSourcePosition; GetCedarSourcePosition: PUBLIC ENTRY PROC[modules: CedarModuleSet, loadedModule: REF LoadStateAccess.LoadedModuleInfo, absPC: CARD] RETURNS[REF CedarSourcePosition] ~ { ENABLE UNWIND => NULL; module: CedarModule ~ GetCedarModuleForLoadedModule[modules, loadedModule]; moduleRelativePC: CARD ~ IF loadedModule # NIL THEN absPC - (loadedModule.lsi[text].base + loadedModule.moduleRelativeBaseAddr) ELSE 0; RETURN[ComputeCedarSourcePosition[module, [[0, ""], moduleRelativePC]]]}; ComputeCedarSourcePosition: PROC[module: CedarModule, spc: ObjF.FileSegmentPC] RETURNS[REF CedarSourcePosition] = BEGIN IF module = NIL THEN RETURN[NEW[CedarSourcePosition_[spc.relPC, NIL, 0, NIL, 0, "unknown mesa module"]]] ELSE BEGIN embeddedModule: ObjF.Module _ GetModule[module]; moduleInfo: REF ObjF.ModuleInfo _ IF embeddedModule # NIL THEN ObjF.GetModuleInfo[embeddedModule] ELSE NIL; parsedRelativePC: ObjF.FileSegmentPC _ [[0, ""], IF moduleInfo # NIL THEN 0--pj moduleInfo.startPC--+spc.relPC ELSE 0]; cLine: CARD _ IF moduleInfo # NIL THEN ObjF.GetLineNumForPC[embeddedModule, parsedRelativePC] ELSE 0; cInfo: CFileInfo _ GetCFileInfo[module]; cFile: CirioFile _ IF cInfo # NIL THEN cInfo.file ELSE NIL; mesaPosition: CARD _ IF cInfo # NIL THEN LookupCLineNum[cInfo, cLine] ELSE 0; remarks: Rope.ROPE _ NIL; IF embeddedModule # NIL AND cInfo # NIL THEN -- check back with parsed BEGIN correspondingcLine: CARD _ LookupMesaSourcePos[cInfo, mesaPosition]; correspondingPC: ObjF.FileSegmentPC _ ObjF.GetPCForLineNum[embeddedModule, correspondingcLine]; originalNest: ObjF.BracketNest _ ObjF.GetBracketNestForPC[embeddedModule, correspondingPC]; originalPair: ObjF.BracketPair _ IF originalNest = NIL THEN NIL ELSE originalNest.rest.first; pcRange: ObjF.PCRange _ IF originalPair = NIL THEN [0, 0] ELSE ObjF.GetPCRange[originalPair]; IF originalPair = NIL OR correspondingPC.relPC < pcRange.first OR pcRange.limit <= correspondingPC.relPC THEN remarks _ IO.PutFR["Source location is potentially erroneous (because it corresponds to c line number %g as well as %g, and the two are in distinct C blocks).", [cardinal[correspondingcLine]], [cardinal[cLine]]]; END; RETURN[NEW[CedarSourcePosition_[spc.relPC, GetMesaFile[module], mesaPosition, cFile, cLine, remarks]]]; END END; GetRopesForSourcePosInfo: PUBLIC PROC[info: REF CedarSourcePosition] RETURNS[LIST OF Rope.ROPE] = BEGIN ropes: LIST OF Rope.ROPE _ NIL; mesaName: PATH _ IF info.mesa = NIL THEN PFSNames.EmptyPath ELSE SystemInterface.GetNameOfFile[info.mesa]; cName: PATH _ IF info.cFile = NIL THEN PFSNames.EmptyPath ELSE SystemInterface.GetNameOfFile[info.cFile]; IF info.remarks # NIL THEN ropes _ CONS[info.remarks, ropes]; ropes _ CONS[IO.PutFR[" line in %g is %g", IO.rope[PFS.RopeFromPath[cName]], IO.card[info.cLineNum]], ropes]; IF info.mesaPosition # 0 THEN ropes _ CONS[IO.PutFR[" position in %g is %g", IO.rope[PFS.RopeFromPath[mesaName]], IO.card[info.mesaPosition]], ropes]; IF info.mesaPosition = 0 THEN ropes _ CONS[IO.PutFR[" position is somewhere in %g", IO.rope[PFS.RopeFromPath[mesaName]]], ropes]; ropes _ CONS[IO.PutFR["for relative pc: %g", IO.card[info.relativePC]], ropes]; RETURN[ropes] END; LoadedModuleInfo: TYPE = NewRMTW.LoadedModuleInfo; LoadedModule: TYPE = REF LoadedModuleBody; LoadedModuleBody: TYPE = RECORD[ module: CedarModule, loadedModule: REF LoadStateAccess.LoadedModuleInfo, loadedModuleFailedTime: BasicTime.GMT]; GetLoadedModuleInfo: PUBLIC ENTRY PROC[modules: CedarModuleSet, loadedModule: REF LoadStateAccess.LoadedModuleInfo] RETURNS[REF LoadedModuleInfo] = BEGIN ENABLE UNWIND => NULL; module: CedarModule _ GetCedarModuleForLoadedModule[modules, loadedModule]; IF module = NIL THEN RETURN[NIL] ELSE RETURN[NEW[LoadedModuleInfo_[ jmpi: GetLoadedJMPI[module], mob: GetMob[module], loadedModule: loadedModule]]]; END; CedarBreakAddress: TYPE = NewRMTW.CedarBreakAddress; GetAbsAddressForBreak: PUBLIC ENTRY PROC[modules: CedarModuleSet, mesa: CirioFile, loadState: LoadStateAccess.LoadStateHandle, sourcePos: CARD] RETURNS[REF CedarBreakAddress] = BEGIN ENABLE UNWIND => NULL; lm: LoadedModule _ GetLoadedModuleForMesa[modules, mesa, loadState]; IF lm = NIL OR lm.module = NIL OR lm.loadedModule = NIL THEN RETURN[NIL] ELSE BEGIN cInfo: CFileInfo _ GetCFileInfo[lm.module]; IF cInfo = NIL THEN RETURN[NIL] ELSE BEGIN cLineNum: CARD _ LookupMesaSourcePos[cInfo, sourcePos]; parsedRelativePC: ObjF.FileSegmentPC _ ObjF.GetPCForLineNum[lm.loadedModule.module, cLineNum]; correspondingCLineNum: CARD _ ObjF.GetLineNumForPC[lm.loadedModule.module, parsedRelativePC]; correspondingMesaPos: CARD _ LookupCLineNum[cInfo, correspondingCLineNum]; moduleRelPC: CARD _ parsedRelativePC.relPC - lm.loadedModule.moduleRelativeBaseAddr; absPC: CARD _ lm.loadedModule.lsi[text].base+parsedRelativePC.relPC; RETURN[NEW[CedarBreakAddress_[mesa, sourcePos, cInfo.file, cLineNum, [[0, ""], moduleRelPC], correspondingCLineNum, correspondingMesaPos, lm.loadedModule, absPC]]]; END; END END; GetRopesForCedarBreakAddress: PUBLIC PROC[addr: REF CedarBreakAddress] RETURNS[LIST OF Rope.ROPE] = BEGIN IF addr = NIL THEN RETURN[LIST["failed to set break"]] ELSE BEGIN mesa: PATH _ SystemInterface.GetNameOfFile[addr.mesa]; cname: PATH _ SystemInterface.GetNameOfFile[addr.cFile]; rope1: Rope.ROPE _ IO.PutFR["setting break in %g at source pos = %g", IO.rope[PFS.RopeFromPath[mesa]], IO.card[addr.mesaPosition]]; rope2: Rope.ROPE _ IO.PutFR[" C line num = %g in %g", IO.card[addr.cLineNum], IO.rope[PFS.RopeFromPath[cname]]]; rope3: Rope.ROPE _ IO.PutFR[" module relative pos = %g", IO.card[addr.moduleRelativePC.relPC]]; rope4: Rope.ROPE _ IO.PutFR[" corresponding C line num = %g", IO.card[addr.correspondingCLineNum]]; rope5: Rope.ROPE _ IO.PutFR[" resulting mesa source pos = %g", IO.card[addr.correspondingMesaPosition]]; rope6: Rope.ROPE _ IO.PutFR[" abs pos = %g", IO.card[addr.absPC]]; RETURN[LIST[rope1, rope2, rope3, rope4, rope5, rope6]]; END; END; DefMobHolder: TYPE = RECORD[failureTime: BasicTime.GMT, mob: MA.MobCookie]; GetDefinitionMob: PUBLIC ENTRY PROC[modules: CedarModuleSet, vs: MobDefs.VersionStamp, stem: PATH _ NIL] RETURNS[MA.MobCookie] = BEGIN ENABLE UNWIND => NULL; vsKey: RefTab.Key _ CreateVSKey[vs, emptyRopePart]; mobRef: REF DefMobHolder _ NARROW[RefTab.Fetch[modules.defMobs.table, vsKey].val]; IF mobRef = NIL THEN BEGIN mobRef _ NEW[DefMobHolder_[modules.flushTime, NIL]]; IF NOT RefTab.Store[modules.defMobs.table, vsKey, mobRef] THEN ERROR; END; IF mobRef.mob = NIL AND BasicTime.Period[mobRef.failureTime, modules.flushTime] >= 0 THEN BEGIN foundMob: MA.MobCookie _ NIL; -- tentative foundPossibleFile: CirioFile _ NIL; -- tentative foundCreateTime: BasicTime.GMT _ BasicTime.earliestGMT; -- tentative AcceptOneFile: PROC [info: SystemInterface.CirioFileInfo] RETURNS[thisIsIt: BOOLEAN _ FALSE] = { possibleFile: CirioFile; mob: MA.MobCookie; mobStamp: MobDefs.VersionStamp; possibleFile _ SystemInterface.GetCirioFile[modules.fileSet, info.fullName, info.uniqueID]; mob _ MA.CreateMobCookie[possibleFile ! MobAccess.MobError => { SystemInterface.ShowReport[IO.PutFR["\tbad mob %g", [rope[PFS.RopeFromPath[info.fullName]]] ], IF debugSearch THEN $urgent ELSE $debug]; GOTO failure}]; mobStamp _ MA.ReadMobVersionStamp[mob]; IF debugSearch THEN SystemInterface.ShowReport[IO.PutFR["\t?name=%g,\n\tmobStamp=%08x%08x.", [rope[PFS.RopeFromPath[info.fullName]]], [cardinal[mobStamp[0]]], [cardinal[mobStamp[1]]] ], $urgent]; foundMob _ mob; foundPossibleFile _ possibleFile; foundCreateTime _ info.uniqueID.egmt.time; RETURN[TRUE]; EXITS failure => RETURN [FALSE]}; TryOneFile: PROC[info: SystemInterface.CirioFileInfo] RETURNS[thisIsIt: BOOLEAN _ FALSE] = { possibleFile: CirioFile; mob: MA.MobCookie; mobStamp: MobDefs.VersionStamp; possibleFile _ SystemInterface.GetCirioFile[modules.fileSet, info.fullName, info.uniqueID]; mob _ MA.CreateMobCookie[possibleFile ! MobAccess.MobError => { SystemInterface.ShowReport[IO.PutFR["\tbad mob %g", [rope[PFS.RopeFromPath[info.fullName]]] ], IF debugSearch THEN $urgent ELSE $debug]; GOTO failure}]; mobStamp _ MA.ReadMobVersionStamp[mob]; IF debugSearch THEN SystemInterface.ShowReport[IO.PutFR["\t?name=%g,\n\tmobStamp=%08x%08x.", [rope[PFS.RopeFromPath[info.fullName]]], [cardinal[mobStamp[0]]], [cardinal[mobStamp[1]]] ], $urgent]; IF vs = mobStamp THEN { foundMob _ mob; foundPossibleFile _ possibleFile; foundCreateTime _ info.uniqueID.egmt.time; RETURN[TRUE]}; RETURN[FALSE]; EXITS failure => RETURN [FALSE]}; TryOneDir: PROC[dir: PATH] = BEGIN mobFileNamePattern: PATH _ PFS.PathFromRope[Rope.Cat[PFS.RopeFromPath[stem], ".mob", "*"]].ExpandName[dir]; IF debugSearch THEN SystemInterface.ShowReport[IO.PutFR["\tSearching file pattern %g.", [rope[PFS.RopeFromPath[mobFileNamePattern]]] ], $urgent]; [] _ SystemInterface.GenCirioFilesForInfo[modules.fileSet, mobFileNamePattern, TryOneFile]; END; SystemInterface.ShowReport[Rope.Cat["searching for mob for ", IF stem#NIL THEN PFS.RopeFromPath[stem] ELSE "???"], $normal]; IF stem=NIL THEN SystemInterface.ShowReport[IO.PutFR["\twith mobStamp=%08x%08x.", [cardinal[vs[0]]], [cardinal[vs[1]]] ], IF debugSearch THEN $urgent ELSE $normal]; IF stem#NIL THEN FOR dirs: LIST OF PATH _ modules.searchPaths, dirs.rest WHILE dirs # NIL AND foundPossibleFile = NIL DO IF debugSearch THEN SystemInterface.ShowReport[IO.PutFR["\tSearching search dir %g.", [rope[PFS.RopeFromPath[dirs.first]]] ], $urgent]; TryOneDir[dirs.first]; ENDLOOP; IF foundPossibleFile = NIL THEN { IF debugSearch THEN SystemInterface.ShowReport["\tSearching version maps.", $urgent]; IF stem#NIL THEN foundPossibleFile _ SystemInterface.GenVersionMapFilesForInfo[modules.fileSet, $Intermediate, vs, LIST[stem], LIST[".mob"], TRUE, AcceptOneFile] ELSE foundPossibleFile _ SystemInterface.GenVersionMapFilesForInfo[modules.fileSet, $Intermediate, vs, LIST[MPfsN.Cons1[MPfsN.ConstructComponent[["*"], [none]]]], LIST[".mob"], TRUE, AcceptOneFile]; }; IF stem#NIL THEN FOR dirs: LIST OF PATH _ modules.otherDirectories, dirs.rest WHILE dirs # NIL AND foundPossibleFile = NIL DO IF debugSearch THEN SystemInterface.ShowReport[IO.PutFR["\tSearching other dir %g.", [rope[PFS.RopeFromPath[dirs.first]]] ], $urgent]; TryOneDir[dirs.first]; ENDLOOP; IF foundPossibleFile = NIL THEN BEGIN mobRef.failureTime _ BasicTime.Now[]; SystemInterface.ShowReport[Rope.Cat["unable to find mob for ", IF stem#NIL THEN PFS.RopeFromPath[stem] ELSE "???"], $urgent]; END ELSE BEGIN mobName: PATH _ SystemInterface.GetNameOfFile[foundPossibleFile]; mobRef.mob _ foundMob; SystemInterface.ShowReport[Rope.Cat[" found ", PFS.RopeFromPath[mobName]], $normal]; END; END; RETURN[mobRef.mob]; END; GetLoadedModuleForMesa: PROC[modules: CedarModuleSet, mesa: CirioFile, loadState: LoadStateAccess.LoadStateHandle] RETURNS[LoadedModule] = BEGIN lm: LoadedModule _ NARROW[RefTab.Fetch[modules.loadedTable, mesa].val]; IF lm = NIL THEN BEGIN lm _ NEW[LoadedModuleBody_[NIL, NIL, modules.flushTime]]; IF NOT RefTab.Store[modules.loadedTable, mesa, lm] THEN ERROR; END; IF lm.loadedModule = NIL AND (BasicTime.Period[lm.loadedModuleFailedTime, modules.flushTime] >= 0) THEN BEGIN mesaName: PATH _ SystemInterface.GetNameOfFile[mesa]; givenSourceStamp: MobDefs.VersionStamp _ MA.ComputeSourceVersionStamp[mesa]; parts: NameParts _ GetNamePartsFromFullPathName[mesaName]; stemRope: Rope.ROPE _ parts.nameStem; module: CedarModule _ NIL; lm.loadedModuleFailedTime _ BasicTime.Now[]; -- if needed SystemInterface.ShowReport[IO.PutFR["Searching for loaded module %g created at %g (source stamp=%g).", [rope[stemRope]], [time[SystemInterface.GetFileInfo[mesa].uniqueID.egmt.time]], [rope[FmtStamp[givenSourceStamp]]] ], $normal]; IF parts.principalDirectory # PFSNames.EmptyPath THEN modules.otherDirectories _ AddAName[parts.principalDirectory, modules.otherDirectories]; FOR skip: CARD _ 1--despite comment under CirioNubAccess.LookupMatchingSymEntryByName, which is inconsistent with the general pattern, 0 and 1 find the same thing(MJS thinks at June 8, 1991)--, skip+1 DO loadedModule: REF LoadStateAccess.LoadedModuleInfo _ LoadStateAccess.GetLoadedModuleInfoFromStemName[loadState, parts.nameStem, skip, modules]; IF loadedModule=NIL THEN { SystemInterface.ShowReport[IO.PutFR["Giving up search for loaded module %g at skip=%g.", [rope[stemRope]], [cardinal[skip]] ], $normal]; EXIT}; module _ GetCedarModuleForLoadedModule[modules, loadedModule]; IF module#NIL THEN { ldoPath: PATH ~ loadedModule.loadedFile.GetNameOfFile[]; ldoRope: Rope.ROPE ~ PFS.RopeFromPath[ldoPath]; [] _ GetMob[module]; IF module.sourceStamp=NIL THEN SystemInterface.ShowReport[IO.PutFR["Rejecting the one in %g of %g (found at skip=%g) for lack of source version stamp.", [rope[ldoRope]], [time[loadedModule.createTimeOfLoadedFile]], [cardinal[skip]] ], $normal] ELSE IF module.sourceStamp^ = givenSourceStamp THEN { lm.module _ module; lm.loadedModule _ loadedModule; SystemInterface.ShowReport[IO.PutFR["Accepting the one in %g of %g (found at skip=%g).", [rope[ldoRope]], [time[loadedModule.createTimeOfLoadedFile]], [cardinal[skip]] ], $normal]; RETURN [lm]} ELSE SystemInterface.ShowReport[IO.PutFR["Rejecting the one in %g of %g (found at skip=%g) because source version stamp (%g) isn't right.", [rope[ldoRope]], [time[loadedModule.createTimeOfLoadedFile]], [cardinal[skip]], [rope[FmtStamp[module.sourceStamp^]]] ], $normal] }; ENDLOOP; END; RETURN[lm]; END; FmtStamp: PROC [stamp: MobDefs.VersionStamp] RETURNS [Rope.ROPE] ~ {RETURN IO.PutFR["%08x%08x", [cardinal[stamp[0]]], [cardinal[stamp[1]]] ]}; GetCedarModuleForLoadedModule: PROC[modules: CedarModuleSet, info: REF LoadStateAccess.LoadedModuleInfo] RETURNS[CedarModule] = BEGIN IF info = NIL THEN RETURN[NIL] ELSE BEGIN tentative: CedarModule _ CreateCedarModuleFromModule[modules, info.parsed, info.module, info.possibleModuleFileNames]; IF tentative#NIL AND tentative.loadedModuleInfo=NIL THEN tentative.loadedModuleInfo _ info; RETURN[tentative]; END END; CreateCedarModuleFromMesa: PROC[modules: CedarModuleSet, mesa: CirioFile] RETURNS[CedarModule] = BEGIN sourceStamp: REF MobDefs.VersionStamp _ NEW[MobDefs.VersionStamp_MA.ComputeSourceVersionStamp[mesa]]; mesaName: PATH _ SystemInterface.GetNameOfFile[mesa]; parts: NameParts _ GetNamePartsFromFullPathName[mesaName]; base: RopeParts.RopePart _ RopeParts.InlineMake[parts.nameStem]; vsKey: RefTab.Key _ CreateVSKey[sourceStamp^, base]; module: CedarModule _ NARROW[RefTab.Fetch[modules.vsHash.table, vsKey].val]; IF module = NIL THEN BEGIN module _ CreateEmptyCedarModule[modules]; module.possiblePrincipalDirectories _ LIST[parts.principalDirectory]; module.originalPossibleNameStems _ LIST[PFS.PathFromRope[parts.nameStem]]; module.possibleNameStems _ module.originalPossibleNameStems; module.mesaSource _ mesa; module.sourceStamp _ sourceStamp; IF NOT RefTab.Store[modules.vsHash.table, vsKey, module] THEN ERROR; END; RETURN[module]; END; CreateCedarModuleFromModule: PROC[modules: CedarModuleSet, whole: ObjF.Parsed, embeddedModule: ObjF.Module, possibleModuleFileNames: LIST OF PATH] RETURNS[CedarModule] = BEGIN vsInfo: REF ObjF.VersionStampInfo _ ObjF.FindVersionStamp[embeddedModule]; recoveredStamp: REF RecoveredVersionStamp _ IF vsInfo = NIL OR Rope.IsEmpty[vsInfo.contents] THEN NIL ELSE ConvertDotOFormatVersionStampToMobFormat[vsInfo.contents]; mobStamp: REF MobDefs.VersionStamp _ IF recoveredStamp = NIL THEN NIL ELSE NEW[MobDefs.VersionStamp_recoveredStamp.mobStamp]; vsKey: RefTab.Key _ IF mobStamp = NIL THEN NIL ELSE CreateVSKey[mobStamp^, emptyRopePart]; module: CedarModule _ IF mobStamp = NIL THEN NIL ELSE NARROW[RefTab.Fetch[modules.vsHash.table, vsKey].val]; IF module = NIL THEN BEGIN moduleInfo: REF ObjF.ModuleInfo _ ObjF.GetModuleInfo[embeddedModule]; -- for SunOS5.x IF mobStamp = NIL THEN RETURN[NIL]; module _ CreateEmptyCedarModule[modules]; module.module _ embeddedModule; module.whole _ whole; module.mobStamp _ mobStamp; IF whole = moduleInfo.whole THEN -- normal case BEGIN FOR names: LIST OF PATH _ possibleModuleFileNames, names.rest WHILE names # NIL DO parts: NameParts _ GetNamePartsFromFullPathName[names.first]; IF parts.nameStem.Length[] # 0 THEN module.originalPossibleNameStems _ AddAName[PFS.PathFromRope[parts.nameStem], module.originalPossibleNameStems]; IF parts.principalDirectory # PFSNames.EmptyPath THEN module.possiblePrincipalDirectories _ AddAName[parts.principalDirectory, module.possiblePrincipalDirectories]; ENDLOOP; BEGIN wholeFileName: PATH _ SystemInterface.GetNameOfFile[ObjF.GetObjectFile[whole]]; parts: NameParts _ GetNamePartsFromFullPathName[wholeFileName]; IF parts.principalDirectory # PFSNames.EmptyPath THEN BEGIN modules.otherDirectories _ AddAName[parts.principalDirectory, modules.otherDirectories]; modules.flushTime _ BasicTime.Now[]; END; END; END ELSE -- SunOS 5.x - couldn't obtain debug information from loaded object module BEGIN parts: NameParts _ GetNamePartsFromFullPathName[moduleInfo.fileName]; IF parts.nameStem.Length[] # 0 THEN module.originalPossibleNameStems _ AddAName[PFS.PathFromRope[parts.nameStem], module.originalPossibleNameStems]; IF parts.principalDirectory # PFSNames.EmptyPath THEN module.possiblePrincipalDirectories _ AddAName[parts.principalDirectory, module.possiblePrincipalDirectories]; BEGIN wholeFileName: PATH _ SystemInterface.GetNameOfFile[ObjF.GetObjectFile[moduleInfo.whole]]; parts: NameParts _ GetNamePartsFromFullPathName[wholeFileName]; IF parts.principalDirectory # PFSNames.EmptyPath THEN BEGIN modules.otherDirectories _ AddAName[parts.principalDirectory, modules.otherDirectories]; modules.flushTime _ BasicTime.Now[]; END; END; END; IF NOT RefTab.Store[modules.vsHash.table, vsKey, module] THEN ERROR; END; IF module # NIL THEN -- just in case BEGIN IF module.module = NIL THEN module.module _ embeddedModule; IF module.whole = NIL THEN module.whole _ whole; END; RETURN[module]; END; CreateEmptyCedarModule: PROC[modules: CedarModuleSet] RETURNS[CedarModule] = {RETURN[NEW[CedarModuleHandle_NEW[CedarModuleBody_[modules, NIL, NIL, NIL, NIL, NIL, BasicTime.Now[], FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, NIL, NIL, NIL, NIL, NIL, NIL, NIL]]]]}; GetLoadedJMPI: PROC[module: CedarModule] RETURNS[MOF.JointMobParsedInfo] = BEGIN IF module.loadedJmpi = NIL AND NOT (module.loadedJmpiFailed AND BasicTime.Period[module.failureTime, module.moduleSet.flushTime] < 0) THEN BEGIN mob: MA.MobCookie _ GetMob[module]; loadedModule: ObjF.Module _ GetLoadedModule[module]; loadedDotO: ObjF.Parsed _ GetLoadedParsed[module]; IF mob # NIL AND loadedModule # NIL AND loadedDotO # NIL THEN module.loadedJmpi _ MOF.CreateJointMobParsedInfo[mob, loadedDotO, loadedModule]; IF module.loadedJmpi = NIL THEN {module.loadedJmpiFailed _ TRUE; module.failureTime _ BasicTime.Now[]} END; RETURN[module.loadedJmpi]; END; GetLoadedParsed: PROC[module: CedarModule] RETURNS[ObjF.Parsed] = BEGIN IF module.loadedWhole = NIL AND module.loadedModuleInfo # NIL THEN module.loadedWhole _ module.loadedModuleInfo.parsed; RETURN[module.loadedWhole]; END; GetLoadedModule: PROC[module: CedarModule] RETURNS[ObjF.Module] = BEGIN IF module.loadedModule = NIL AND module.loadedModuleInfo # NIL THEN module.loadedModule _ module.loadedModuleInfo.module; RETURN[module.loadedModule]; END; SeekCSource: PUBLIC PROC [cms: CedarModuleSet, basicInfo: REF LSA.BasicPCInfo, ledo: REF LSA.LoadedModuleInfo] RETURNS [foundFile: SystemInterface.CirioFile _ NIL] ~ { TryOneFile: PROC[info: SystemInterface.CirioFileInfo] RETURNS[thisIsIt: BOOLEAN] = {RETURN[TRUE]}; TryOneDir: PROC[dir: PATH] = { IF debugSearch THEN SystemInterface.ShowReport[IO.PutFR["\tSearching directory %g.", [rope[PFS.RopeFromPath[dir]]] ], $urgent]; FOR spats: LIST OF ROPE _ pats, spats.rest WHILE spats#NIL AND foundFile=NIL DO mesaPathName: PATH _ PFS.PathFromRope[spats.first]; mesaPathNamePattern: PATH _ mesaPathName.ExpandName[dir]; foundFile _ SystemInterface.GenCirioFilesForInfo[cms.fileSet, mesaPathNamePattern, TryOneFile]; ENDLOOP; RETURN}; pats: LIST OF ROPE _ NIL; paths: LIST OF PATH _ NIL; descr: ROPE _ NIL; FOR pmns: LIST OF PATH _ basicInfo.possibleModuleNames, pmns.rest WHILE pmns#NIL DO short: ROPE _ PFS.RopeFromPath[pmns.first]; sl: INT _ short.Length; this: ROPE; IF sl>2 AND short.EqualSubstrs[start1: sl-2, s2: ".o"] THEN this _ short.Replace[sl-1, 1, "c"] ELSE this _ short.Concat[".c"]; IF descr=NIL THEN descr _ this ELSE descr _ Rope.Cat[descr, " or ", this]; pats _ CONS[this, pats]; paths _ CONS[PFS.PathFromRope[this], paths]; ENDLOOP; SystemInterface.ShowReport[Rope.Concat["Searching for C source in ", descr], $normal]; FOR dirs: LIST OF PATH _ cms.searchPaths, dirs.rest WHILE dirs # NIL AND foundFile = NIL DO TryOneDir[dirs.first]; ENDLOOP; IF foundFile = NIL THEN { IF debugSearch THEN SystemInterface.ShowReport["\tTrying version maps.", $urgent]; foundFile _ SystemInterface.GenVersionMapFilesForInfo[cms.fileSet, $Source, MobDefs.NullVersion, paths, LIST[""], TRUE, TryOneFile]}; FOR dirs: LIST OF PATH _ cms.otherDirectories, dirs.rest WHILE dirs # NIL AND foundFile = NIL DO TryOneDir[dirs.first]; ENDLOOP; IF foundFile # NIL THEN { nameRope: PATH _ SystemInterface.GetNameOfFile[foundFile]; SystemInterface.ShowReport[Rope.Cat[" found ", PFS.RopeFromPath[nameRope]], $normal]; } ELSE { SystemInterface.ShowReport[" failed", $normal]; }; RETURN}; GetMesaFile: PROC[module: CedarModule] RETURNS[CirioFile] = BEGIN IF module.mesaSource = NIL AND NOT (module.mesaSourceFailed AND BasicTime.Period[module.failureTime, module.moduleSet.flushTime] < 0) THEN BEGIN foundFile: CirioFile _ NIL; -- tentative mob: MA.MobCookie _ GetMob[module]; sourceUnique: PFS.UniqueID; TryOneFile: PROC[info: SystemInterface.CirioFileInfo] RETURNS[thisIsIt: BOOLEAN] = {RETURN[info.uniqueID = sourceUnique]}; TryOneDir: PROC[dir: PATH] = BEGIN FOR stems: LIST OF PATH _ module.possibleNameStems, stems.rest WHILE stems # NIL AND foundFile = NIL DO mesaPathName: PATH _ PFS.PathFromRope [Rope.Cat [PFS.RopeFromPath[stems.first], ".mesa*"]]; mesaPathNamePattern: PATH _ mesaPathName.ExpandName[dir]; foundFile _ SystemInterface.GenCirioFilesForInfo[module.moduleSet.fileSet, mesaPathNamePattern, TryOneFile]; ENDLOOP; END; IF module.sourceStamp#NIL THEN sourceUnique _ SystemInterface.VersionStampToUniqueID[module.sourceStamp^] ELSE IF mob#NIL THEN sourceUnique _ SystemInterface.VersionStampToUniqueID[MA.ReadSourceVersionStamp[mob]] ELSE RETURN[NIL]; ShowSearchReport["mesa source", module]; FOR dirs: LIST OF PATH _ module.moduleSet.searchPaths, dirs.rest WHILE dirs # NIL AND foundFile = NIL DO TryOneDir[dirs.first]; ENDLOOP; IF foundFile = NIL THEN foundFile _ SystemInterface.GenVersionMapFilesForInfo[module.moduleSet.fileSet, $Source, MobDefs.NullVersion, module.possibleNameStems, LIST[".mesa"], TRUE, TryOneFile, sourceUnique]; FOR dirs: LIST OF PATH _ module.possiblePrincipalDirectories, dirs.rest WHILE dirs # NIL AND foundFile = NIL DO TryOneDir[dirs.first]; ENDLOOP; FOR dirs: LIST OF PATH _ module.moduleSet.otherDirectories, dirs.rest WHILE dirs # NIL AND foundFile = NIL DO TryOneDir[dirs.first]; ENDLOOP; IF foundFile # NIL THEN BEGIN mesaName: PATH _ SystemInterface.GetNameOfFile[foundFile]; parts: NameParts _ GetNamePartsFromFullPathName[mesaName]; module.possiblePrincipalDirectories _ AddAName[parts.principalDirectory, module.possiblePrincipalDirectories]; module.possibleNameStems _ LIST[PFS.PathFromRope[parts.nameStem]]; module.mesaSource _ foundFile; module.mesaSourceFailed _ FALSE; SystemInterface.ShowReport[Rope.Cat[" found ", PFS.RopeFromPath[mesaName]], $normal]; END ELSE BEGIN module.mesaSourceFailed _ TRUE; module.failureTime _ BasicTime.Now[]; ShowFailureReport["mesa source", module]; END; END; RETURN[module.mesaSource]; END; GetCFileInfo: PROC[module: CedarModule] RETURNS[CFileInfo] = BEGIN IF module.cInfo = NIL AND NOT (module.cSourceFailed AND BasicTime.Period[module.failureTime, module.moduleSet.flushTime] < 0) THEN BEGIN [] _ GetMob[module]; -- always get the mob first. Thus, if we have a mesa source, then the corresponding mob will give us the mob version IF module.possibleNameStems # NIL THEN BEGIN foundFile: CirioFile _ NIL; -- tentative foundCInfo: CFileInfo _ NIL; -- tentative foundPossibleFile: CirioFile _ NIL; -- tentative TryOneFile: PROC[info: SystemInterface.CirioFileInfo] RETURNS[thisIsIt: BOOLEAN _ FALSE] = BEGIN IF module.mobStamp = NIL THEN BEGIN possibleFile: CirioFile _ SystemInterface.GetCirioFile[module.moduleSet.fileSet, info.fullName, info.uniqueID]; cInfo: CFileInfo _ CreateCFileInfo[possibleFile]; foundCInfo _ cInfo; foundPossibleFile _ possibleFile; SystemInterface.ShowReport[Rope.Cat["accepting ", PFS.RopeFromPath[info.fullName], " without checking version stamp"], $normal]; RETURN[TRUE] END ELSE BEGIN possibleFile: CirioFile _ SystemInterface.GetCirioFile[module.moduleSet.fileSet, info.fullName, info.uniqueID]; vsRope: Rope.ROPE _ ScanCFileForVersionStamp[possibleFile]; IF vsRope # NIL THEN BEGIN recoveredStamp: REF RecoveredVersionStamp _ ConvertDotOFormatVersionStampToMobFormat[vsRope]; IF recoveredStamp # NIL AND module.mobStamp # NIL AND module.mobStamp^ = recoveredStamp.mobStamp THEN BEGIN foundCInfo _ CreateCFileInfo[possibleFile]; foundPossibleFile _ possibleFile; RETURN[TRUE] END END; RETURN[FALSE]; END; END; TryOneDir: PROC[dir: PATH] = BEGIN FOR stems: LIST OF PATH _ module.possibleNameStems, stems.rest WHILE stems # NIL AND foundFile = NIL DO cFileNamePattern1: PATH _ PFS.PathFromRope[Rope.Cat[PFS.RopeFromPath[stems.first], ".c2c.c", "*"]]; cFileNamePattern2: PATH _ PFS.PathFromRope[Rope.Cat[PFS.RopeFromPath[stems.first], ".c", "*"]]; -- perhaps the conventions aren't being followed cFileNamePattern1 _ cFileNamePattern1.ExpandName[dir]; cFileNamePattern1 _ cFileNamePattern2.ExpandName[dir]; foundFile _ SystemInterface.GenCirioFilesForInfo[module.moduleSet.fileSet, cFileNamePattern1, TryOneFile]; IF foundFile = NIL THEN foundFile _ SystemInterface.GenCirioFilesForInfo[module.moduleSet.fileSet, cFileNamePattern2, TryOneFile] ENDLOOP; END; ShowSearchReport["c source", module]; FOR dirs: LIST OF PATH _ module.moduleSet.searchPaths, dirs.rest WHILE dirs # NIL AND foundFile = NIL DO TryOneDir[dirs.first]; ENDLOOP; IF foundFile = NIL THEN foundFile _ SystemInterface.GenVersionMapFilesForInfo[module.moduleSet.fileSet, $Intermediate, MobDefs.NullVersion, module.possibleNameStems, LIST[".c2c.c"], TRUE, TryOneFile]; IF foundFile = NIL THEN foundFile _ SystemInterface.GenVersionMapFilesForInfo[module.moduleSet.fileSet, $Source, MobDefs.NullVersion, module.possibleNameStems, LIST[".c"], TRUE, TryOneFile]; FOR dirs: LIST OF PATH _ module.possiblePrincipalDirectories, dirs.rest WHILE dirs # NIL AND foundFile = NIL DO TryOneDir[dirs.first]; ENDLOOP; FOR dirs: LIST OF PATH _ module.moduleSet.otherDirectories, dirs.rest WHILE dirs # NIL AND foundFile = NIL DO TryOneDir[dirs.first]; ENDLOOP; IF foundFile = NIL THEN BEGIN module.cSourceFailed _ TRUE; module.failureTime _ BasicTime.Now[]; ShowFailureReport["c source", module]; END ELSE BEGIN cName: PATH _ SystemInterface.GetNameOfFile[foundFile]; parts: NameParts _ GetNamePartsFromFullPathName[cName]; IF foundFile # foundPossibleFile THEN ERROR; module.cInfo _ foundCInfo; module.possiblePrincipalDirectories _ AddAName[parts.principalDirectory, module.possiblePrincipalDirectories]; module.cSourceFailed _ FALSE; SystemInterface.ShowReport[Rope.Cat[" found ", PFS.RopeFromPath[cName]], $normal]; END; END; END; RETURN[module.cInfo]; END; GetJMPI: PROC[module: CedarModule] RETURNS[MOF.JointMobParsedInfo] = BEGIN IF module.jmpi = NIL AND NOT (module.jmpiFailed AND BasicTime.Period[module.failureTime, module.moduleSet.flushTime] < 0) THEN BEGIN mob: MA.MobCookie _ GetMob[module]; embeddedModule: ObjF.Module _ GetModule[module]; whole: ObjF.Parsed _ GetParsed[module]; IF mob # NIL AND embeddedModule # NIL AND whole # NIL THEN module.jmpi _ MOF.CreateJointMobParsedInfo[mob, whole, embeddedModule]; IF module.jmpi = NIL THEN {module.jmpiFailed _ TRUE; module.failureTime _ BasicTime.Now[]} END; RETURN[module.jmpi]; END; GetParsed: PROC[module: CedarModule] RETURNS[ObjF.Parsed] = BEGIN IF module.whole = NIL AND NOT (module.wholeFailed AND BasicTime.Period[module.failureTime, module.moduleSet.flushTime] < 0) THEN BEGIN [] _ GetModule[module]; IF module.whole = NIL THEN BEGIN module.wholeFailed _ TRUE; module.failureTime _ BasicTime.Now[]; ShowFailureReport["whole", module]; END; END; RETURN[module.whole]; END; GetModule: PROC[module: CedarModule] RETURNS[ObjF.Module] = BEGIN IF module.module = NIL AND NOT (module.moduleFailed AND BasicTime.Period[module.failureTime, module.moduleSet.flushTime] < 0) THEN BEGIN [] _ GetMob[module]; IF module.possibleNameStems # NIL AND module.mob # NIL THEN BEGIN foundFile: CirioFile _ NIL; -- tentative foundDotO: ObjF.Parsed _ NIL; -- tentative foundModule: ObjF.Module _ NIL; -- tentative foundPossibleFile: CirioFile _ NIL; -- tentative TryOneFile: PROC[info: SystemInterface.CirioFileInfo] RETURNS[thisIsIt: BOOLEAN _ FALSE] = BEGIN IF module.mobStamp = NIL THEN ERROR ELSE BEGIN possibleFile: CirioFile _ SystemInterface.GetCirioFile[module.moduleSet.fileSet, info.fullName, info.uniqueID]; possibleDotO: ObjF.Parsed _ ObjF.CreateParsed[possibleFile]; possibleModule: ObjF.Module _ FallBackFindModule[possibleDotO, 0]; vsInfo: REF ObjF.VersionStampInfo _ ObjF.FindVersionStamp[possibleModule]; recoveredStamp: REF RecoveredVersionStamp _ IF vsInfo = NIL OR vsInfo.contents = NIL THEN NIL ELSE ConvertDotOFormatVersionStampToMobFormat[vsInfo.contents]; IF recoveredStamp # NIL AND module.mobStamp # NIL AND recoveredStamp.mobStamp = module.mobStamp^ THEN BEGIN foundDotO _ possibleDotO; foundModule _ possibleModule; foundPossibleFile _ possibleFile; RETURN[TRUE] END ELSE RETURN[FALSE]; END; END; TryOneDir: PROC[dir: PATH] = BEGIN rdir: Rope.ROPE _ PFS.RopeFromPath[PFSNames.EnsureDirectory[dir]]; FOR stems: LIST OF PATH _ module.possibleNameStems, stems.rest WHILE stems # NIL AND foundFile = NIL DO patterns: LIST OF PATH _ LIST[ PFS.PathFromRope[Rope.Cat[rdir, "debug/", PFS.RopeFromPath[stems.first], ".c2c.o"]], PFS.PathFromRope[Rope.Cat[rdir, "debug/", PFS.RopeFromPath[stems.first], ".o"]], PFS.PathFromRope[Rope.Cat[rdir, "debug/", PFS.RopeFromPath[stems.first]]], PFS.PathFromRope[Rope.Cat[rdir, "sun4-debug/", PFS.RopeFromPath[stems.first], ".c2c.o", "*"]], PFS.PathFromRope[Rope.Cat[rdir, "sun4-debug/", PFS.RopeFromPath[stems.first], ".o", "*"]], PFS.PathFromRope[Rope.Cat[rdir, "sun4-debug/", PFS.RopeFromPath[stems.first], "*"]], PFS.PathFromRope[Rope.Cat[rdir, "sun4/", PFS.RopeFromPath[stems.first], ".c2c.o", "*"]], PFS.PathFromRope[Rope.Cat[rdir, "sun4/", PFS.RopeFromPath[stems.first], ".o", "*"]], PFS.PathFromRope[Rope.Cat[rdir, "sun4/", PFS.RopeFromPath[stems.first], "*"]], PFS.PathFromRope[Rope.Cat[rdir, PFS.RopeFromPath[stems.first], ".c2c.o", "*"]], PFS.PathFromRope[Rope.Cat[rdir, PFS.RopeFromPath[stems.first], ".o", "*"]], PFS.PathFromRope[Rope.Cat[rdir, PFS.RopeFromPath[stems.first], "*"]]]; FOR ps: LIST OF PATH _ patterns, ps.rest WHILE ps # NIL AND foundFile = NIL DO foundFile _ SystemInterface.GenCirioFilesForInfo[module.moduleSet.fileSet, ps.first, TryOneFile]; ENDLOOP; ENDLOOP; END; ShowSearchReport["module", module]; FOR dirs: LIST OF PATH _ module.moduleSet.searchPaths, dirs.rest WHILE dirs # NIL AND foundFile = NIL DO TryOneDir[dirs.first]; ENDLOOP; IF foundFile = NIL THEN [] _ SystemInterface.GenVersionMapFilesForInfo[module.moduleSet.fileSet, $Executable, <>MobDefs.NullVersion, module.possibleNameStems, LIST[".c2c.o", ".o", ""], TRUE, TryOneFile]; FOR dirs: LIST OF PATH _ module.possiblePrincipalDirectories, dirs.rest WHILE dirs # NIL AND foundFile = NIL DO TryOneDir[dirs.first]; ENDLOOP; FOR dirs: LIST OF PATH _ module.moduleSet.otherDirectories, dirs.rest WHILE dirs # NIL AND foundFile = NIL DO TryOneDir[dirs.first]; ENDLOOP; IF foundFile = NIL THEN BEGIN module.moduleFailed _ TRUE; module.failureTime _ BasicTime.Now[]; ShowFailureReport["module", module]; END ELSE BEGIN moduleName: PATH _ SystemInterface.GetNameOfFile[foundFile]; parts: NameParts _ GetNamePartsFromFullPathName[moduleName]; IF foundFile # foundPossibleFile THEN ERROR; module.module _ foundModule; module.whole _ foundDotO; module.possiblePrincipalDirectories _ AddAName[parts.principalDirectory, module.possiblePrincipalDirectories]; module.moduleFailed _ FALSE; SystemInterface.ShowReport[Rope.Cat[" found ", PFS.RopeFromPath[moduleName]], $normal]; END; END; END; RETURN[module.module]; END; GetMob: PROC[module: CedarModule] RETURNS[MA.MobCookie] = BEGIN modules: CedarModuleSet _ module.moduleSet; IF module.mobStamp = NIL AND module.sourceStamp = NIL THEN ERROR; IF module.mob = NIL AND NOT (module.mobFailed AND BasicTime.Period[module.failureTime, modules.flushTime] < 0) THEN BEGIN otherModule: CedarModule; base: RopeParts.RopePart _ emptyRopePart; mobKey, srcKey: RefTab.Key; IF module.mobStamp#NIL THEN { mobKey _ CreateVSKey[module.mobStamp^, emptyRopePart]; otherModule _ NARROW[RefTab.Fetch[modules.vsHash.table, mobKey].val]; mobKey _ mobKey}; IF otherModule=NIL AND module.sourceStamp#NIL THEN { nameStems: LIST OF PATH _ IF module.possibleNameStems # NIL THEN module.possibleNameStems ELSE module.originalPossibleNameStems; baseComponent: PFSNames.Component; FOR stems: LIST OF PATH _ nameStems, stems.rest WHILE stems#NIL AND otherModule=NIL DO baseComponent _ PFSNames.ShortName[stems.first]; base _ [baseComponent.name.base, baseComponent.name.start, baseComponent.name.len]; srcKey _ CreateVSKey[module.sourceStamp^, base]; otherModule _ NARROW[RefTab.Fetch[modules.vsHash.table, srcKey].val]; ENDLOOP; }; IF otherModule # NIL AND otherModule # module THEN -- good, lets combine info BEGIN -- we must produce a single module, while checking for inconsistencies incompatible: BOOLEAN _ FALSE; -- tentative IF module.moduleSet # otherModule.moduleSet THEN ERROR; IF module.mobStamp = NIL THEN module.mobStamp _ otherModule.mobStamp; IF otherModule.mobStamp = NIL THEN otherModule.mobStamp _ module.mobStamp; IF module.mobStamp # NIL AND module.mobStamp^ # otherModule.mobStamp^ THEN ERROR; IF module.sourceStamp = NIL THEN module.sourceStamp _ otherModule.sourceStamp; IF otherModule.sourceStamp = NIL THEN otherModule.sourceStamp _ module.sourceStamp; IF module.sourceStamp # NIL AND module.sourceStamp^ # otherModule.sourceStamp^ THEN ERROR; FOR ppds: LIST OF PATH _ otherModule.possiblePrincipalDirectories, ppds.rest WHILE ppds # NIL DO module.possiblePrincipalDirectories _ AddAName[ppds.first, module.possiblePrincipalDirectories]; ENDLOOP; FOR ppds: LIST OF PATH _ module.possiblePrincipalDirectories, ppds.rest WHILE ppds # NIL DO otherModule.possiblePrincipalDirectories _ AddAName[ppds.first, otherModule.possiblePrincipalDirectories]; ENDLOOP; FOR pns: LIST OF PATH _ otherModule.possibleNameStems, pns.rest WHILE pns # NIL DO module.possibleNameStems _ AddAName[pns.first, module.possibleNameStems]; ENDLOOP; FOR pns: LIST OF PATH _ module.possibleNameStems, pns.rest WHILE pns # NIL DO otherModule.possibleNameStems _ AddAName[pns.first, otherModule.possibleNameStems]; ENDLOOP; IF BasicTime.Period[module.failureTime, otherModule.failureTime] > 0 THEN otherModule.failureTime _ module.failureTime ELSE module.failureTime _ otherModule.failureTime; -- (earliest failure time to both) IF NOT module.mesaSourceFailed OR NOT otherModule.mesaSourceFailed THEN module.mesaSourceFailed _ otherModule.mesaSourceFailed _ FALSE; IF NOT module.mobFileFailed OR NOT otherModule.mobFileFailed THEN module.mobFileFailed _ otherModule.mobFileFailed _ FALSE; IF NOT module.mobFailed OR NOT otherModule.mobFailed THEN module.mobFailed _ otherModule.mobFailed _ FALSE; IF NOT module.cSourceFailed OR NOT otherModule.cSourceFailed THEN module.cSourceFailed _ otherModule.cSourceFailed _ FALSE; IF NOT module.jmpiFailed OR NOT otherModule.jmpiFailed THEN module.jmpiFailed _ otherModule.jmpiFailed _ FALSE; IF NOT module.moduleFailed OR NOT otherModule.moduleFailed THEN module.moduleFailed _ otherModule.moduleFailed _ FALSE; IF NOT module.wholeFailed OR NOT otherModule.wholeFailed THEN module.wholeFailed _ otherModule.wholeFailed _ FALSE; IF module.mesaSource # NIL AND otherModule.mesaSource # NIL THEN incompatible _ module.mesaSource # otherModule.mesaSource; IF module.mesaSource = NIL THEN module.mesaSource _ otherModule.mesaSource; IF otherModule.mesaSource = NIL THEN otherModule.mesaSource _ module.mesaSource; IF module.jmpi # NIL AND otherModule.jmpi # NIL THEN incompatible _ module.jmpi # otherModule.jmpi; IF module.jmpi = NIL THEN module.jmpi _ otherModule.jmpi; IF otherModule.jmpi = NIL THEN otherModule.jmpi _ module.jmpi; IF module.mobFile # NIL AND otherModule.mobFile # NIL THEN incompatible _ module.mobFile # otherModule.mobFile; IF module.mobFile = NIL THEN module.mobFile _ otherModule.mobFile; IF otherModule.mobFile = NIL THEN otherModule.mobFile _ module.mobFile; IF module.mob # NIL AND otherModule.mob # NIL THEN incompatible _ module.mob # otherModule.mob; IF module.mob = NIL THEN module.mob _ otherModule.mob; IF otherModule.mob = NIL THEN otherModule.mob _ module.mob; IF module.cInfo # NIL AND otherModule.cInfo # NIL THEN incompatible _ module.cInfo # otherModule.cInfo; IF module.cInfo = NIL THEN module.cInfo _ otherModule.cInfo; IF otherModule.cInfo = NIL THEN otherModule.cInfo _ module.cInfo; IF module.module # NIL AND otherModule.module # NIL THEN incompatible _ module.module # otherModule.module; IF module.module = NIL THEN module.module _ otherModule.module; IF otherModule.module = NIL THEN otherModule.module _ module.module; IF module.whole # NIL AND otherModule.whole # NIL THEN incompatible _ module.whole # otherModule.whole; IF module.whole = NIL THEN module.whole _ otherModule.whole; IF otherModule.whole = NIL THEN otherModule.whole _ module.whole; IF NOT incompatible THEN module^ _ otherModule^; END; IF module.mob = NIL THEN -- we still have to find the mob BEGIN nameStems: LIST OF PATH _ IF module.possibleNameStems # NIL THEN module.possibleNameStems ELSE module.originalPossibleNameStems; IF nameStems # NIL THEN BEGIN foundMob: MA.MobCookie _ NIL; -- tentative foundPossibleFile: CirioFile _ NIL; -- tentative foundCreateTime: BasicTime.GMT _ BasicTime.earliestGMT; -- tentative TryOneFile: PROC[info: SystemInterface.CirioFileInfo] RETURNS[thisIsIt: BOOLEAN _ FALSE] = BEGIN possibleFile: CirioFile _ SystemInterface.GetCirioFile[modules.fileSet, info.fullName, info.uniqueID]; IF module.mobStamp = NIL AND module.sourceStamp = NIL THEN BEGIN mob: MA.MobCookie _ MA.CreateMobCookie[possibleFile ! MobAccess.MobError => { SystemInterface.ShowReport[IO.PutFR["\tbad mob %g", [rope[PFS.RopeFromPath[info.fullName]]] ], IF debugSearch THEN $urgent ELSE $debug]; GOTO failure}]; SystemInterface.ShowReport[Rope.Cat["accepting ", PFS.RopeFromPath[info.fullName], " without any version checking"], $normal]; IF foundPossibleFile = NIL OR (BasicTime.Period[foundCreateTime, info.uniqueID.egmt.time] > 0) THEN BEGIN foundMob _ mob; foundPossibleFile _ possibleFile; foundCreateTime _ info.uniqueID.egmt.time; RETURN[TRUE] END; RETURN[FALSE] END ELSE BEGIN mob: MA.MobCookie _ MA.CreateMobCookie[possibleFile ! MobAccess.MobError => { SystemInterface.ShowReport[IO.PutFR["\tbad mob %g", [rope[PFS.RopeFromPath[info.fullName]]] ], IF debugSearch THEN $urgent ELSE $debug]; GOTO failure}]; mobStamp: MobDefs.VersionStamp _ MA.ReadMobVersionStamp[mob]; mobSourceStamp: MobDefs.VersionStamp _ MA.ReadSourceVersionStamp[mob]; ok: BOOLEAN _ FALSE; -- tentative; IF module.mobStamp # NIL AND module.mobStamp^ = mobStamp THEN ok _ TRUE; IF module.sourceStamp # NIL AND module.sourceStamp^ = mobSourceStamp THEN ok _ TRUE; ok _ ok AND (foundPossibleFile = NIL OR (BasicTime.Period[foundCreateTime, info.uniqueID.egmt.time] > 0)); IF debugSearch THEN SystemInterface.ShowReport[IO.PutFLR["\t?name=%g,\n\tmobStamp=%08x%08x, sourceStamp=%08x%08x,\n\tcreate=%g, ok=%g.", LIST[ [rope[PFS.RopeFromPath[info.fullName]]], [cardinal[mobStamp[0]]], [cardinal[mobStamp[1]]], [cardinal[mobSourceStamp[0]]], [cardinal[mobSourceStamp[1]]], [time[info.uniqueID.egmt.time]], [boolean[ok]] ]], $urgent]; IF ok THEN BEGIN foundMob _ mob; foundPossibleFile _ possibleFile; foundCreateTime _ info.uniqueID.egmt.time; RETURN[TRUE]; END; RETURN[FALSE]; END; EXITS failure => RETURN[FALSE]; END; TryOneDir: PROC[dir: PATH] = BEGIN FOR stems: LIST OF PATH _ nameStems, stems.rest WHILE stems # NIL AND foundPossibleFile = NIL DO mobFileNamePattern: PATH _ PFS.PathFromRope[Rope.Cat[PFS.RopeFromPath[stems.first], ".mob", "*"]]; mobFileNamePattern _ mobFileNamePattern.ExpandName[dir]; IF debugSearch THEN SystemInterface.ShowReport[IO.PutFR["\tSearching file pattern %g.", [rope[PFS.RopeFromPath[mobFileNamePattern]]] ], $urgent]; [] _ SystemInterface.GenCirioFilesForInfo[modules.fileSet, mobFileNamePattern, TryOneFile]; ENDLOOP; END; ShowSearchReport["mob", module]; IF debugSearch THEN SystemInterface.ShowReport[IO.PutFR["\twith mob stamp %g and source stamp %g.", [rope[DescribeRefStamp[module.mobStamp]]], [rope[DescribeRefStamp[module.sourceStamp]]] ], $urgent]; FOR dirs: LIST OF PATH _ modules.searchPaths, dirs.rest WHILE dirs # NIL AND foundPossibleFile = NIL DO IF debugSearch THEN SystemInterface.ShowReport[IO.PutFR["\tSearching search dir %g.", [rope[PFS.RopeFromPath[dirs.first]]] ], $urgent]; TryOneDir[dirs.first]; ENDLOOP; IF foundPossibleFile = NIL THEN { IF debugSearch THEN SystemInterface.ShowReport["\tSearching version maps.", $urgent]; foundPossibleFile _ SystemInterface.GenVersionMapFilesForInfo[modules.fileSet, $Intermediate, MobDefs.NullVersion, nameStems, LIST[".mob"], TRUE, TryOneFile]}; FOR dirs: LIST OF PATH _ module.possiblePrincipalDirectories, dirs.rest WHILE dirs # NIL AND foundPossibleFile = NIL DO IF debugSearch THEN SystemInterface.ShowReport[IO.PutFR["\tSearching possible principle dir %g.", [rope[PFS.RopeFromPath[dirs.first]]] ], $urgent]; TryOneDir[dirs.first]; ENDLOOP; FOR dirs: LIST OF PATH _ modules.otherDirectories, dirs.rest WHILE dirs # NIL AND foundPossibleFile = NIL DO IF debugSearch THEN SystemInterface.ShowReport[IO.PutFR["\tSearching other dir %g.", [rope[PFS.RopeFromPath[dirs.first]]] ], $urgent]; TryOneDir[dirs.first]; ENDLOOP; IF foundPossibleFile = NIL THEN BEGIN module.mobFailed _ TRUE; module.failureTime _ BasicTime.Now[]; ShowFailureReport["mob", module]; END ELSE BEGIN mobName: PATH _ SystemInterface.GetNameOfFile[foundPossibleFile]; parts: NameParts _ GetNamePartsFromFullPathName[mobName]; module.mob _ foundMob; module.possiblePrincipalDirectories _ AddAName[parts.principalDirectory, module.possiblePrincipalDirectories]; module.mobStamp _ NEW[MobDefs.VersionStamp _ MA.ReadMobVersionStamp[module.mob]]; IF module.sourceStamp = NIL THEN { module.sourceStamp _ NEW[MobDefs.VersionStamp _ MA.ReadSourceVersionStamp[module.mob]]; base _ RopeParts.InlineMake[parts.nameStem]; srcKey _ CreateVSKey[module.sourceStamp^, base]; [] _ RefTab.Store[modules.vsHash.table, srcKey, module]; }; IF module.possibleNameStems = NIL THEN module.possibleNameStems _ LIST[PFS.PathFromRope[parts.nameStem]]; module.mobFailed _ FALSE; mobKey _ CreateVSKey[module.mobStamp^, emptyRopePart]; IF RefTab.Fetch[modules.vsHash.table, mobKey].val = NIL THEN {IF NOT RefTab.Store[modules.vsHash.table, mobKey, module] THEN ERROR}; SystemInterface.ShowReport[Rope.Cat[" found ", PFS.RopeFromPath[mobName]], $normal]; END; END; END; END; RETURN[module.mob]; END; GetDotO: PUBLIC PROC [targetData: REF ANY, dotOPathRope, dotORope: Rope.ROPE, dotOId: CARD, getDotOId: PROC [ObjF.Parsed] RETURNS [CARD]] RETURNS [ObjF.Parsed] = { modules: CedarModuleSet _ NARROW[targetData]; RETURN [GetDotOInner[modules, dotOPathRope, dotORope, dotOId, getDotOId]]; }; GetDotOInner: PROC [moduleSet: CedarModuleSet, dotOPathRope, dotORope: Rope.ROPE, dotOId: CARD, getDotOId: PROC [ObjF.Parsed] RETURNS [CARD]] RETURNS [ObjF.Parsed] = { foundFile: CirioFile _ NIL; -- tentative foundDotO: ObjF.Parsed _ NIL; -- tentative foundPossibleFile: CirioFile _ NIL; -- tentative TryOneFile: PROC [info: SystemInterface.CirioFileInfo] RETURNS [thisIsIt: BOOLEAN _ FALSE] = { possibleFile: CirioFile _ SystemInterface.GetCirioFile[moduleSet.fileSet, info.fullName, info.uniqueID]; possibleDotO: ObjF.Parsed _ ObjF.CreateParsed[possibleFile]; IF getDotOId[possibleDotO] = dotOId THEN { foundDotO _ possibleDotO; foundPossibleFile _ possibleFile; RETURN[TRUE] }; RETURN[FALSE]; }; TryOneDir: PROC [dir: PATH] = { rdir: Rope.ROPE _ PFS.RopeFromPath[PFSNames.EnsureDirectory[dir]]; patterns: LIST OF PATH _ LIST[ PFS.PathFromRope[Rope.Cat[rdir, dotORope]], PFS.PathFromRope[Rope.Cat[rdir, "debug/", dotORope]], PFS.PathFromRope[Rope.Cat[rdir, "sun4-debug/", dotORope, "*"]], PFS.PathFromRope[Rope.Cat[rdir, "sun4/", dotORope, "*"]] ]; FOR ps: LIST OF PATH _ patterns, ps.rest WHILE ps # NIL AND foundFile = NIL DO foundFile _ SystemInterface.GenCirioFilesForInfo[moduleSet.fileSet, ps.first, TryOneFile]; ENDLOOP; }; SystemInterface.ShowReport[Rope.Concat["searching for ", dotORope], $normal]; FOR dirs: LIST OF PATH _ moduleSet.searchPaths, dirs.rest WHILE dirs # NIL AND foundFile = NIL DO TryOneDir[dirs.first]; ENDLOOP; IF foundFile = NIL THEN [] _ SystemInterface.GenVersionMapFilesForInfo[moduleSet.fileSet, $Executable, MobDefs.NullVersion, LIST[PFS.PathFromRope[dotORope]], NIL, TRUE, TryOneFile]; FOR dirs: LIST OF PATH _ moduleSet.otherDirectories, dirs.rest WHILE dirs # NIL AND foundFile = NIL DO TryOneDir[dirs.first]; ENDLOOP; IF foundFile = NIL THEN SystemInterface.ShowReport[Rope.Cat["unable to find module for ", dotORope], $normal] ELSE { moduleName: PATH _ SystemInterface.GetNameOfFile[foundFile]; IF foundFile # foundPossibleFile THEN ERROR; SystemInterface.ShowReport[Rope.Cat[" found ", PFS.RopeFromPath[moduleName]], $normal]; }; RETURN [foundDotO]; }; FallBackFindModule: PROC[whole: ObjF.Parsed, relativePC: CARD] RETURNS[ObjF.Module] = BEGIN RETURN[ObjF.ModuleFromParsedAndPC[whole, [[0,""], relativePC]]] END; VSHashTable: TYPE = REF VSHashTableBody; VSHashTableBody: TYPE = RECORD[table: RefTab.Ref]; VSHashEntryKey: TYPE = RECORD[versionStamp: MobDefs.VersionStamp, base: RopeParts.RopePart]; emptyRopePart: RopeParts.RopePart _ [base: "", start: 0, len: 0]; CreateVSHashTable: PROC RETURNS[VSHashTable] = {RETURN[NEW[VSHashTableBody _ [table: RefTab.Create[equal: VSKeyEqualProc, hash: VSKeyHashProc]]]]}; CreateVSKey: PROC[stamp: MobDefs.VersionStamp, base: RopeParts.RopePart] RETURNS[RefTab.Key] = {RETURN[NEW[VSHashEntryKey _ [versionStamp: stamp, base: base]]]}; VSKeyEqualProc: PROC[key1, key2: RefTab.Key] RETURNS[BOOL] = BEGIN vs1: REF VSHashEntryKey _ NARROW[key1]; vs2: REF VSHashEntryKey _ NARROW[key2]; RETURN[(vs1^.versionStamp = vs2^.versionStamp) AND (RopeParts.Equal[vs1^.base, vs2^.base])]; END; VSKeyHashProc: PROC[key: RefTab.Key] RETURNS[CARDINAL] = BEGIN vs: REF VSHashEntryKey _ NARROW[key]; word0: PBasics.LongNumber _ LOOPHOLE[vs^.versionStamp[0]]; word1: PBasics.LongNumber _ LOOPHOLE[vs^.versionStamp[1]]; RETURN[RopeParts.Hash[base: vs^.base, seed: PBasics.BITXOR[PBasics.BITXOR[word0.lo, word0.hi], PBasics.BITXOR[word1.lo, word1.hi]]]]; END; GetNamePartsFromFullPathName: PUBLIC PROC [fullPathName: PATH] RETURNS [NameParts] = { principalDirectory: PATH; sun4: PATH _ PFSNames.EmptyPath; -- tentative c2c: PATH _ PFSNames.EmptyPath; -- tentative shortComp: PFSNames.Component _ fullPathName.ShortName; shortName: ROPE _ shortComp.ComponentRope; directoryPath: PATH _ fullPathName.Directory; IF directoryPath # PFSNames.EmptyPath AND directoryPath # NIL AND directoryPath.ComponentCount # 0 THEN BEGIN lastDirectory: PFSNames.Component _ directoryPath.Fetch[directoryPath.ComponentCount - 1]; lastDirectoryRope: Rope.ROPE _ lastDirectory.ComponentRope; IF Rope.Equal["sun4", lastDirectoryRope] OR Rope.Equal["sun4-o3", lastDirectoryRope] OR Rope.Equal["sun4o3", lastDirectoryRope, FALSE] THEN directoryPath _ directoryPath.Parent; END; principalDirectory _ directoryPath; {lastDot: INT _ Rope.FindBackward[shortName, "."]; IF lastDot > -1 AND lastDot+1 < Rope.Length[shortName] AND Rope.Fetch[shortName, lastDot+1] = '~ THEN -- remove the version shortName _ Rope.Substr[shortName, 0, lastDot]; }; {lastDot: INT _ Rope.FindBackward[shortName, "."]; secondToLastDot: INT _ IF lastDot <= 0 THEN -1 ELSE Rope.FindBackward[shortName, ".", lastDot-1]; IF secondToLastDot > -1 AND Rope.Equal["c2c", Rope.Substr[shortName, secondToLastDot+1, lastDot-1-secondToLastDot]] THEN { shortName _ Rope.Replace[shortName, secondToLastDot, 4, ""]; c2c _ PFS.PathFromRope[".c2c"]}; }; {lastDot: INT _ Rope.FindBackward[shortName, "."]; IF lastDot > -1 THEN shortName _ Rope.Substr[shortName, 0, lastDot]; }; RETURN[[ principalDirectory, shortName ]]; }; CFileInfo: TYPE = REF CFileInfoBody; CFileInfoBody: TYPE = RECORD[ file: CirioFile, sourcePosSeq: SourcePosSeq, lineNumSeq: LineNumSeq, versionStamp: Rope.ROPE]; SourcePosSeq: TYPE = REF SourcePosSeqBody; SourcePosSeqBody: TYPE = RECORD[ SEQUENCE nSourceMacros: CARDINAL OF SourcePosMacro]; LineNumSeq: TYPE = REF LineNumSeqBody; LineNumSeqBody: TYPE = RECORD[ SEQUENCE nSourceMacros: CARDINAL OF SourcePosMacro]; SourcePosMacro: TYPE = RECORD[pos: CARD, nChars: CARD, lineNum: CARD]; LookupMesaSourcePos: PROC[info: CFileInfo, pos: CARD] RETURNS[cLineNum: CARD] = BEGIN FOR I: CARDINAL DECREASING IN [0..info.sourcePosSeq.nSourceMacros) DO IF info.sourcePosSeq[I].pos <= pos THEN RETURN[info.sourcePosSeq[I].lineNum] ENDLOOP; IF info.sourcePosSeq.nSourceMacros = 0 THEN RETURN[0]; RETURN[info.sourcePosSeq[0].lineNum] END; LookupCLineNum: PROC[info: CFileInfo, cLineNum: CARD] RETURNS[pos: CARD] = BEGIN FOR I: CARDINAL DECREASING IN [0..info.lineNumSeq.nSourceMacros) DO IF info.lineNumSeq[I].lineNum <= cLineNum THEN RETURN[info.lineNumSeq[I].pos] ENDLOOP; IF info.lineNumSeq.nSourceMacros = 0 THEN RETURN[0]; RETURN[info.lineNumSeq[0].pos] END; CompareSourceMacrosByPos: PROC[ref1: REF ANY, ref2: REF ANY] RETURNS [Basics.Comparison] = BEGIN sm1: REF SourcePosMacro _ NARROW[ref1]; sm2: REF SourcePosMacro _ NARROW[ref2]; IF sm1.pos < sm2.pos THEN RETURN[less]; IF sm1.pos > sm2.pos THEN RETURN[greater]; IF sm1.lineNum < sm2.lineNum THEN RETURN[less]; IF sm1.lineNum > sm2.lineNum THEN RETURN[greater]; RETURN[equal]; END; CompareSourceMacrosByCLineNum: PROC[ref1: REF ANY, ref2: REF ANY] RETURNS [Basics.Comparison] = BEGIN sm1: REF SourcePosMacro _ NARROW[ref1]; sm2: REF SourcePosMacro _ NARROW[ref2]; IF sm1.lineNum < sm2.lineNum THEN RETURN[less]; IF sm1.lineNum > sm2.lineNum THEN RETURN[greater]; IF sm1.pos < sm2.pos THEN RETURN[less]; IF sm1.pos > sm2.pos THEN RETURN[greater]; RETURN[equal]; END; ScanCFileForVersionStamp: PROC[cFile: CirioFile] RETURNS[versionStamp: Rope.ROPE _ NIL] = BEGIN source: IO.STREAM _ SystemInterface.GetStreamForFile[cFile]; BEGIN ENABLE UNWIND => SystemInterface.ReleaseStreamForFile[cFile, source]; buffer: REF TEXT _ NIL; smKey: Rope.ROPE _ "SOURCE("; smKeyLength: CARD _ Rope.Length[smKey]; vsKey: Rope.ROPE _ Rope.Cat["static char versionStamp[] = \"@", "(#)", "mob_version ["]; vsKeyLength: CARD _ Rope.Length[vsKey]; FOR ln: CARD _ 1, ln+1 WHILE NOT IO.EndOf[source] DO buffer _ IO.GetLine[source, buffer]; IF buffer[0] = 's THEN -- possible version stamp hit BEGIN line: Rope.ROPE _ Rope.FromRefText[buffer]; IF Rope.Equal[vsKey, Rope.Substr[line, 0, vsKeyLength]] THEN -- we have a hit BEGIN quote1: INT _ Rope.Index[line, 0, "\""]; quote2: INT _ Rope.Index[line, quote1+1, "\""]; IF quote2 = Rope.Length[line]-2 THEN -- a final consistency check versionStamp _ Rope.Substr[line, quote1+1, quote2-quote1-1]; END END; IF versionStamp # NIL THEN EXIT; ENDLOOP; END; SystemInterface.ReleaseStreamForFile[cFile, source]; END; CreateCFileInfo: PROC[cFile: CirioFile] RETURNS[CFileInfo] = BEGIN list1: LIST OF REF ANY _ NIL; list2: LIST OF REF ANY _ NIL; nMacros: INTEGER _ 0; sortedList: LIST OF REF ANY _ NIL; sourcePosSeq: SourcePosSeq; lineNumSeq: LineNumSeq; versionStamp: Rope.ROPE _ NIL; SeeOnePosition: PROC[sp: CARD, nChars: CARD, ln: CARD] = BEGIN list1 _ CONS[NEW[SourcePosMacro_[sp, nChars, ln]], list1]; list2 _ CONS[NEW[SourcePosMacro_[sp, nChars, ln]], list2]; nMacros _ nMacros+1; END; versionStamp _ GenMesaSourcePositionMacros[cFile, SeeOnePosition]; sortedList _ List.Sort[list1, CompareSourceMacrosByPos]; sourcePosSeq _ NEW[SourcePosSeqBody[nMacros]]; FOR I: INTEGER IN [0..nMacros) DO macro: REF SourcePosMacro _ NARROW[sortedList.first]; sourcePosSeq[I] _ macro^; sortedList _ sortedList.rest; ENDLOOP; sortedList _ List.Sort[list2, CompareSourceMacrosByCLineNum]; lineNumSeq _ NEW[LineNumSeqBody[nMacros]]; FOR I: INTEGER IN [0..nMacros) DO macro: REF SourcePosMacro _ NARROW[sortedList.first]; lineNumSeq[I] _ macro^; sortedList _ sortedList.rest; ENDLOOP; RETURN[NEW[CFileInfoBody_[cFile, sourcePosSeq, lineNumSeq, versionStamp]]] END; GetCFileVersionStamp: PROC[info: CFileInfo] RETURNS[Rope.ROPE] = {RETURN[info.versionStamp]}; GenMesaSourcePositionMacros: PROC[cFile: CirioFile, SeeOnePosition: PROC[sp: CARD, nChars: CARD, ln: CARD]] RETURNS[versionStamp: Rope.ROPE _ NIL] = BEGIN source: IO.STREAM _ SystemInterface.GetStreamForFile[cFile]; BEGIN ENABLE UNWIND => SystemInterface.ReleaseStreamForFile[cFile, source]; buffer: REF TEXT _ NIL; smKey: Rope.ROPE _ "SOURCE("; smKeyLength: CARD _ Rope.Length[smKey]; vsKey: Rope.ROPE _ Rope.Cat["static char versionStamp[] = \"@", "(#)", "mob_version ["]; vsKeyLength: CARD _ Rope.Length[vsKey]; FOR ln: CARD _ 1, ln+1 WHILE NOT IO.EndOf[source] DO buffer _ IO.GetLine[source, buffer]; IF buffer[0] = 'S THEN -- possible SourcePositionMacro hit BEGIN line: Rope.ROPE _ Rope.FromRefText[buffer]; IF Rope.Equal[smKey, Rope.Substr[line, 0, smKeyLength]] THEN -- we have a hit BEGIN x: CARD _ smKeyLength; sp: CARD _ 0; nChars: CARD _ 0; DO IF buffer[x] = ', THEN EXIT; sp _ sp*10 + ORD[buffer[x]] - ORD['0]; x _ x+1; ENDLOOP; WHILE buffer[x] = ', OR buffer[x] = ' DO x _ x+1 ENDLOOP; DO IF buffer[x] = ') THEN EXIT; nChars _ nChars*10 + ORD[buffer[x]] - ORD['0]; x _ x+1; ENDLOOP; SeeOnePosition[sp, nChars, ln]; END; END; IF buffer[0] = 's THEN -- possible version stamp hit BEGIN line: Rope.ROPE _ Rope.FromRefText[buffer]; IF Rope.Equal[vsKey, Rope.Substr[line, 0, vsKeyLength]] THEN -- we have a hit BEGIN quote1: INT _ Rope.Index[line, 0, "\""]; quote2: INT _ Rope.Index[line, quote1+1, "\""]; IF quote2 = Rope.Length[line]-2 THEN -- a final consistency check versionStamp _ Rope.Substr[line, quote1+1, quote2-quote1-1]; END END; ENDLOOP; END; SystemInterface.ReleaseStreamForFile[cFile, source]; END; AddAName: PROC[newName: PATH, names: LIST OF PATH] RETURNS[LIST OF PATH] = BEGIN FOR nms: LIST OF PATH _ names, nms.rest WHILE nms # NIL DO IF nms.first.Equal[newName] THEN RETURN[names]; ENDLOOP; RETURN[CONS[newName, names]]; END; ShowSearchReport: PROC[target: Rope.ROPE, module: CedarModule] = BEGIN names: Rope.ROPE _ NIL; FOR stems: LIST OF PATH _ IF module.possibleNameStems # NIL THEN module.possibleNameStems ELSE module.originalPossibleNameStems, stems.rest WHILE stems # NIL DO IF names # NIL THEN names _ Rope.Cat[names, " or "]; names _ Rope.Cat[names, PFS.RopeFromPath[stems.first]]; ENDLOOP; SystemInterface.ShowReport[Rope.Cat["searching for ", target, " for ", names], $normal]; END; ShowFailureReport: PROC[target: Rope.ROPE, module: CedarModule] = BEGIN names: Rope.ROPE _ NIL; FOR stems: LIST OF PATH _ IF module.possibleNameStems # NIL THEN module.possibleNameStems ELSE module.originalPossibleNameStems, stems.rest WHILE stems # NIL DO IF names # NIL THEN names _ Rope.Cat[names, " or"]; names _ Rope.Cat[names, " ", PFS.RopeFromPath[stems.first]]; ENDLOOP; SystemInterface.ShowReport[Rope.Cat["unable to find ", target, " for ", names], $normal]; END; RecoveredVersionStamp: TYPE = RECORD[ mobStamp: MobDefs.VersionStamp, stem: PATH]; ConvertDotOFormatVersionStampToMobFormat: PROC[wholeVersionStamp: Rope.ROPE] RETURNS[REF RecoveredVersionStamp] = BEGIN ENABLE BEGIN RuntimeError.BoundsFault => GOTO fails; Convert.Error => GOTO fails; CantConvert => GOTO fails; END; expectedPreamble: Rope.ROPE _ Rope.Cat["@", "(#)", "mob_version ["]; stemStart: INT _ Rope.Index[wholeVersionStamp, 0, "] "]+2; stampLength: INT _ Rope.Length[wholeVersionStamp]; preambleLength: INT _ Rope.Length[expectedPreamble]; stemLength: INT _ Rope.Length[wholeVersionStamp]-stemStart; stem: Rope.ROPE _ IF stemLength > 0 THEN Rope.Substr[wholeVersionStamp, stemStart, stemLength] ELSE NIL; preamble: Rope.ROPE _ Rope.Substr[wholeVersionStamp, 0, preambleLength]; digits: Rope.ROPE _ Rope.Substr[wholeVersionStamp, preambleLength, stampLength-preambleLength-stemLength-2]; comma: INT _ Rope.Find[digits, ","]; digits1: Rope.ROPE _ Rope.Substr[digits, 0, comma]; digits2: Rope.ROPE _ Rope.Substr[digits, comma+1, Rope.Length[digits]-comma-1]; stamp: MobDefs.VersionStamp _ [Convert.CardFromRope[digits1], Convert.CardFromRope[digits2]]; IF NOT Rope.Equal[preamble, expectedPreamble] THEN RaiseCantConvert[]; IF stem = NIL THEN RaiseCantConvert[]; RETURN[NEW[RecoveredVersionStamp _ [stamp, PFS.PathFromRope[stem]]]]; EXITS fails => RETURN[NIL]; END; CantConvert: ERROR = CODE; RaiseCantConvert: PROC = {CantConvert[]}; DescribeRefStamp: PROC [rs: REF MobDefs.VersionStamp] RETURNS [Rope.ROPE] ~ {IF rs=NIL THEN RETURN ["NIL"] ELSE RETURN IO.PutFR["%08x%08x", [cardinal[rs[0]]], [cardinal[rs[1]]] ]}; TestGenMesaSourcePositionMacros: Commander.CommandProc = BEGIN args: CommandTool.ArgumentVector _ CommandTool.Parse[cmd]; fileName: PATH _ PFS.PathFromRope[args[1]]; fileSet: SystemInterface.FileSet _ SystemInterface.CreateFileSet[]; BEGIN ENABLE UNWIND => SystemInterface.CloseFileSet[fileSet]; file: CirioFile _ SystemInterface.GetCirioFile[fileSet, fileName]; versionStamp: Rope.ROPE _ NIL; SeeOnePosition: PROC[sp: CARD, nChars: CARD, ln: CARD] = {IO.PutF[cmd.out, "sp: %g..%g, ln: %g\N", IO.card[sp], IO.card[sp+nChars], IO.card[ln]]}; versionStamp _ GenMesaSourcePositionMacros[file, SeeOnePosition]; IO.PutF[cmd.out, "\NversionStamp = %g\N", IO.rope[versionStamp]]; END; SystemInterface.CloseFileSet[fileSet]; END; TestCreateCFileInfo: Commander.CommandProc = BEGIN args: CommandTool.ArgumentVector _ CommandTool.Parse[cmd]; fileName: PATH _ PFS.PathFromRope[args[1]]; fileSet: SystemInterface.FileSet _ SystemInterface.CreateFileSet[]; BEGIN ENABLE UNWIND => SystemInterface.CloseFileSet[fileSet]; file: SystemInterface.CirioFile _ SystemInterface.GetCirioFile[fileSet, fileName]; info: CFileInfo _ CreateCFileInfo[file]; ss: SourcePosSeq _ info.sourcePosSeq; lns: LineNumSeq _ info.lineNumSeq; IO.PutF[cmd.out, "versionStamp: %g\N", IO.rope[info.versionStamp]]; IO.PutF[cmd.out, "nSourcePosMacros = %g\n", IO.card[ss.nSourceMacros]]; FOR I: CARD IN [0..ss.nSourceMacros) DO IO.PutF[cmd.out, "\T%g..%g CLine: %g\N", IO.card[ss[I].pos], IO.card[ss[I].pos+ss[I].nChars], IO.card[ss[I].lineNum]]; ENDLOOP; IO.PutF[cmd.out, "\N"]; FOR I: CARD IN [0..lns.nSourceMacros) DO IO.PutF[cmd.out, "\T CLine: %g %g..%g\N", IO.card[lns[I].lineNum], IO.card[lns[I].pos], IO.card[lns[I].pos+lns[I].nChars]]; ENDLOOP; END; SystemInterface.CloseFileSet[fileSet]; END; TestSetBreak: Commander.CommandProc = BEGIN args: CommandTool.ArgumentVector _ CommandTool.Parse[cmd]; cFileName: PATH _ PFS.PathFromRope[args[1]]; fileSet: SystemInterface.FileSet _ SystemInterface.CreateFileSet[]; BEGIN ENABLE UNWIND => SystemInterface.CloseFileSet[fileSet]; file: SystemInterface.CirioFile _ SystemInterface.GetCirioFile[fileSet, cFileName]; info: CFileInfo _ CreateCFileInfo[file]; pos: SourceFileOpsExtras.Position _ SourceFileOpsExtras.noPosition; cLineNum: CARD; newMesaCharIdx: CARD; IO.PutF[cmd.out, "versionStamp: %g\N", IO.rope[info.versionStamp]]; pos _ SourceFileOpsExtras.FullGetSelection[primary].pos; IO.PutF[cmd.out, "%g in %g selected\N", IO.card[pos.index[char].first], IO.rope[PFS.RopeFromPath[pos.fileName]]]; cLineNum _ LookupMesaSourcePos[info, pos.index[char].first]; IO.PutF[cmd.out, "pointing to line %g in %g\N", IO.card[cLineNum], IO.rope[PFS.RopeFromPath[cFileName]]]; newMesaCharIdx _ LookupCLineNum[info, cLineNum]; IO.PutF[cmd.out, "pointing back to pos %g in %g\N", IO.card[newMesaCharIdx], IO.rope[PFS.RopeFromPath[pos.fileName]]]; SourceFileOpsExtras.FullOpenSource[desc: "Break set at ", pos: [fileName: pos.fileName, uniqueID: SourceFileOpsExtras.nullUniqueID, index: [char: [newMesaCharIdx] ] ], feedBack: cmd.out]; IO.PutF[cmd.out, "\N"]; END; SystemInterface.CloseFileSet[fileSet]; END; TestFromMesa: Commander.CommandProc = BEGIN args: CommandTool.ArgumentVector _ CommandTool.Parse[cmd]; mesaName: PATH _ PFS.PathFromRope[args[1]]; fileSet: SystemInterface.FileSet _ SystemInterface.CreateFileSet[]; BEGIN ENABLE BEGIN UNWIND => SystemInterface.CloseFileSet[fileSet]; SystemInterface.ShowReport => {ShowReportByLevel[cmd.out, msgText, priority]; RESUME}; END; modules: CedarModuleSet _ CreateCedarModuleSet[fileSet]; mesaFile: CirioFile _ SystemInterface.GetCirioFile[fileSet, mesaName]; module: CedarModule _ CreateCedarModuleFromMesa[modules, mesaFile]; [] _ GetParsed[module]; [] _ GetCFileInfo[module]; [] _ GetMesaFile[module]; [] _ GetJMPI[module]; [] _ GetMob[module]; [] _ GetModule[module]; END; SystemInterface.CloseFileSet[fileSet]; END; TestFromDotO: Commander.CommandProc = BEGIN args: CommandTool.ArgumentVector _ CommandTool.Parse[cmd]; wholeName: PATH _ PFS.PathFromRope[args[1]]; pc: CARD _ Convert.CardFromRope[args[2]]; fileSet: SystemInterface.FileSet _ SystemInterface.CreateFileSet[]; BEGIN ENABLE BEGIN UNWIND => SystemInterface.CloseFileSet[fileSet]; SystemInterface.ShowReport => {ShowReportByLevel[cmd.out, msgText, priority]; RESUME}; END; modules: CedarModuleSet _ CreateCedarModuleSet[fileSet]; wholeFile: CirioFile _ SystemInterface.GetCirioFile[fileSet, wholeName]; whole: ObjF.Parsed _ ObjF.CreateParsed[wholeFile]; embeddedModule: ObjF.Module _ FallBackFindModule[whole, pc]; module: CedarModule _ CreateCedarModuleFromModule[modules, whole, embeddedModule, LIST[wholeName]]; sourcePos: REF CedarSourcePosition _ ComputeCedarSourcePosition[module, [[0, ""], pc]]; IF module # NIL THEN { [] _ GetMesaFile[module]; [] _ GetCFileInfo[module]; [] _ GetMesaFile[module]; [] _ GetJMPI[module]; [] _ GetMob[module]; [] _ GetModule[module]; }; ShowIndentedRopes[GetRopesForSourcePosInfo[sourcePos], cmd.out, 5]; END; SystemInterface.CloseFileSet[fileSet]; END; ShowIndentedRopes: PROC[ropes: LIST OF Rope.ROPE, on: IO.STREAM, indent: CARD] = BEGIN FOR rps: LIST OF Rope.ROPE _ ropes, rps.rest WHILE rps # NIL DO FOR I: CARD IN [0..indent] DO IO.PutF[on, " "]; ENDLOOP; IO.PutF[on, "%g\N", IO.rope[rps.first]]; ENDLOOP; END; CrudeExp: Commander.CommandProc = BEGIN args: CommandTool.ArgumentVector _ CommandTool.Parse[cmd]; mesaName: PATH _ PFS.PathFromRope[args[1]]; mobName: PATH _ PFS.PathFromRope[args[2]]; fileSet: SystemInterface.FileSet _ SystemInterface.CreateFileSet[]; BEGIN ENABLE BEGIN UNWIND => SystemInterface.CloseFileSet[fileSet]; SystemInterface.ShowReport => {ShowReportByLevel[cmd.out, msgText, priority]; RESUME}; END; mesaFile: CirioFile _ SystemInterface.GetCirioFile[fileSet, mesaName]; mobFile: CirioFile _ SystemInterface.GetCirioFile[fileSet, mobName]; mob: MA.MobCookie _ MA.CreateMobCookie[mobFile]; mobVersion: MobDefs.VersionStamp _ MA.ReadMobVersionStamp[mob]; mobSourceVersion: MobDefs.VersionStamp _ MA.ReadSourceVersionStamp[mob]; possibleSourceVersion: MobDefs.VersionStamp _ MA.ComputeSourceVersionStamp[mesaFile]; ERROR -- for inspection END; END; NewTestSetBreak: Commander.CommandProc = BEGIN args: CommandTool.ArgumentVector _ CommandTool.Parse[cmd]; remoteName: Rope.ROPE _ args[1]; portNum: CARD _ Convert.CardFromRope[args[2]]; nub: CirioNubAccess.Handle _ CirioNubAccess.CreateRemoteNub[debuggee: remoteName, port: portNum, timeoutMsec: 10000]; fileSet: SystemInterface.FileSet _ SystemInterface.CreateFileSet[]; BEGIN ENABLE BEGIN UNWIND => {SystemInterface.CloseFileSet[fileSet]; CirioNubAccess.DestroyNub[nub]}; SystemInterface.ShowReport => {ShowReportByLevel[cmd.out, msgText, priority]; RESUME}; END; modules: CedarModuleSet _ CreateCedarModuleSet[fileSet]; loadState: LoadStateAccess.LoadStateHandle _ LoadStateAccess.CreateLoadStateHandle[remoteName, nub, fileSet]; pos: SourceFileOpsExtras.Position; pos _ SourceFileOpsExtras.FullGetSelection[].pos; IF pos.fileName # NIL THEN BEGIN mesaFileName: PATH ~ pos.fileName; mesaSourcePosition: INT ~ pos.index[char].first; mesaFile: CirioFile _ SystemInterface.GetCirioFile[fileSet, mesaFileName]; addr: REF CedarBreakAddress _ GetAbsAddressForBreak[modules, mesaFile, loadState, mesaSourcePosition]; ropes: LIST OF Rope.ROPE _ GetRopesForCedarBreakAddress[addr]; ShowIndentedRopes[ropes, cmd.out, 0]; IF addr # NIL THEN BEGIN basicInfo: REF LoadStateAccess.BasicPCInfo _ LoadStateAccess.GetBasicPCInfo[loadState, addr.absPC]; moreInfo: REF LoadStateAccess.LoadedModuleInfo _ LoadStateAccess.GetLoadedModuleInfoFromAbsPC[loadState, addr.absPC]; rope1: Rope.ROPE _ LoadStateAccess.GetRopeForBasicPCInfo[basicInfo, addr.absPC, TRUE, TRUE, TRUE, TRUE]; ropes2: LIST OF Rope.ROPE _ LoadStateAccess.GetRopeListForBasicPCInfo[basicInfo]; ropes3: LIST OF Rope.ROPE _ LoadStateAccess.GetRopeListForLoadedModuleInfo[moreInfo]; ShowIndentedRopes[LIST[rope1], cmd.out, 0]; ShowIndentedRopes[ropes2, cmd.out, 0]; ShowIndentedRopes[ropes3, cmd.out, 0]; BEGIN mesaParts: NameParts _ GetNamePartsFromFullPathName[mesaFileName]; ResetSearchPaths[modules, LIST[mesaParts.principalDirectory], BasicTime.Now[]]; BEGIN resultingModule: CedarModule _ GetCedarModuleForLoadedModule[modules, moreInfo]; moduleRelativeAddr: CARD _ addr.absPC-(moreInfo.lsi[text].base+moreInfo.moduleRelativeBaseAddr); resultingSourcePos: REF CedarSourcePosition _ ComputeCedarSourcePosition[resultingModule, [[0, ""], moduleRelativeAddr]]; ropes4: LIST OF Rope.ROPE _ GetRopesForSourcePosInfo[resultingSourcePos]; ShowIndentedRopes[ropes4, cmd.out, 0]; IF resultingSourcePos.mesaPosition # addr.correspondingMesaPosition THEN ERROR; END; END; END; END; END; CirioNubAccess.DestroyNub[nub]; SystemInterface.CloseFileSet[fileSet]; END; SetDebugSearch: Commander.CommandProc ~ { debugSearch _ cmd.procData.clientData = $True; msg _ IO.PutFR["debugSearch=%g", [boolean[debugSearch]] ]}; ShowReportByLevel: PUBLIC PROC [s: IO.STREAM, r: Rope.ROPE, level: ATOM] ~ { SELECT messagesDesired FROM $debug => IO.PutF[s, "%g\N", IO.rope[r]]; $normal => SELECT level FROM $debug => {}; $normal, $urgent => IO.PutF[s, "%g\N", IO.rope[r]]; ENDCASE => IO.PutF[s, "Bad level for message: %g\N", IO.rope[r]]; $urgent => SELECT level FROM $debug => {}; $normal => {}; $urgent => IO.PutF[s, "%g\N", IO.rope[r]]; ENDCASE => IO.PutF[s, "Bad level for message: %g\N", IO.rope[r]]; ENDCASE => IO.PutF[s, "Bad desired level for message: %g\N", IO.rope[r]]; }; LevelFromRope: PROC [r: Rope.ROPE] RETURNS [ATOM] ~ { SELECT TRUE FROM Rope.Equal[r, "normal", FALSE] => RETURN[$normal]; Rope.Equal[r, "debug", FALSE] => RETURN[$debug]; Rope.Equal[r, "urgent", FALSE] => RETURN[$urgent]; ENDCASE => RETURN[$error]; }; RopeFromLevel: PROC [l: ATOM] RETURNS [Rope.ROPE _ "ERROR"] ~ { SELECT l FROM $normal => RETURN["normal"]; $debug => RETURN["debug"]; $urgent => RETURN["urgent"]; ENDCASE => RETURN["ERROR"]; }; MessageLevel: PROC [] RETURNS [ATOM _ $error] ~ { levelRope: Rope.ROPE _ UserProfile.Token[key: "Cirio.MessageLevel", default: "normal"]; level: ATOM _ LevelFromRope[levelRope]; IF level = $error THEN level _ $normal; RETURN [level]; }; ChangeLevel: Commander.CommandProc ~ { numArgs:CARD _ CommanderOps.NumArgs[cmd]; newLevel: ATOM _ NIL; newLevelRope: Rope.ROPE _ NIL; IF numArgs > 1 THEN { newLevelRope _ CommanderOps.NextArgument[cmd]; newLevel _ LevelFromRope[newLevelRope]; SELECT newLevel FROM $error => IO.PutF[cmd.out, "level %g is not a valid message level\nValid levels are normal, urgent, and debug.\n", IO.rope[newLevelRope]]; messagesDesired => IO.PutF[cmd.out, "level %g was already the message level.\n", IO.rope[newLevelRope]]; ENDCASE => { IO.PutF[cmd.out, "level changed from %g to %g.\n", IO.rope[RopeFromLevel[messagesDesired]], IO.rope[newLevelRope]]; messagesDesired _ newLevel; } } ELSE IO.PutF[cmd.out, "Current level: %g\n", IO.rope[RopeFromLevel[messagesDesired]]]; }; messagesDesired: ATOM _ MessageLevel[]; debugSearch: BOOL _ FALSE; Commander.Register["ChangeCirioMessageLevel", ChangeLevel, "Change the verbosity level of the messages that Cirio prints out.\n\tUsage: ChangeCirioMessageLevel [level]\n\tValid levels:\n\t\turgent:\tMessages that should always be seen.\n\t\tnormal:\tInformative messages.\n\t\tdebug:\tMore informatation than you want to see.\n\t\tPrint the current setting.\n"]; Commander.Register["TestGenMesaSourcePositionMacros", TestGenMesaSourcePositionMacros]; Commander.Register["TestCreateCFileInfo", TestCreateCFileInfo]; Commander.Register["TestSetBreak", TestSetBreak]; Commander.Register["TestFromMesa", TestFromMesa]; Commander.Register["TestFromDotO", TestFromDotO, "file.o file-rel-pc"]; Commander.Register["CrudeExp", CrudeExp]; Commander.Register["NewTestSetBreak", NewTestSetBreak]; Commander.Register["Cirio.DebugSearch", SetDebugSearch, "RMTWModules.debugSearch _ TRUE", $True]; Commander.Register["Cirio.DontDebugSearch", SetDebugSearch, "RMTWModules.debugSearch _ FALSE", $False]; END. Ö RMTWModules.mesa Copyright Ó 1990, 1991, 1992, 1993 by Xerox Corporation. All rights reserved. Sturgis, April 1, 1990 2:58 pm PDT Last tweaked by Mike Spreitzer on April 10, 1992 7:28 pm PDT Last changed by Theimer on November 29, 1989 4:07:25 am PST Linda Howe December 28, 1989 8:25:20 am PST Coolidge, August 15, 1990 9:35 am PDT Laurie Horton, February 25, 1993 4:24 pm PST Philip James, January 6, 1992 10:47 am PST Katsuyuki Komatsu January 2, 1993 5:50 pm PST In this module we tackle the issue of mesa modules. A mesa module is (roughly) a quintuple: mesa file, mob file, C file, object file (perhaps component), and memory locations. These files must satisfy certain consistency conditions with respect to version stamps. Using a module one can compute the absolute address at which to set a break point and one can compute a source position. An issue not resolved in current implementation: there may be more than one mob with the same source version stamp. I simply take the first one I find. STILL NEED loaded version of this stuff and the action routines NOTE: November 10, 1989 10:42:22 am PST. heavy changes underway. Pervious implementation got mesaSOurce => dotO working. New implementation recognizes source version stamps, and I am editing in GetMesa. Must repair getMob to either check source version stamp, or mob versoin stamp, depending on which is present. Note: April 9, 1990 3:40:24 pm PDT. more heavy changes underway. Issue is the inability to set breakpoints starting from a mesa file for a previously unvisited module. This frequntly results in long serach times involving finding embedded dot Os that always seem to fail. In the past, the searces were short, always seemed to fail, but the breakpoint succeeded. Now the searches are long, and breakpoints fail to be planted. First step: reorder procedures so that all calls go "down" and all public procs are at top. the following extra level of indirection allows for the discovery that two partially built modules are actually the same. These modules will be looked up starting from a mesaSource or starting from a Module. no need for entry as this is a create proc no need for ENTRY because info^ is a constant NIL means failure to compute no need for ENTRY because addr^ is constant returns nil if can't be found one should try later if search paths change FIX: Use the PFS extension options when they're available. parts: NameParts _ GetNamePartsFromFullPathName[mobName]; here we start assorted procedures that get loaded modules given various starts here we have the procedures that get a module from various starts base: RopeParts.RopePart _ RopeSequence.Fetch[RopeSequence.ParsePartToSeq[RopeParts.RopePart _ NARROW[parts], '.], 0]; mesaName: PATH _ SystemInterface.GetNameOfFile[mesa]; parts: NameParts _ GetNamePartsFromFullPathName[mesaName]; now, lets see if we can learn anything about the dotO location that might be helpful later. now, lets see if we can learn anything about the dotO location that might be helpful later. here are the procedures that get loaded components of modules here are the procedures that get (non loaded) components of modules this computation of vs is designed to be equivalent to MobAccessImpl.ComputeSourceVersionStamp. our only effective criterion is the version stamp, if we have one. no version stamp, so accept any file with the right name parts: NameParts _ GetNamePartsFromFullPathName[info.fullName]; (this depends on the file caching mechanism in FileSet, to that we get only one file for each name.) module must have been created from a mesa file our only effective criterion is the version stamp, if we have one. parts: NameParts _ GetNamePartsFromFullPathName[info.fullName]; FIX: Use the PFS Extentions stuff when available. (this depends on the file caching mechanism in FileSet, to that we get only one file for each name.) if one is not present and we succeed in finding one, it will be the singleton. try to find a name for the hash key. maybe we already have a module with this mob that started from a different direction now, lets look again our only effective criterion is the version stamp, if we have one. no version stamp, so accept last created file with the right name we take the latest created acceptable mob in the same directory parts: NameParts _ GetNamePartsFromFullPathName[info.fullName]; we take the latest created acceptable mob in the same directory FIX: Use the PFS Extentions stuff when available. (this depends on the file caching mechanism in FileSet, to that we get only one file for each name.) Some other procedures version stamp hashing name parts check for and remove sun4 and sun4-o3 Do the comparisons as ropes. Should be safe, and it's easier. Yup, sun4 or sun4-o3 found. Cut it off. check for and remove twiddle version check for and remove c2c (which must have a following extension) check for and remove extension sun4, c2c Handle C files At the time of this writing, Christian was not around to answer questions, but Peter was. Peter says that the pair of numbers in a SOURCE macro are a source position and a char count. They represent nested regions. (However, experiment shows that they do not represent nested regions.) They may not be in monotonic increasing order. As a starting point, I take a very crude position. I shall map a source position to the line number holding the SOURCE macro containing the largest source position less than or equal to the given source position. Similarly, given a cLineNum, I shall map to a SOURCE macro containing the largest cLineNum less than or equal to the given cLineNum. (Note that there can only be one source macro per c line.) probably should make this a binary search, oh well no need to be monitor locked because nothing modifies contents of info no need to be monitor locked because nothing modifies contents of info if starting positions are equal, then sort by CLine number (however, I don't believe that this can happen) If c line numbers are the same, then sort by increasing start source position (I don't believe that this can happen) note: the version stamp key is broken into pieces so that it won't look like a version stamp in the various files. no need for ENTRY because this is a create routine and doesnt examine modules no need for ENTRY because info^ is constant note: the version stamp key is broken into pieces so that it won't look like a version stamp in the various files. definition files misc FIX: Figure this out and use PFS Extensions instead of ROPEs note: the version stamp key is broken into pieces so that it won't look like a version stamp in the various files. needed in Dorado land test code This is used with CreateButton c TestSetBreak Test.c for example, when we have Test.mesa open and Test.c available. IO.PutF[cmd.out, "%g\N", IO.rope[msgText]]; IO.PutF[cmd.out, "%g\N", IO.rope[msgText]]; IO.PutF[cmd.out, "%g\N", IO.rope[msgText]]; SystemInterface.CloseFileSet[fileSet]; this is to be used with CreateButton tsb NewTestSetBreak menhir 4816 IO.PutF[cmd.out, "%g\N", IO.rope[msgText]]; cludge, mechanism should have noticed this added principal directory main code TestFromMesa /pixel1/pcedar2.0/sunterminal/sunterminalimpl.mesa.~23~ TestFromDotO /pixel1/pcedar2.0/sunterminal/sun4/sunterminalimpl.c2c.o.~23~ 50 CrudeExp /pixel1/pcedar2.0//sunterminal/sunterminalimpl.mesa.~23~ /pixel1/pcedar2.0//sunterminal/sunterminalimpl.mob.~23~ this is to be used with CreateButton tsb NewTestSetBreak menhir 4816 after selecting a position in some mesa file, e.g., [palain-ux]sturgis>Cedar>2.0>System>PlumberImpl.mesa ÊQì•NewlineDelimiter ™codešœ™K™NKšœ"™"K™˜YKš˜Kšœ œ œ  ˜*Kšœœ  ˜0Kšœœ  ˜DK˜š Ÿ œœ'œ œœ˜`Kšœ˜Kšœœ ˜Kšœ˜Kšœ[˜[šœœ7˜?Kš œœœ"œ œ œ ˜ˆKšœ ˜—Kšœ œ˜'Kšœ œœ2œ]˜ÃKšœ˜Kšœ!˜!Kšœ*˜*Kšœœ˜ Kšœ œœ˜!—K˜š Ÿ œœ&œ œœ˜\Kšœ˜Kšœœ ˜Kšœ˜Kšœ[˜[šœœ7˜?Kš œœœ"œ œ œ ˜ˆKšœ ˜—Kšœ œ˜'Kšœ œœ2œ]˜Ãšœœ˜Kšœ˜Kšœ!˜!Kšœ*˜*Kšœœ˜—Kšœœ˜Kšœ œœ˜!—K˜šŸ œœœ˜Kš˜K™:Kšœœœœ3˜kKšœ œœ-œ0˜‘Kšœ[˜[Kšœ˜—K˜Kš œ>œœœœœ˜|KšœœœœLœ œ œ ˜¤K˜K˜šœœœœœœœ"œœœœ˜xKšœ œœ+œ(˜‡K˜Kšœ˜K˜—šœœœ˜!Kšœ œB˜UKšœ˜ Kšœcœœ œ˜•Kšœcœ8œ œ˜ÆKšœ˜K˜—šœœœœœœœ'œœœœ˜}Kšœ œœ*œ(˜†K˜Kšœ˜K˜—šœœ˜Kš˜Kšœ%˜%Kš œ?œœœœœ˜}Kš˜—šœ˜Kš˜Kšœ œ4˜AKšœ9™9Kšœ˜Kšœ1œ"˜VKšœ˜K˜—Kšœ˜—Kšœ ˜Kšœ˜—K˜K™NK™šŸœœWœ˜ŠKš˜Kšœœ.˜Gšœœ˜Kš˜Kšœœœœ˜9Kšœœ-œœ˜>Kšœ˜—šœœœG˜gKš˜Kšœ œ'˜5Kšœ)œ!˜LKšœ:˜:Kšœœ˜%Kšœœ˜Kšœ-  ˜9KšœœÉ˜æKšœ/œY˜Žšœœ ®œ ˜ËKšœœ~˜šœœœ˜Kšœœk˜ˆKšœ˜—Kšœ>˜>šœœœ˜Kšœ œ+˜8Kšœœœ˜/Kšœ˜Kšœœœœ·˜óšœœ(œ˜5K˜K˜Kšœœ—˜´Kšœ˜ —Kšœœë˜K˜—Kšœ˜—Kšœ˜—Kšœ˜ Kšœ˜—K˜šŸœœœœ˜@KšœœœA˜M—K˜šŸœœ œ#œ˜Kš˜š œœœœœ˜#Kš˜Kšœv˜vš œ œœœ˜8Kšœ"˜"—Kšœ ˜Kš˜—Kšœ˜—K˜™AK˜—šŸœœ+œ˜`š˜Kšœ œœœ"˜eKšœ œ'˜5Kšœ:˜:Kšœ_œ™vK˜Kšœ@˜@Kšœ4˜4Kšœœ0˜Lšœ œ˜Kš˜Kšœ œ'™5Kšœ:™:K˜Kšœ)˜)K˜Kšœ&œ˜EKšœ#œœ˜JKšœ<˜˜sKš˜Kšœ$™$Kšœ˜Kšœ+˜+Kšœ˜K˜šœœœ˜Kšœ6˜6Kšœœ1˜EK˜—K˜š œ œœœœ˜4Kšœ œœœœœœœ"˜€Kšœ"˜"šœœœœœœœ œ˜VKšœ0˜0KšœS˜SKšœ0˜0Kšœœ1˜EKšœ˜—K˜—K˜K™Tš œœœœ ˜MKšœ F˜LKšœœœ  ˜+Kšœ*œœ˜7K˜Kšœœœ(˜EKšœœœ(˜JKš œœœ*œœ˜QK˜Kšœœœ.˜NKšœœœ.˜SKš œœœ0œœ˜ZK˜š œœœœ7œœ˜`Kšœ`˜`Kšœ˜—š œœœœ2œœ˜[Kšœj˜jKšœ˜—K˜š œœœœ+œœ˜RKšœI˜IKšœ˜—š œœœœ&œœ˜MKšœS˜SKšœ˜—K˜šœC˜IKšœ,˜,Kšœ/ "˜U—K˜š œœœœ˜GKšœ9œ˜?—š œœœœ˜AKšœ3œ˜9—š œœœœ˜9Kšœ+œ˜1—š œœœœ˜AKšœ3œ˜9—š œœœœ˜;Kšœ-œ˜3—š œœœœ˜?Kšœ1œ˜7—š œœœœ˜=Kšœ/œ˜5K˜—š œœœœ˜@Kšœ:˜:—Kšœœœ,˜KKšœœœ,˜PK˜š œœœœ˜4Kšœ.˜.—Kšœœœ ˜9Kšœœœ ˜>K˜š œœœœ˜:Kšœ4˜4—Kšœœœ&˜BKšœœœ&˜GK˜š œœœœ˜2Kšœ,˜,—Kšœœœ˜6Kšœœœ˜;K˜š œœœœ˜6Kšœ0˜0—Kšœœœ"˜——šŸ œ˜%Kš˜Kšœ:˜:Kšœ œœ˜,šœC˜CKšœœœ*˜=KšœS˜SKšœ(˜(K˜CKšœ œ˜Kšœœ˜K˜Kšœ%œ˜CKšœ8˜8Kšœ&œœœ˜qKšœ<˜K˜%šœœ˜Kš˜Kšœ œU˜cKšœ œh˜uK˜Kš œ œ@œœœœ˜hKšœœœœ8˜QKšœœœœ<˜UKšœœ˜+Kšœ&˜&šœ&˜&Kš˜KšœB˜Bšœœ1˜OK™DKš˜KšœP˜PKšœœH˜`Kšœœb˜yKšœœœœ0˜IKšœ&˜&KšœBœœ˜OKšœ˜—Kšœ˜—Kšœ˜—Kšœ˜—Kšœ˜—Kšœ˜Kšœ&˜&Kšœ˜——K˜šŸœ˜)Kšœ.˜.Kšœœ3˜;—K˜šŸœœœœœ œ œ˜Lšœ˜Kšœ œœ ˜)šœ œ˜K˜ Kšœ ˜ Kšœ œœ ˜*Kšœ œ(œ ˜A—šœ œ˜K˜ K˜Kšœ œœ ˜*Kšœ œ(œ ˜A—Kšœœ0œ ˜I—K˜K˜—š Ÿ œœ œœœ˜5šœœ˜Kšœœœ ˜2Kšœœœ ˜0Kšœœœ ˜2Kšœœ ˜—K˜K˜—š Ÿ œœœœœ˜?šœ˜ Kšœ œ ˜Kšœ œ ˜Kšœ œ ˜Kšœœ ˜—K˜K˜—šŸ œœœœ˜1KšœœC˜WKšœœ˜'šœ˜K˜—Kšœ ˜K˜—K˜šŸ œ˜&Kšœœ˜)Kšœ œœ˜Kšœœœ˜šœ œ˜K˜.K˜'šœ ˜Kšœ œgœ˜ŠKšœœ<œ˜hšœ˜ Kšœ1œ'œ˜sKšœ˜K˜——K˜—šœ˜Kšœ&œ'˜Q—K˜K˜——™ K˜Kšœœ˜'K˜Kšœ œœ˜K˜Kšœð˜ðKšœW˜WKšœ?˜?Kšœ1˜1K˜šœ1˜1KšœD™DK™—šœG˜GKšœM™M—K™šœ)˜)Kšœy™y—K™šœ7˜7™Kšœ,™,K™3Kšœ<™<——K˜Kšœa˜aK˜Kšœg˜gK˜—Kšœ˜—…—!2ô