-- 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[]];
}.