DIRECTORY CD, CDGenerate, CDGenerateBackdoor, CDDirectory, CDIO, CDProperties, CDRemote, CDValue, FileNames, RefTab, Rope, SymTab, TerminalIO; CDRemoteImpl: CEDAR PROGRAM IMPORTS CDGenerate, CDGenerateBackdoor, CDDirectory, CDIO, CDProperties, CDValue, FileNames, RefTab, Rope, SymTab, TerminalIO EXPORTS CDRemote = BEGIN dummy: CDGenerate.Table _ CDGenerate.Create[]; tableToName: RefTab.Ref _ RefTab.Create[]; -- table ==> remote design name NameRec: TYPE = RECORD [name: Rope.ROPE, key: REF]; nameToTable: SymTab.Ref _ SymTab.Create[]; -- remote design name ==> table UnspecSelector: CDGenerateBackdoor.SelectorProc = { key _ TerminalIO.RequestRope[" include [design.oject] >"]; }; Selector: CDGenerateBackdoor.SelectorProc = { dName: Rope.ROPE = DesignName[table]; key _ TerminalIO.RequestRope[Rope.Cat[label, " include oject from ", dName, " >"]]; }; UnspecRemoteIGenerator: CDGenerateBackdoor.IGeneratorProc = BEGIN dotIndex: INT; remoteName, objectName: Rope.ROPE _ NIL; name: Rope.ROPE _ FileNames.GetShortName[key]; dotIndex _ Rope.Index[name, 0, "."]; --the first dot! multiple dots belong to the object name IF dotIndex < Rope.Length[name] THEN { objectName _ Rope.Substr[name, dotIndex+1]; remoteName _ Rope.Substr[name, 0, dotIndex] }; IF ~Rope.IsEmpty[remoteName] AND ~Rope.IsEmpty[objectName] THEN { table: CDGenerate.Table _ GetTable[remoteName]; ob _ CDGenerate.FetchNCall[table, design, objectName]; } ELSE TerminalIO.WriteRopes["**tried to access remote with bad syntax; [", key, "]\n"]; END; GetTable: PUBLIC PROC [remoteDesign: Rope.ROPE] RETURNS [table: CDGenerate.Table_NIL] = TRUSTED BEGIN IF Rope.IsEmpty[remoteDesign] THEN ERROR; WITH nameToTable.Fetch[remoteDesign].val SELECT FROM t: CDGenerate.Table => RETURN [t] ENDCASE => NULL; table _ CDGenerateBackdoor.CreateIndirect[onTopOf: dummy, iGenerator: RemoteIGenerator, selector: Selector, cache: TRUE, flushThrough: FALSE, clearThrough: FALSE, registerThrough: FALSE]; [] _ tableToName.Insert[LOOPHOLE[table], NEW[NameRec _ [name: remoteDesign, key: NEW[INT]] ] ]; IF nameToTable.Insert[remoteDesign, LOOPHOLE[table]] THEN RETURN; RETURN [GetTable[remoteDesign]] --indirection for concurrency problems END; ioFailed: PUBLIC SIGNAL = CODE; GetTableUsingFile: PUBLIC PROC [for: CD.Design, remoteDesign: Rope.ROPE, remoteFile: Rope.ROPE _ NIL, reload: BOOL _ FALSE] RETURNS [CDGenerate.Table] = BEGIN remote: CD.Design _ NIL; IF ~reload THEN remote _ FetchDesign[for, remoteDesign]; IF remote=NIL THEN { remote _ DoLoad[importer: for, remoteName: remoteDesign, fileName: remoteFile]; IF remote#NIL THEN CacheDesign[for, remote] ELSE SIGNAL ioFailed; }; RETURN [ GetTable[remoteDesign] ]; END; Get: PUBLIC PROC [for: CD.Design, remoteDesign: Rope.ROPE, object: Rope.ROPE] RETURNS [ob: CD.Object] = BEGIN table: CDGenerate.Table = GetTable[remoteDesign]; ob _ CDGenerate.FetchNCall[table, for, object]; END; RemoteInfo: PROC [table: CDGenerate.Table] RETURNS [r: REF NameRec_NIL] = TRUSTED BEGIN WITH tableToName.Fetch[LOOPHOLE[table]].val SELECT FROM rn: REF NameRec => RETURN [rn]; ENDCASE => { table _ CDGenerateBackdoor.Indiretee[table]; IF table#NIL THEN RETURN[RemoteInfo[table]] }; END; DesignName: PUBLIC PROC [table: CDGenerate.Table] RETURNS [r: Rope.ROPE_NIL] = BEGIN rn: REF NameRec _ RemoteInfo[table]; IF rn#NIL THEN RETURN [rn.name] END; RemoteIGenerator: CDGenerateBackdoor.IGeneratorProc = BEGIN replaceList: CDDirectory.ReplaceList _ NIL; GetOrLoad: PROC [importer: CD.Design, remoteInfo: REF NameRec] RETURNS [design: CD.Design_NIL] = BEGIN IF remoteInfo=NIL OR Rope.IsEmpty[remoteInfo.name] THEN { TerminalIO.WriteRope["**generate with bad remote name\n"]; RETURN }; WITH CDValue.Fetch[boundTo: importer, key: remoteInfo.key] SELECT FROM d: CD.Design => design _ d; ENDCASE => NULL; IF design=NIL THEN { design _ DoLoad[importer, remoteInfo.name]; CDValue.Store[boundTo: importer, key: remoteInfo.key, value: design]; }; END; EachChild: CDDirectory.EnumerateObjectsProc = -- PROC [me: CD.Object, x: REF] -- BEGIN IF me.class.inDirectory THEN { name: Rope.ROPE _ CDDirectory.Name[me]; ob1: CD.Object _ CDGenerate.FetchNCall[realTable, design, name];--will be cached! replaceRec: REF CDDirectory.ReplaceRec _ NEW[CDDirectory.ReplaceRec _ [ old: me, oldSize: me.size, new: ob1, newSize: ob1.size, off: [0, 0] ]]; replaceList _ CONS[replaceRec, replaceList]; } END; remoteDesign: CD.Design; remoteInfo: REF NameRec _ RemoteInfo[passTable]; IF Rope.Equal[remoteInfo.name, design.name] THEN { ob _ CDDirectory.Fetch[design, key].object; RETURN }; remoteDesign _ GetOrLoad[design, remoteInfo]; IF remoteDesign#NIL THEN { rob: CD.Object _ CDDirectory.Fetch[remoteDesign, key].object; IF rob#NIL THEN { tm, cm: CDDirectory.DMode; [ob, tm, cm] _ CDDirectory.Another[me: rob, fromOrNil: remoteDesign, into: design]; IF ob#NIL THEN { IF cm=immutable THEN { CDDirectory.EnumerateChildObjects[me: ob, p: EachChild]; IF replaceList#NIL THEN [] _ CDDirectory.ReplaceDirectChild[me: ob, design: design, replace: replaceList]; }; IF tm=ready THEN [] _ CDDirectory.Include[design: design, object: ob]; CDProperties.PutObjectProp[ob, $CameFrom, remoteDesign.name]; CDProperties.PutObjectProp[ob, $OriginalName, key]; RETURN [ob] }; }; }; END; CacheDesign: PUBLIC PROC [for: CD.Design, remote: CD.Design] = BEGIN rn: REF NameRec; IF for.technology#remote.technology THEN ERROR; rn _ RemoteInfo[GetTable[remote.name]]; IF rn#NIL THEN CDValue.Store[boundTo: for, key: rn.key, value: remote] ELSE TerminalIO.WriteRope["**CacheRemoteDesign failed; debugging is appropriate\n"]; END; FetchDesign: PUBLIC PROC [for: CD.Design, name: Rope.ROPE] RETURNS [remote: CD.Design _ NIL] = BEGIN rn: REF NameRec _ RemoteInfo[GetTable[name]]; WITH CDValue.Fetch[boundTo: for, key: rn.key, propagation: design] SELECT FROM d: CD.Design => remote _ d ENDCASE => NULL; END; DoLoad: PROC [importer: CD.Design, remoteName: Rope.ROPE, fileName: Rope.ROPE_NIL] RETURNS [design: CD.Design_NIL] = BEGIN checkWasCalled: BOOL _ FALSE; Check: PROC [design: CD.Design] RETURNS [ok: BOOL] = BEGIN checkWasCalled _ TRUE; IF ok _ design.technology=importer.technology THEN { ok _ Rope.Equal[remoteName, CDIO.DesignInReadOperation[].name]; IF NOT ok THEN TerminalIO.WriteRope[Rope.Cat["file """, fileName, """ has different design: """, CDIO.DesignInReadOperation[].name, """\n"]]; } ELSE TerminalIO.WriteRopes["**Technology missmatch: remote design is ", design.technology.name, "\n"]; END; name1: Rope.ROPE; TerminalIO.WriteRopes["load remote design ", remoteName, "\n"]; IF Rope.IsEmpty[fileName] THEN fileName _ remoteName; name1 _ CDIO.MakeName[base: fileName, ext: "dale", wDir: CDIO.GetWorkingDirectory[importer]]; design _ CDIO.ReadDesign[name1, Check]; IF ~checkWasCalled AND design=NIL THEN { name2: Rope.ROPE _ CDIO.MakeName[base: fileName, ext: "dale", wDir: CDIO.GetWorkingDirectory[NIL]]; IF ~Rope.Equal[name1, name2, FALSE] THEN design _ CDIO.ReadDesign[name2, Check]; }; TerminalIO.WriteRopes["loading remote design ", (IF design#NIL THEN "done\n" ELSE "not done\n")]; END; unspecRemoteTable: CDGenerate.Table _ CDGenerateBackdoor.CreateIndirect[ onTopOf: dummy, iGenerator: UnspecRemoteIGenerator, selector: UnspecSelector ]; TRUSTED { [] _ SymTab.Insert[CDGenerateBackdoor.publicTables, "INCLUDE", LOOPHOLE[unspecRemoteTable]]; }; [] _ CDProperties.RegisterAndInstall[$CameFrom, [autoRem: TRUE]]; [] _ CDProperties.RegisterAndInstall[$OriginalName, [autoRem: TRUE]]; END. ώCDRemoteImpl.mesa (part of ChipNDale) Copyright c 1985 by Xerox Corporation. All rights reserved. by Christian Jacobi, June 5, 1985 8:02:35 pm PDT Last Edited by: Jacobi July 23, 1986 3:00:32 pm PDT Last edited by: Christian Jacobi, October 16, 1986 5:33:17 pm PDT --implements two methods of generator tables --tables as exported from CDRemote: selecting an object from one specific remote design --table "INCLUDE": generator key is designName.objectName; for any designName -- entries of type REF NameRec --this one even does not know what design to use --Creates a generator table, "generating" = fetching an object from the remote design. --Reads remoteDesign if necessary or reload -- remoteFile defaults to remoteDesign -- re-reading may cause children objects to be duplicated --test for silly case of using same design name --caller MUST guarantee: remote will NEVER be changed -- (but a different design with the same name might be cached later...) --CDRemote guarantees: it will never change remote Κ ­˜codešœ%™%Kšœ Οmœ1™Kšœ5™5KšœH™HKšœ4™4Kšž˜Kšœžœ ˜Kšžœ"žœžœ˜/Kšœ'˜'Kšžœžœžœ8˜Fšžœ˜KšœO˜O—Kšžœ˜K˜—š’ œžœžœžœžœžœ žœ žœ˜^Kšž˜Kšœžœ&˜-šžœ?žœž˜NKšœžœ˜Kšžœžœ˜—Kšžœ˜K˜—K˜š’œžœ žœžœžœžœžœ žœžœ˜tKšž˜Kšœžœžœ˜K˜š ’œžœ žœ žœžœ˜4Kšž˜Kšœžœ˜šžœ,žœ˜4Kšœžœ˜?KšžœžœžœTžœ(˜ŽK˜—Kšžœb˜fKšž˜—K˜Kšœ žœ˜Kšœ?˜?Kšžœžœ˜5Kšœžœ-žœ ˜]Kšœ žœ˜'šžœžœžœžœ˜)Kš œ žœžœ-žœžœ˜cKšžœžœžœ žœ˜PK˜—Kš œ1žœžœžœ žœ˜aKšžœ˜—K˜K˜Kšœš˜ššžœ˜ Kšœ?žœ˜\Kšœ˜—Kšœ:žœ˜AKšœ>žœ˜EKšžœ˜K˜—…—4*ί