<> <> <> DIRECTORY AMBridge USING [GetWorld, GFHFromTV, RemoteGFHFromTV], AMFiles USING [OpenIt], AMModel USING [Class, Context, Source, SourceObj, CharIndex, SourceFileName, SourceClass, ContextChildren, ContextClass, SectionVersion, SectionSource, ContextSection, MostRecentNamedContext], AMModelPrivate USING [FGIndex, FGNull, EPI, FGIToEPI, GetLocalBCD, GetRemoteBCD, CharIndexToFGI, SectionRec, RefTVRec, ConfigContext], AMTypes USING [Error, TVType, GlobalParent], BasicTime USING [ToNSTime], BcdDefs USING [VersionStamp, MTIndex, FTSelf, BcdBase, MTHandle], BcdOps USING [ProcessModules], FS USING [OpenFile, nullOpenFile, GetInfo, Close], LoadState USING [nullConfig], Rope USING [ROPE, Concat, Equal, Find, Substr, Match], RTSymbolDefs USING [SymbolTableBase, SymbolTableHandle, nullHandle, nullBase], RTSymbols USING [ReleaseSTB, AcquireSTBFromSGI, AcquireSTB, GetSTHForModule], RTSymbolsPrivate USING [AcquireBCDFromVersion, ReleaseBCD], RTTypesRemotePrivate USING [ReleaseRemoteBCD], SafeStorage USING [gfhType, fhType], Table USING [Base], WorldVM USING [LocalWorld, World]; AMModelSourceImpl: PROGRAM IMPORTS AMBridge, AMFiles, AMTypes, BasicTime, BcdOps, AMModel, AMModelPrivate, FS, LoadState, RTSymbols, Rope, RTSymbolsPrivate, RTTypesRemotePrivate, WorldVM EXPORTS AMModel, AMModelPrivate = { OPEN AMBridge, AMModel, AMModelPrivate, AMTypes, Rope, RTSymbolDefs, RTSymbols, RTTypesRemotePrivate, SafeStorage, WorldVM; <> <> Section: TYPE = REF SectionObj; SectionObj: PUBLIC TYPE = SectionRec; <> <<... dealing with Source>> FileSource: PUBLIC PROC[fileName: ROPE, class: --model, prog, interface--Class] RETURNS[s: Source _ NIL] = { f: FS.OpenFile _ FS.nullOpenFile; IF class = model THEN { IF NOT Rope.Match["*.config*", fileName, FALSE] THEN fileName _ fileName.Concat[".config"]; } ELSE { IF NOT Rope.Match["*.mesa*", fileName, FALSE] THEN fileName _ fileName.Concat[".mesa"]; }; f _ AMFiles.OpenIt[fileName].openFile; IF f # FS.nullOpenFile THEN { s _ NEW[SourceObj _ [fileName: fileName, class: class, versionStamp: [0, 0, BasicTime.ToNSTime[FS.GetInfo[f].created]], sourceRange: entire[]]]; FS.Close[f]; }; }; <> <> <> <> <> <> <> SourceSection: PUBLIC PROC[source: Source, context: --worldRoot or model--Context] RETURNS[section: Section _ NIL, contexts: LIST OF --prog--Context _ NIL] = {SELECT SourceClass[source] FROM statement => {[section, contexts] _ SourceSection [NEW[SourceObj _ [fileName: source.fileName, class: prog, versionStamp: source.versionStamp, sourceRange: entire[]]], context]; section _ NEW[SectionObj _ [statement[prog: NARROW[section], fgtIndex: SourceToFirstFGI [source, NARROW[section]]]]]; }; proc => {[section, contexts] _ SourceSection [NEW[SourceObj _ [fileName: source.fileName, class: prog, versionStamp: source.versionStamp, sourceRange: entire[]]], context]; section _ NEW[SectionObj _ [proc[prog: NARROW[section], entryPointIndex: SourceToEPI [source, NARROW[section]]]]]; }; prog => <> <> <> { WITH context SELECT FROM tv: RefTVRec => {SELECT TVType[tv] FROM gfhType => { section _ ContextSection[context]; IF Rope.Equal[SourceFileName[source], SourceFileName[SectionSource[section]], FALSE] THEN contexts _ CONS[context, NIL] ELSE section _ NIL; RETURN}; fhType => {[section, contexts] _ SourceSection[source, GlobalParent[tv]]; RETURN}; ENDCASE => ERROR Error[typeFault]; }; mc: ConfigContext => {context: Context; fn: ROPE = SourceFileName[source]; i: INT _ Rope.Find[s1: fn, s2: ".", pos1: 0, case: FALSE]; mn: ROPE _ IF i = -1 THEN fn ELSE Rope.Substr[base: fn, len: i]; context _ MostRecentNamedContext[mn, mc]; IF context = NIL THEN ERROR AMTypes.Error [reason: notImplemented, msg: "Finding an object location for a source not loaded"]; section _ ContextSection[context]; contexts _ CONS[context, contexts]; IF TRUE THEN RETURN; IF mc.configIndex = LoadState.nullConfig THEN {proc: PROC[context: Context] RETURNS[stop: BOOL _ FALSE] = { IF ContextClass[context] = model THEN {s: Section; cl: LIST OF Context; [s, cl] _ SourceSection[source, context]; IF s # NIL THEN { IF section = NIL THEN section _ s ELSE {IF SectionVersion[section] # SectionVersion[s] THEN ERROR Error [reason: notImplemented, msg: "different sections for the same source"]}; UNTIL cl = NIL DO contexts _ CONS[cl.first, contexts]; cl _ cl.rest; ENDLOOP; }; RETURN}; IF Rope.Equal[SourceFileName[source], SourceFileName[SectionSource[ContextSection[context]]], FALSE] THEN {IF section = NIL THEN section _ ContextSection[context] ELSE {IF SectionVersion[ContextSection[context]] # SectionVersion[section] THEN ERROR Error[reason: notImplemented, msg: "different sections for the same source"]}; contexts _ CONS[context, contexts]; }; }; -- end proc defn [] _ ContextChildren[context, proc]; } -- end IF mc.configIndex = LoadState.nullConfig ELSE {proc: PROC[context: Context] RETURNS[stop: BOOL _ FALSE] = { IF Rope.Equal[SourceFileName[source], SourceFileName[SectionSource[ContextSection[context]]], FALSE] THEN {IF section = NIL THEN section _ ContextSection[context] ELSE {IF SectionVersion[ContextSection[context]] # SectionVersion[section] THEN ERROR Error[reason: notImplemented, msg: "different sections for the same source"]}; contexts _ CONS[context, contexts]; }; }; [] _ ContextChildren[context, proc]; }; }; ENDCASE => ERROR }; model => ERROR AMTypes.Error[ reason: notImplemented, msg: "SourceSection[model source]"]; interface => ERROR AMTypes.Error[ reason: notImplemented, msg: "SourceSection[interface source]"]; ENDCASE => ERROR}; -- end SourceSection <<[prog module bcd, CharIndex] => FGIndex (wrt prog module bcd)>> SourceToFirstFGI: PROC[source: Source, prog: REF prog SectionObj] RETURNS[ans: FGIndex _ FGNull] = {IF prog.someGFHTV # NIL THEN -- prog loaded {world: World = GetWorld[prog.someGFHTV]; local: BOOL _ (world = LocalWorld[]); IF local THEN {bcd: BcdDefs.BcdBase = GetLocalBCD[GFHFromTV[prog.someGFHTV]]; stb: SymbolTableBase _ GetModuleSTB[bcd, prog.versionStamp]; ans _ CharIndexToFGI[stb, (WITH s: source SELECT FROM field => s.firstCharIndex ENDCASE => 0) ! UNWIND => ReleaseSTB[stb]]; ReleaseSTB[stb]} ELSE {bcd: BcdDefs.BcdBase = GetRemoteBCD[RemoteGFHFromTV[prog.someGFHTV]]; stb: SymbolTableBase _ GetModuleSTB[bcd, prog.versionStamp ! UNWIND => ReleaseRemoteBCD[bcd]]; ReleaseRemoteBCD[bcd]; ans _ CharIndexToFGI[stb, (WITH s: source SELECT FROM field => s.firstCharIndex ENDCASE => 0) ! UNWIND => ReleaseSTB[stb]]; ReleaseSTB[stb]}; } ELSE -- prog not loaded {bcd: BcdDefs.BcdBase = RTSymbolsPrivate.AcquireBCDFromVersion [versionStamp: prog.versionStamp, shortFileNameHint: Rope.Concat[prog.moduleName, ".bcd"]]; stb: SymbolTableBase _ GetModuleSTB[bcd, prog.versionStamp ! UNWIND => RTSymbolsPrivate.ReleaseBCD[bcd]]; RTSymbolsPrivate.ReleaseBCD[bcd]; ans _ CharIndexToFGI[stb, (WITH s: source SELECT FROM field => s.firstCharIndex ENDCASE => 0) ! UNWIND => ReleaseSTB[stb]]; ReleaseSTB[stb]}; }; <<[prog module bcd, CharIndex] => entryPointIndex (wrt prog module bcd)>> SourceToEPI: PROC[source: Source, prog: REF prog SectionObj] RETURNS[ans: EPI _ 0] = {IF prog.someGFHTV # NIL THEN -- prog loaded {world: World = GetWorld[prog.someGFHTV]; local: BOOL _ (world = LocalWorld[]); IF local THEN {bcd: BcdDefs.BcdBase = GetLocalBCD[GFHFromTV[prog.someGFHTV]]; stb: SymbolTableBase _ GetModuleSTB[bcd, prog.versionStamp]; fgi: FGIndex _ CharIndexToFGI[stb, (WITH s: source SELECT FROM field => s.firstCharIndex ENDCASE => 0) ! UNWIND => ReleaseSTB[stb]]; ans _ FGIToEPI[stb, fgi ! UNWIND => ReleaseSTB[stb]]; ReleaseSTB[stb]; } ELSE {bcd: BcdDefs.BcdBase = GetRemoteBCD[RemoteGFHFromTV[prog.someGFHTV]]; stb: SymbolTableBase _ GetModuleSTB[bcd, prog.versionStamp ! UNWIND => ReleaseRemoteBCD[bcd]]; fgi: FGIndex; ReleaseRemoteBCD[bcd]; fgi _ CharIndexToFGI[stb, (WITH s: source SELECT FROM field => s.firstCharIndex ENDCASE => 0) ! UNWIND => ReleaseSTB[stb]]; ans _ FGIToEPI[stb, fgi ! UNWIND => ReleaseSTB[stb]]; ReleaseSTB[stb]}; } ELSE -- prog not loaded {bcd: BcdDefs.BcdBase = RTSymbolsPrivate.AcquireBCDFromVersion [versionStamp: prog.versionStamp, shortFileNameHint: Rope.Concat[prog.moduleName, ".bcd"]]; stb: SymbolTableBase _ GetModuleSTB[bcd, prog.versionStamp ! UNWIND => RTSymbolsPrivate.ReleaseBCD[bcd]]; fgi: FGIndex; RTSymbolsPrivate.ReleaseBCD[bcd]; fgi _ CharIndexToFGI[stb, (WITH s: source SELECT FROM field => s.firstCharIndex ENDCASE => 0) ! UNWIND => ReleaseSTB[stb]]; ans _ FGIToEPI[stb, fgi ! UNWIND => ReleaseSTB[stb]]; ReleaseSTB[stb]}; }; GetModuleSTB: PUBLIC PROC[bcd: BcdDefs.BcdBase, versionStamp: BcdDefs.VersionStamp] RETURNS[stb: SymbolTableBase _ nullBase] = { FindModule: PROC[mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex] RETURNS[stop: BOOLEAN _ FALSE] = {version: BcdDefs.VersionStamp _ IF mth.file = BcdDefs.FTSelf THEN bcd.version ELSE ftb[mth.file].version; IF version = versionStamp THEN {stb _ AcquireSTBFromSGI[bcd, mth.sseg]; RETURN[TRUE]}}; <> sth: SymbolTableHandle _ nullHandle; ftb: Table.Base = LOOPHOLE[bcd + bcd.ftOffset]; sth _ GetSTHForModule[versionStamp, NIL, NIL ! ANY => CONTINUE]; IF sth = nullHandle THEN [] _ BcdOps.ProcessModules[bcd, FindModule] ELSE stb _ AcquireSTB[sth]; }; }.