CDDesignCacheImpl.mesa (part of ChipNDale)
Copyright © 1987 by Xerox Corporation. All rights reserved.
Created by Christian Jacobi, April 9, 1987 12:29:43 pm PDT
Last edited by: Christian Jacobi, October 19, 1987 10:49:30 am PDT
DIRECTORY
BasicTime,
CD,
CDDesignCache,
CDEnvironment,
CDIO,
CDOps,
CDPrivate,
CDProperties,
CDValue,
FileNames,
FS,
IO,
RefTab,
Rope,
SymTab,
TerminalIO,
TokenIO,
UserProfile;
CDDesignCacheImpl: CEDAR PROGRAM
IMPORTS CD, CDEnvironment, CDIO, CDOps, CDPrivate, CDProperties, CDValue, FileNames, FS, IO, RefTab, Rope, SymTab, TerminalIO, UserProfile
EXPORTS CDDesignCache =
BEGIN
GetSymTab: PROC [for: CD.Design] RETURNS [SymTab.Ref] = {
x: REF ~ CDValue.Fetch[for, $CDDesignCachePrivate];
WITH x SELECT FROM
t: SymTab.Ref => RETURN [t];
ENDCASE => IF x=NIL
THEN [] ← CDValue.StoreConditional[for, $CDDesignCachePrivate, SymTab.Create[5]]
ELSE [] ← CDValue.Store[for, $CDDesignCachePrivate, SymTab.Create[5]];
RETURN [GetSymTab[for]]
};
Set: PUBLIC PROC [for: CD.Design, remote: CD.Design] = {
tab: SymTab.Ref ~ GetSymTab[for];
IF for.technology#remote.technology OR for=remote THEN ERROR CD.Error[calling];
IF remote.mutability#readonly THEN ERROR CD.Error[designMutability];
[] ← SymTab.Store[tab, remote.name, remote];
};
Fetch: PUBLIC PROC [for: CD.Design, remoteName: Rope.ROPE] RETURNS [remote: CD.Design ← NIL] = {
tab: SymTab.Ref ~ GetSymTab[for];
WITH SymTab.Fetch[tab, remoteName].val SELECT FROM
d: CD.Design => IF d.mutability=readonly THEN RETURN [d];
ENDCASE => NULL;
};
IsCached: PUBLIC PROC [for: CD.Design, remoteName: Rope.ROPE] RETURNS [BOOL] = {
RETURN [Fetch[for, remoteName]#NIL]
};
Forget: PUBLIC PROC [for: CD.Design, remoteName: Rope.ROPE] = {
tab: SymTab.Ref ~ GetSymTab[for];
[] ← SymTab.Delete[tab, remoteName]
};
CameFile: PROC [d: CD.Design] RETURNS [Rope.ROPENIL] = {
IF d#NIL THEN
WITH CDValue.Fetch[d, $CDxCachedFile, design] SELECT FROM
r: Rope.ROPE => RETURN [r];
ENDCASE => NULL;
};
CameTime: PROC [d: CD.Design] RETURNS [BasicTime.GMT�sicTime.nullGMT] = {
IF d#NIL THEN
WITH CDValue.Fetch[d, $CDxCachedCreated, design] SELECT FROM
t: REF INT => RETURN [LOOPHOLE[t^, BasicTime.GMT]];
ENDCASE => NULL;
};
Search: PUBLIC PROC [remoteName: Rope.ROPE, fileName: Rope.ROPENIL, createdTime: BasicTime.GMT ← BasicTime.nullGMT, check: CDDesignCache.CheckProc←NIL, data: REFNIL] RETURNS [found: CD.Design←NIL] = {
Check: PROC [d: CD.Design] RETURNS [ok: BOOLFALSE] = {
IF d#NIL AND d.mutability=readonly THEN
IF fileName=NIL OR Rope.Equal[CameFile[d], fileName, FALSE] THEN
IF createdTime=BasicTime.nullGMT OR CameTime[d]=createdTime THEN
IF check=NIL OR check[d, data] THEN {
ok ← TRUE; found ← d;
};
};
EachDesign: CDPrivate.DesignEnumerator = {
cache: CD.Design;
IF ~RefTab.Insert[seen, design, NIL] THEN RETURN;
IF design.mutability=readonly AND Rope.Equal[design.name, remoteName] THEN {
IF Check[design].ok THEN RETURN [quit←TRUE];
RETURN;
};
cache ← Fetch[for: design, remoteName: remoteName];
IF cache#NIL AND RefTab.Insert[seen, cache, NIL] THEN
IF Check[cache].ok THEN RETURN [quit←TRUE];
};
seen: RefTab.Ref ← RefTab.Create[5];
IF fileName#NIL THEN fileName ← FileNames.ConvertToSlashFormat[fileName];
[] ← CDPrivate.EnumDesigns[EachDesign];
};
GetOrRead: PUBLIC PROC [for: CD.Design, remoteName: Rope.ROPE, remoteFile: Rope.ROPENIL, reload: BOOLFALSE, checkFile: BOOLTRUE, check: CDDesignCache.CheckProc←NIL, data: REFNIL] RETURNS [remote: CD.Design←NIL, different: BOOLFALSE] = {
remote ← Fetch[for, remoteName];
IF remote=NIL OR reload THEN {
d: CD.Design ← DoLoad[for, remoteName, remoteFile, checkFile, check, data];
IF different ← (d#NIL AND remote#d) THEN Set[for, remote𡤍];
};
};
DoLoad: PROC [for: CD.Design, remoteName: Rope.ROPE, fileName: Rope.ROPENIL, checkFile: BOOL, check: CDDesignCache.CheckProc, data: REF] RETURNS [design: CD.Design←NIL] = {
IOCheck: PROC [h: TokenIO.Handle] RETURNS [ok: BOOL] = {
design: CD.Design ← CDIO.DesignInReadOperation[h];
IF design.technology#for.technology THEN {
TerminalIO.PutF["**technology missmatch: remote design is %g",
IO.rope[design.technology.name]
];
RETURN [FALSE]
};
ok ← Rope.Equal[remoteName, design.name];
IF ~ok THEN
TerminalIO.PutF["file %g has different design: %g\n",
IO.rope[fileName],
IO.rope[CD.DesignName[design]]
];
};
SearchCheck: CDDesignCache.CheckProc = {
ok ← design.technology=for.technology;
IF ok AND check#NIL THEN ok ← check[design, data];
};
foundFile: Rope.ROPENIL; x: REF;
time: BasicTime.GMT ← BasicTime.nullGMT;
TerminalIO.PutRopes["load remote design ", remoteName, "\n"];
IF Rope.IsEmpty[fileName] THEN fileName ← MakeUpFile[for, remoteName];
IF checkFile THEN {
foundFile ← CDEnvironment.FindFile[fileName, ".dale", for];
IF Rope.IsEmpty[foundFile] THEN {
TerminalIO.PutRopes[" not done; file ", fileName, " not found\n"];
RETURN
};
time ← FS.FileInfo[name: foundFile, remoteCheck: FALSE ! FS.Error => CONTINUE].created;
};
design ← Search[remoteName, foundFile, time, SearchCheck, data];
IF design#NIL THEN RETURN [design];
IF foundFile#NIL THEN fileName ← foundFile;
design ← CDIO.ReadDesign[fileName, IOCheck];
IF design#NIL THEN {
CDOps.SetMutability[design, readonly];
x ← CDValue.Fetch[design, $CDxFromFile, design];
CDValue.Store[design, $CDxCachedFile, x];
x ← CDValue.Fetch[design, $CDxFileCreated, design];
CDValue.Store[design, $CDxCachedCreated, x];
TerminalIO.PutRopes[" ", remoteName, " loaded\n"];
};
};
MakeUpFile: PUBLIC PROC [for: CD.Design, remoteName: Rope.ROPE] RETURNS [fileName: Rope.ROPENIL] = {
GetHintList: PROC [for: CD.Design] RETURNS [LIST OF Rope.ROPENIL] = {
IF for#NIL THEN
WITH CDProperties.GetDesignProp[for, $ImportHints] SELECT FROM
rL: LIST OF Rope.ROPE => RETURN [rL];
ENDCASE => NULL;
};
RemSpaces: PROC [r: Rope.ROPE] RETURNS [Rope.ROPENIL] = {
leng: INT ← Rope.Length[r];
start: INT ← 0;
WHILE start<leng AND Rope.Fetch[r, start]=' DO start ← start+1 ENDLOOP;
WHILE leng>start AND Rope.Fetch[r, leng-1]=' DO leng ← leng-1 ENDLOOP;
IF leng>start THEN RETURN [Rope.Substr[r, start, leng-start]];
};
rl: LIST OF Rope.ROPE ← GetHintList[for];
key, rest: Rope.ROPENIL;
FOR list: LIST OF Rope.ROPE ← rl, list.rest WHILE list#NIL DO
[key, rest] ← CDEnvironment.SplitLine[list.first];
IF Rope.Equal[remoteName, key] THEN RETURN [RemSpaces[rest]];
ENDLOOP;
fileName ← UserProfile.Token[Rope.Cat["ChipNDale.ImportFor.", remoteName], remoteName];
};
END.