-- SMProjImpl.mesa -- last edit by Satterthwaite, August 4, 1983 1:37 pm DIRECTORY BcdDefs: TYPE USING [Base, MTIndex], BcdOps: TYPE USING [BcdBase], CompilerOps: TYPE USING [Transaction], CS: TYPE USING [EndsIn, EquivalentRS, RootName, StringToRope, z], Directory: TYPE USING [Error, ignore, Lookup, Rename], File: TYPE USING [Capability, nullCapability], FileSegment: TYPE USING [], OrderedSymbolTable: TYPE OrderedSymbolTable USING [ Table, CreateTable, DestroyTable, EnumerateIncreasing, Initialize, Insert, Lookup], Rope: TYPE USING [Cat, Flatten, Text], SMProj: TYPE USING [Proj, ProjInfo], Space: TYPE USING [ Create, CreateUniformSwapUnits, Delete, Handle, LongPointer, MakeReadOnly, Map, virtualMemory], TimeStamp: TYPE USING [Stamp, Null]; SMProjImpl: CEDAR MONITOR IMPORTS CS, Directory, OrderedSymbolTable, Rope, Space EXPORTS SMProj ~ { Proj: TYPE ~ SMProj.Proj; -- can't be opaque with current RedBlackTree impl -- all code in this module updates the projection table -- therefore all PUBLIC procedures acquire the monitor lock -- MDS usage (protected by the monitor lock) table: OrderedSymbolTable.Table; -- endof MDS -- code to manipulate the projection (bcd) cache Flush: PUBLIC ENTRY PROC ~ { ENABLE UNWIND => {NULL}; table.DestroyTable}; Reset: PUBLIC ENTRY PROC ~ { ENABLE UNWIND => {NULL}; ResetProj: PROC[proj: Proj] RETURNS[stop: BOOL←FALSE] ~ { IF proj.state > $analyzed THEN { proj.capability ← File.nullCapability; proj.state ← $analyzed}; }; table.EnumerateIncreasing[ResetProj]}; Erase: PUBLIC ENTRY PROC[proj: Proj] ~ { ENABLE UNWIND => {NULL}; oldCap: File.Capability ~ proj.capability; IF oldCap ~= File.nullCapability THEN { EraseProj: PROC[proj: Proj] RETURNS[stop: BOOL←FALSE] ~ { IF oldCap = proj.capability THEN { proj.state ← MAX[proj.state, $analyzed]; proj.capability ← File.nullCapability; proj.localName ← NIL} }; table.EnumerateIncreasing[EraseProj]}; }; Analyzed: PUBLIC ENTRY PROC[proj: Proj] RETURNS[BOOL] ~ { ENABLE UNWIND => {NULL}; RETURN[proj.state >= $analyzed]}; Available: PUBLIC ENTRY PROC[proj: Proj] RETURNS[BOOL] ~ { ENABLE UNWIND => {NULL}; RETURN[proj.state = $opened]}; Fill: PUBLIC ENTRY PROC[proj: Proj, localName: Rope.Text, new: BOOL] ~ { ENABLE UNWIND => {NULL}; IF proj.state < $opened THEN { proj.localName ← (IF CS.EndsIn[localName, ".bcd"] THEN localName ELSE CS.RootName[localName].Cat[".bcd"].Flatten[]); IF ~new THEN OpenProj[proj]}; }; Find: PUBLIC ENTRY PROC[stamp: TimeStamp.Stamp] RETURNS[proj: Proj] ~ { ENABLE UNWIND => {NULL}; proj ← table.Lookup[stamp]; IF proj = NIL THEN { proj ← (CS.z).NEW[SMProj.ProjInfo ← [stamp~stamp, state~$empty]]; table.Insert[proj, stamp]}; RETURN}; Rename: PUBLIC ENTRY PROC[proj: Proj, newName: Rope.Text] ~ TRUSTED { ENABLE UNWIND => {NULL}; Directory.Rename[ newName~LOOPHOLE[newName], oldName~LOOPHOLE[proj.localName]]; proj.localName ← newName}; FindFile: PROC[localName: Rope.Text] RETURNS [cap: File.Capability] ~ TRUSTED { cap ← Directory.Lookup[ fileName~LOOPHOLE[localName], permissions~Directory.ignore ! Directory.Error => {cap ← File.nullCapability; CONTINUE}]; }; RetrieveRemoteFile: PROC[proj: Proj] ~ {}; -- place holder OpenProj: PROC[proj: Proj] ~ TRUSTED { cap: File.Capability ~ FindFile[proj.localName]; IF cap = File.nullCapability THEN NULL ELSE IF proj.state = $analyzed THEN { proj.capability ← cap; proj.state ← $opened} -- version stamp not verified here ELSE { bcdBase: BcdOps.BcdBase; space: Space.Handle; [space, bcdBase] ← LoadUpBcd[cap]; IF bcdBase.version = proj.stamp THEN { firstMti: BcdDefs.MTIndex ~ BcdDefs.MTIndex.FIRST; mtb: BcdDefs.Base ~ LOOPHOLE[bcdBase + bcdBase.mtOffset]; sgb: BcdDefs.Base ~ LOOPHOLE[bcdBase + bcdBase.sgOffset]; proj.interface ← bcdBase.definitions; proj.symbolPages ← [ base~sgb[mtb[firstMti].sseg].base, pages~sgb[mtb[firstMti].sseg].pages]; proj.capability ← cap; proj.state ← $opened}; Space.Delete[space]}; }; LoadUpBcd: PROC[cap: File.Capability] RETURNS[space: Space.Handle, bcdBase: BcdOps.BcdBase] ~ TRUSTED { nPages: CARDINAL ← 10; IF cap = File.nullCapability THEN ERROR; DO space ← Space.Create[size~nPages, parent~Space.virtualMemory]; space.Map[window~[file~cap, base~1]]; bcdBase ← space.LongPointer; IF bcdBase.nPages <= nPages THEN EXIT; nPages ← bcdBase.nPages; Space.Delete[space]; ENDLOOP; Space.CreateUniformSwapUnits[parent~space, size~8]; space.MakeReadOnly}; -- for proj info provided by the compiler Update: PUBLIC ENTRY PROC[ proj: Proj, parms: POINTER TO READONLY CompilerOps.Transaction] ~ TRUSTED { ENABLE UNWIND => {NULL}; IF proj.stamp # parms.objectVersion THEN ERROR; proj.interface ← parms.interface; IF ~CS.EquivalentRS[proj.localName, parms.objectName] THEN proj.localName ← StringToText[parms.objectName]; proj.capability ← parms.objectFile; proj.symbolPages ← parms.symbolPages; proj.state ← $opened}; StringToText: PROC[string: LONG STRING] RETURNS[Rope.Text] ~ TRUSTED INLINE { RETURN [CS.StringToRope[string].Flatten]}; -- start code EmptyProj: PROC RETURNS [Proj] ~ { RETURN [(CS.z).NEW[SMProj.ProjInfo←[stamp~TimeStamp.Null]]]}; OrderedSymbolTable.Initialize[EmptyProj[], EmptyProj[]]; table ← OrderedSymbolTable.CreateTable[EmptyProj[]]; }.