DIRECTORY Atom, CedarProcess, Convert, Core, CoreClasses, CoreIO, CoreOps, CoreProperties, FS, HashTable, IO, Rope; CoreIOImpl: CEDAR PROGRAM IMPORTS Atom, CedarProcess, Convert, CoreClasses, CoreOps, CoreProperties, FS, HashTable, IO, Rope EXPORTS CoreIO SHARES Core = BEGIN OPEN CoreIO; CoreWriteProcProp: ATOM = $CoreWriteProc; CoreReadProcProp: ATOM = $CoreReadProc; classRegistry: HashTable.Table _ HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope]; UnknownProperty: PUBLIC SIGNAL [propKey: ATOM] = CODE; UnknownCellClass: PUBLIC SIGNAL [class: Core.CellClass] = CODE; ReportSaveCellType: PUBLIC PROC [cellType: Core.CellType, fileName: ROPE _ NIL] RETURNS [props: LIST OF ATOM _ NIL, classes: LIST OF Core.CellClass _ NIL] = { SaveCellType[cellType, fileName ! UnknownProperty => { FOR pl: LIST OF ATOM _ props, pl.rest UNTIL pl=NIL DO IF pl.first=propKey THEN EXIT; REPEAT FINISHED => props _ CONS[propKey, props]; ENDLOOP; RESUME; }; UnknownCellClass => { FOR cl: LIST OF Core.CellClass _ classes, cl.rest UNTIL cl=NIL DO IF cl.first=class THEN EXIT; REPEAT FINISHED => classes _ CONS[class, classes]; ENDLOOP; RESUME; }]; }; SaveCellType: PUBLIC PROC [cellType: Core.CellType, fileName: ROPE _ NIL] = { h: Handle _ NEW [HandleRec]; IF fileName=NIL THEN fileName _ Rope.Cat[CoreOps.GetCellTypeName[cellType], ".core"]; h.stream _ FS.StreamOpen[fileName, $create]; h.cellTypeIDTab _ HashTable.Create[]; h.ropeIDTab _ HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope]; h.atomIDTab _ HashTable.Create[]; WriteCellType[h, cellType]; IO.Close[h.stream]; }; importCellClass: PUBLIC Core.CellClass _ CoreOps.SetClassPrintProc[NEW [Core.CellClassRec _ [name: "Import", recast: RecastImport, layersProps: TRUE]], PrintImport]; RestoreCellType: PUBLIC PROC [cellName: ROPE _ NIL, fileName: ROPE _ NIL] RETURNS [cellType: Core.CellType] = { h: Handle _ NEW[HandleRec]; IF fileName=NIL AND cellName=NIL THEN ERROR; IF fileName=NIL THEN fileName _ Rope.Cat[cellName, ".core"]; h.fileName _ fileName; h.stream _ FS.StreamOpen[fileName]; h.cellTypeIDTab _ HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope]; h.ropeIDTab _ HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope]; h.atomIDTab _ HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope]; [cellType, h.wireIDTab] _ ReadCellTypePublic[h]; cellType.class _ importCellClass; cellType.data _ h; }; RecastImport: Core.RecastProc = { h: Handle _ NARROW [me.data]; me.data _ NIL; ReadCellTypeRest[h, me, h.wireIDTab]; new _ me; }; PrintImport: CoreOps.PrintClassProc = { h: Handle _ NARROW [data]; CoreOps.PrintIndent[indent, out]; IO.PutF[out, "Import of : %g", IO.rope[h.fileName]]; }; WriteImport: ClassWriteProc = { WriteWireIDPair: HashWriteProc = { id: ROPE _ NARROW[key]; wire: Core.Wire _ NARROW[value]; WriteID[h, id]; WriteWire[h, wireIDTab, wire]; }; child: Handle _ NARROW [cellType.data]; WriteRope[h, child.fileName]; WriteInt[h, IO.GetIndex[child.stream]]; WriteHashTable[h, child.cellTypeIDTab, WriteCellTypeIDPair]; WriteHashTable[h, child.ropeIDTab, WriteRopeIDPair]; WriteHashTable[h, child.atomIDTab, WriteAtomIDPair]; WriteHashTable[h, child.wireIDTab, WriteWireIDPair]; WriteProperties[h, child.properties]; }; ReadImport: ClassReadProc = { ReadWireIDPair: HashReadProc = { key _ ReadID[h]; value _ ReadWire[h, wireIDTab]; }; child: Handle _ NEW[HandleRec]; child.cellType _ NIL; -- I'm not sure what's right here child.wire _ NIL; -- I'm not sure what's right here child.fileName _ ReadRope[h]; child.stream _ FS.StreamOpen[child.fileName]; IO.SetIndex[child.stream, ReadInt[h]]; child.cellTypeIDTab _ ReadHashTable[h, ReadCellTypeIDPair, HashTable.RopeEqual, HashTable.HashRope]; child.ropeIDTab _ ReadHashTable[h, ReadRopeIDPair, HashTable.RopeEqual, HashTable.HashRope]; child.atomIDTab _ ReadHashTable[h, ReadAtomIDPair, HashTable.RopeEqual, HashTable.HashRope]; child.wireIDTab _ ReadHashTable[h, ReadWireIDPair, HashTable.RopeEqual, HashTable.HashRope]; child.properties _ ReadProperties[h]; cellType.data _ child; }; RegisterClass: PUBLIC PROC [class: Core.CellClass, write: ClassWriteProc, read: ClassReadProc] RETURNS [sameClass: Core.CellClass] = { sameClass _ class; CoreProperties.PutCellClassProp[class, CoreWriteProcProp, NEW[ClassWriteProc _ write]]; CoreProperties.PutCellClassProp[class, CoreReadProcProp, NEW[ClassReadProc _ read]]; [] _ HashTable.Store[classRegistry, class.name, class]; }; RegisterProperty: PUBLIC PROC [prop: ATOM, write: PropWriteProc, read: PropReadProc] RETURNS [sameProp: ATOM] = { props: Core.Properties _ CoreProperties.FetchProperties[prop]; props _ CoreProperties.PutProp[props, CoreWriteProcProp, NEW[PropWriteProc _ write]]; props _ CoreProperties.PutProp[props, CoreReadProcProp, NEW[PropReadProc _ read]]; CoreProperties.StoreProperties[prop, props]; sameProp _ prop; }; WriteCellType: PUBLIC PROC [h: Handle, cellType: Core.CellType] = { cellTypeID: ROPE _ NARROW [HashTable.Fetch[h.cellTypeIDTab, cellType].value]; IF cellTypeID=NIL THEN { parentCellType: Core.CellType _ h.cellType; wireIDTab: HashTable.Table _ HashTable.Create[]; classWrite: REF ClassWriteProc _ NARROW[CoreProperties.GetCellClassProp[from: cellType.class, prop: CoreWriteProcProp]]; IF classWrite=NIL THEN { SIGNAL UnknownCellClass[cellType.class]; cellType _ CoreOps.Recast[cellType]; IF cellType=NIL THEN ERROR; WriteCellType[h, cellType]; RETURN; }; cellTypeID _ Rope.Cat["C", Convert.RopeFromInt[from: HashTable.GetSize[h.cellTypeIDTab], base: 16, showRadix: FALSE]]; IF NOT HashTable.Insert[h.cellTypeIDTab, cellType, cellTypeID] THEN ERROR; h.cellType _ cellType; WriteID[h, cellTypeID]; WriteWire[h, wireIDTab, cellType.public]; WriteProperties[h, cellType.properties]; WriteRope[h, cellType.class.name]; classWrite^[h, cellType, wireIDTab]; h.cellType _ parentCellType; } ELSE WriteID[h, cellTypeID]; }; ReadCellType: PUBLIC PROC [h: Handle] RETURNS [cellType: Core.CellType] = { wireIDTab: HashTable.Table _ NIL; parentCellType: Core.CellType _ h.cellType; [cellType, wireIDTab] _ ReadCellTypePublic[h]; IF wireIDTab#NIL THEN ReadCellTypeRest[h, cellType, wireIDTab]; h.cellType _ parentCellType; }; ReadCellTypePublic: PUBLIC PROC [h: Handle] RETURNS [cellType: Core.CellType, wireIDTab: HashTable.Table] = { cellTypeID: ROPE _ ReadID[h]; IF Rope.Fetch[cellTypeID]#'C THEN ERROR; cellType _ NARROW[HashTable.Fetch[h.cellTypeIDTab, cellTypeID].value]; IF cellType=NIL THEN { cellType _ NEW[Core.CellTypeRec]; IF NOT HashTable.Insert[h.cellTypeIDTab, cellTypeID, cellType] THEN ERROR; h.cellType _ cellType; wireIDTab _ HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope]; cellType.public _ ReadWire[h, wireIDTab]; cellType.properties _ ReadProperties[h]; }; }; ReadCellTypeRest: PUBLIC PROC [h: Handle, cellType: Core.CellType, wireIDTab: HashTable.Table] = { className: ROPE _ ReadRope[h]; classRead: REF ClassReadProc _ NIL; cellType.class _ NARROW[HashTable.Fetch[classRegistry, className].value]; classRead _ NARROW[CoreProperties.GetCellClassProp[from: cellType.class, prop: CoreReadProcProp]]; classRead^[h, cellType, wireIDTab]; }; WriteWire: PUBLIC PROC [h: Handle, wireIDTab: HashTable.Table, wire: Core.Wire] = { wireID: ROPE _ NARROW[HashTable.Fetch[wireIDTab, wire].value]; IF wireID=NIL THEN { parentWire: Core.Wire _ h.wire; wireID _ Rope.Cat["W", Convert.RopeFromInt[from: HashTable.GetSize[wireIDTab], base: 16, showRadix: FALSE]]; IF NOT HashTable.Insert[wireIDTab, wire, wireID] THEN ERROR; WriteID[h, wireID]; WriteInt[h, wire.size]; h.wire _ wire; WriteProperties[h, wire.properties]; FOR w: NAT IN [0..wire.size) DO WriteWire[h, wireIDTab, wire[w]]; ENDLOOP; h.wire _ parentWire; } ELSE WriteID[h, wireID]; }; ReadWire: PUBLIC PROC [h: Handle, wireIDTab: HashTable.Table] RETURNS [wire: Core.Wire] = { wireID: ROPE _ ReadID[h]; IF Rope.Fetch[wireID]#'W THEN ERROR; wire _ NARROW[HashTable.Fetch[wireIDTab, wireID].value]; IF wire=NIL THEN { parentWire: Core.Wire _ h.wire; wireSize: NAT _ ReadInt[h]; wire _ NEW[Core.WireRec[wireSize]]; IF NOT HashTable.Insert[wireIDTab, wireID, wire] THEN ERROR; h.wire _ wire; wire.properties _ ReadProperties[h]; FOR w: NAT IN [0..wire.size) DO wire[w] _ ReadWire[h, wireIDTab]; ENDLOOP; h.wire _ parentWire; }; }; WriteProperties: PUBLIC PROC [h: Handle, properties: Core.Properties] = { propCount: INT _ 0; CedarProcess.CheckAbort[]; FOR props: Core.Properties _ properties, props.rest UNTIL props=NIL DO propKey: ATOM _ NARROW[props.first.key]; propVal: REF ANY _ props.first.val; propWrite: REF PropWriteProc _ NARROW[CoreProperties.GetProp[from: CoreProperties.FetchProperties[propKey], prop: CoreWriteProcProp]]; IF propWrite#NIL OR ISTYPE[propVal, ROPE] OR ISTYPE[propVal, LIST OF ROPE] OR ISTYPE[propVal, REF INT] OR ISTYPE[propVal, REF NAT] OR ISTYPE[propVal, ATOM] OR ISTYPE[propVal, REF REAL] THEN propCount _ propCount + 1; ENDLOOP; WriteInt[h, propCount]; FOR props: Core.Properties _ properties, props.rest UNTIL props=NIL DO StartProp: PROC [type: ROPE] = { WriteAtom[h, propKey]; IF type#NIL THEN WriteID[h, type]; }; propKey: ATOM _ NARROW[props.first.key]; propWrite: REF PropWriteProc _ NARROW[CoreProperties.GetProp[from: CoreProperties.FetchProperties[propKey], prop: CoreWriteProcProp]]; IF propWrite=NIL THEN WITH props.first.val SELECT FROM r: ROPE => {StartProp["r"]; WriteRope[h, r]}; lor: LIST OF ROPE => {StartProp["lor"]; WriteListOfRope[h, lor]}; i: REF INT => {StartProp["i"]; IO.PutF[h.stream, "%g ", IO.int[i^]]}; n: REF NAT => {StartProp["n"]; IO.PutF[h.stream, "%g ", IO.int[n^]]}; a: ATOM => {StartProp["a"]; WriteAtom[h, a]}; real: REF REAL => {StartProp["real"]; IO.PutF[h.stream, "%g ", IO.real[real^]]}; ENDCASE => SIGNAL UnknownProperty[propKey] ELSE {StartProp[NIL]; propWrite^[h, propKey, props.first.val]}; ENDLOOP; }; ReadProperties: PUBLIC PROC [h: Handle] RETURNS [properties: Core.Properties _ NIL] = { propCount: INT _ ReadInt[h]; CedarProcess.CheckAbort[]; FOR c: INT IN [0..propCount) DO key: ATOM _ ReadAtom[h]; val: REF ANY; propRead: REF PropReadProc _ NARROW[CoreProperties.GetProp[from: CoreProperties.FetchProperties[key], prop: CoreReadProcProp]]; IF propRead=NIL THEN { type: ROPE _ ReadID[h]; val _ SELECT TRUE FROM Rope.Equal["r", type] => ReadRope[h], Rope.Equal["lor", type] => ReadListOfRope[h], Rope.Equal["i", type] => NEW[INT _ IO.GetInt[h.stream]], Rope.Equal["n", type] => NEW[NAT _ IO.GetInt[h.stream]], Rope.Equal["a", type] => ReadAtom[h], Rope.Equal["real", type] => NEW[REAL _ IO.GetReal[h.stream]], ENDCASE => ERROR UnknownProperty[Atom.MakeAtom[type]]; } ELSE val _ propRead^[h, key]; properties _ CONS[[key, val], properties]; ENDLOOP; }; WriteID: PUBLIC PROC [h: Handle, id: ROPE] = { IO.PutRope[h.stream, id]; IO.PutRope[h.stream, " "]; }; ReadID: PUBLIC PROC [h: Handle] RETURNS [id: ROPE] = { id _ IO.GetID[h.stream]; }; WriteAtom: PUBLIC PROC [h: Handle, atom: ATOM] = { atomID: ROPE _ NARROW[HashTable.Fetch[h.atomIDTab, atom].value]; IF atomID=NIL THEN { atomID _ Rope.Cat["A", Convert.RopeFromInt[from: HashTable.GetSize[h.atomIDTab], base: 16, showRadix: FALSE]]; IF NOT HashTable.Insert[h.atomIDTab, atom, atomID] THEN ERROR; WriteID[h, atomID]; IO.PutF[h.stream, "%g ", IO.atom[atom]]; } ELSE WriteID[h, atomID]; }; ReadAtom: PUBLIC PROC [h: Handle] RETURNS [atom: ATOM] = { atomID: ROPE _ ReadID[h]; IF Rope.Fetch[atomID]#'A THEN ERROR; atom _ NARROW[HashTable.Fetch[h.atomIDTab, atomID].value]; IF atom=NIL THEN { atom _ IO.GetAtom[h.stream]; IF NOT HashTable.Insert[h.atomIDTab, atomID, atom] THEN ERROR; }; }; WriteRope: PUBLIC PROC [h: Handle, rope: ROPE] = { ropeID: ROPE _ NARROW[HashTable.Fetch[h.ropeIDTab, rope].value]; IF ropeID=NIL THEN { ropeID _ Rope.Cat["R", Convert.RopeFromInt[from: HashTable.GetSize[h.ropeIDTab], base: 16, showRadix: FALSE]]; IF NOT HashTable.Insert[h.ropeIDTab, rope, ropeID] THEN ERROR; WriteID[h, ropeID]; IO.PutRope[h.stream, "\""]; IO.PutRope[h.stream, rope]; -- cannot use IO.PutF that truncates long ropes! IO.PutRope[h.stream, "\" "]; } ELSE WriteID[h, ropeID]; }; ReadRope: PUBLIC PROC [h: Handle] RETURNS [rope: ROPE] = { ropeID: ROPE _ ReadID[h]; IF Rope.Fetch[ropeID]#'R THEN ERROR; rope _ NARROW[HashTable.Fetch[h.ropeIDTab, ropeID].value]; IF rope=NIL THEN { rope _ IO.GetRopeLiteral[h.stream]; IF NOT HashTable.Insert[h.ropeIDTab, ropeID, rope] THEN ERROR; }; }; WriteListOfRope: PUBLIC PROC [h: Handle, ropes: LIST OF ROPE] = { count: INT _ 0; FOR rl: LIST OF ROPE _ ropes, rl.rest UNTIL rl=NIL DO count _ count + 1; ENDLOOP; WriteInt[h, count]; FOR rl: LIST OF ROPE _ ropes, rl.rest UNTIL rl=NIL DO WriteRope[h, rl.first]; ENDLOOP; }; ReadListOfRope: PUBLIC PROC [h: Handle] RETURNS [ropes: LIST OF ROPE] = { count: INT _ ReadInt[h]; lor: LIST OF ROPE _ NIL; FOR c: INT IN [0..count) DO lor _ CONS[ReadRope[h], lor]; ENDLOOP; FOR rl: LIST OF ROPE _ lor, rl.rest UNTIL rl=NIL DO ropes _ CONS[rl.first, ropes]; ENDLOOP; }; WriteInt: PUBLIC PROC [h: Handle, int: INT] = { IO.PutF[h.stream, "%g ", IO.int[int]]; }; ReadInt: PUBLIC PROC [h: Handle] RETURNS [int: INT] = { int _ IO.GetInt[h.stream]; }; WriteReal: PUBLIC PROC [h: Handle, real: REAL] = { IO.PutF[h.stream, "%g ", IO.int[LOOPHOLE[real]]]; }; ReadReal: PUBLIC PROC [h: Handle] RETURNS [real: REAL] = { real _ LOOPHOLE[IO.GetInt[h.stream]]; }; WriteBool: PUBLIC PROC [h: Handle, bool: BOOL] = { IO.PutChar[h.stream, IF bool THEN 'T ELSE 'F]; IO.PutChar[h.stream, ' ]; }; ReadBool: PUBLIC PROC [h: Handle] RETURNS [bool: BOOL] = { bool _ SELECT IO.GetChar[h.stream] FROM 'T => TRUE, 'F => FALSE, ENDCASE => ERROR; [] _ IO.GetChar[h.stream]; }; WriteHashTable: PUBLIC PROC [h: Handle, table: HashTable.Table, eachPair: HashWriteProc] = { HashPair: HashTable.EachPairAction = { eachPair[h, key, value]; }; WriteInt[h, HashTable.GetSize[table]]; IF HashTable.Pairs[table, HashPair] THEN ERROR; }; ReadHashTable: PUBLIC PROC [h: Handle, eachPair: HashReadProc, equal: HashTable.EqualProc _ NIL, hash: HashTable.HashProc _ NIL] RETURNS [table: HashTable.Table] = { table _ HashTable.Create[equal: equal, hash: hash]; THROUGH [1..ReadInt[h]] DO key, value: REF ANY _ NIL; [key, value] _ eachPair[h]; IF NOT HashTable.Insert[table, key, value] THEN ERROR; ENDLOOP; }; WriteCellTypeIDPair: PUBLIC HashWriteProc = { id: ROPE _ NARROW[key]; cellType: Core.CellType _ NARROW[value]; WriteID[h, id]; WriteCellType[h, cellType]; }; ReadCellTypeIDPair: PUBLIC HashReadProc = { key _ ReadID[h]; value _ ReadCellType[h]; }; WriteRopeIDPair: PUBLIC HashWriteProc = { id: ROPE _ NARROW[key]; rope: ROPE _ NARROW[value]; WriteID[h, id]; WriteRope[h, rope]; }; ReadRopeIDPair: PUBLIC HashReadProc = { key _ ReadID[h]; value _ ReadRope[h]; }; WriteAtomIDPair: PUBLIC HashWriteProc = { id: ROPE _ NARROW[key]; atom: ATOM _ NARROW[value]; WriteID[h, id]; WriteAtom[h, atom]; }; ReadAtomIDPair: PUBLIC HashReadProc = { key _ ReadID[h]; value _ ReadAtom[h]; }; WriteRecordCell: ClassWriteProc = { rct: CoreClasses.RecordCellType _ NARROW[cellType.data]; WriteInt[h, rct.size]; WriteWire[h, wireIDTab, rct.internal]; FOR in: NAT IN [0..rct.size) DO instance: CoreClasses.CellInstance _ rct[in]; WriteWire[h, wireIDTab, instance.actual]; WriteProperties[h, instance.properties]; WriteCellType[h, instance.type]; ENDLOOP; }; ReadRecordCell: ClassReadProc = { rct: CoreClasses.RecordCellType _ NEW[CoreClasses.RecordCellTypeRec[ReadInt[h]]]; rct.internal _ ReadWire[h, wireIDTab]; FOR in: NAT IN [0..rct.size) DO instance: CoreClasses.CellInstance _ NEW[CoreClasses.CellInstanceRec]; rct[in] _ instance; instance.actual _ ReadWire[h, wireIDTab]; instance.properties _ ReadProperties[h]; instance.type _ ReadCellType[h]; ENDLOOP; cellType.data _ rct; }; WriteTransistor: ClassWriteProc = { tran: CoreClasses.Transistor _ NARROW[cellType.data]; WriteID[h, CoreClasses.transistorTypeNames[tran.type]]; WriteInt[h, tran.length]; WriteInt[h, tran.width]; }; ReadTransistor: ClassReadProc = { tran: CoreClasses.Transistor _ NEW[CoreClasses.TransistorRec]; type: ROPE _ ReadID[h]; FOR t: CoreClasses.TransistorType IN CoreClasses.TransistorType DO IF Rope.Equal[CoreClasses.transistorTypeNames[t], type] THEN { tran.type _ t; EXIT; }; REPEAT FINISHED => ERROR; ENDLOOP; tran.length _ ReadInt[h]; tran.width _ ReadInt[h]; cellType.data _ tran; }; WriteUnspecified: ClassWriteProc = {}; ReadUnspecified: ClassReadProc = {cellType.data _ NIL}; WriteSequence: ClassWriteProc = { WriteSequenceSet: PROC [set: CoreClasses.SequenceSet] = { IF set=NIL THEN WriteInt[h, -1] ELSE { WriteInt[h, set.length]; FOR i: NAT IN [0..set.length) DO WriteInt[h, set[i]]; ENDLOOP; }; }; seq: CoreClasses.SequenceCellType _ NARROW[cellType.data]; WriteCellType[h, seq.base]; WriteInt[h, seq.count]; WriteSequenceSet[seq.sequence]; WriteSequenceSet[seq.flatSequence]; }; ReadSequence: ClassReadProc = { ReadSequenceSet: PROC RETURNS [set: CoreClasses.SequenceSet _ NIL] = { length: INT _ ReadInt[h]; IF length >= 0 THEN { set _ NEW[CoreClasses.SequenceSetRec[length]]; FOR i: NAT IN [0..set.length) DO set[i] _ ReadInt[h]; ENDLOOP; }; }; seq: CoreClasses.SequenceCellType _ NEW[CoreClasses.SequenceCellTypeRec]; seq.base _ ReadCellType[h]; seq.count _ ReadInt[h]; seq.sequence _ ReadSequenceSet[]; seq.flatSequence _ ReadSequenceSet[]; cellType.data _ seq; }; [] _ RegisterClass[CoreClasses.recordCellClass, WriteRecordCell, ReadRecordCell]; [] _ RegisterClass[CoreClasses.transistorCellClass, WriteTransistor, ReadTransistor]; [] _ RegisterClass[CoreClasses.unspecifiedCellClass, WriteUnspecified, ReadUnspecified]; [] _ RegisterClass[CoreClasses.sequenceCellClass, WriteSequence, ReadSequence]; [] _ RegisterClass[importCellClass, WriteImport, ReadImport]; END. restoreProp: ATOM = $CoreRestoreCellType; CoreProperties.PutCellTypeProp[cellType, restoreProp, fileName]; WriteCellType: PUBLIC PROC [h: Handle, cellType: Core.CellType] = { cellTypeID: ROPE _ NARROW [HashTable.Fetch[h.cellTypeIDTab, cellType].value]; IF cellTypeID=NIL THEN { restoreFileName: ROPE _ NARROW[CoreProperties.GetCellTypeProp[cellType, restoreProp]]; IF restoreFileName=NIL THEN { parentCellType: Core.CellType _ h.cellType; wireIDTab: HashTable.Table _ HashTable.Create[]; classWrite: REF ClassWriteProc _ NARROW[CoreProperties.GetCellClassProp[from: cellType.class, prop: CoreWriteProcProp]]; IF classWrite=NIL THEN { SIGNAL UnknownCellClass[cellType.class]; cellType _ CoreOps.Recast[cellType]; IF cellType=NIL THEN ERROR; WriteCellType[h, cellType]; RETURN; }; cellTypeID _ Rope.Cat["C", Convert.RopeFromInt[from: HashTable.GetSize[h.cellTypeIDTab], base: 16, showRadix: FALSE]]; IF NOT HashTable.Insert[h.cellTypeIDTab, cellType, cellTypeID] THEN ERROR; h.cellType _ cellType; WriteID[h, cellTypeID]; WriteWire[h, wireIDTab, cellType.public]; WriteProperties[h, cellType.properties]; WriteRope[h, cellType.class.name]; classWrite^[h, cellType, wireIDTab]; h.cellType _ parentCellType; } ELSE { cellTypeID _ Rope.Cat["I", Convert.RopeFromInt[from: HashTable.GetSize[h.cellTypeIDTab], base: 16, showRadix: FALSE]]; IF NOT HashTable.Insert[h.cellTypeIDTab, cellType, cellTypeID] THEN ERROR; WriteID[h, cellTypeID]; WriteRope[h, restoreFileName]; }; } ELSE WriteID[h, cellTypeID]; }; ReadCellTypePublic: PUBLIC PROC [h: Handle] RETURNS [cellType: Core.CellType, wireIDTab: HashTable.Table] = { cellTypeID: ROPE _ ReadID[h]; cellType _ NARROW[HashTable.Fetch[h.cellTypeIDTab, cellTypeID].value]; IF cellType=NIL THEN { SELECT Rope.Fetch[cellTypeID] FROM 'C => { cellType _ NEW[Core.CellTypeRec]; IF NOT HashTable.Insert[h.cellTypeIDTab, cellTypeID, cellType] THEN ERROR; h.cellType _ cellType; wireIDTab _ HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope]; cellType.public _ ReadWire[h, wireIDTab]; cellType.properties _ ReadProperties[h]; }; 'I => cellType _ RestoreCellType[fileName: ReadRope[h]]; ENDCASE => ERROR; }; }; >CoreIOImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Barth, December 5, 1986 11:29:20 am PST Bertrand Serlet December 1, 1986 7:10:26 pm PST Cell Type IO IO Registration IO Utilities Cell Class IO Initialization The following is a memorial to not thinking things through first. Κ6– "cedar" style˜codešœ™Kšœ Οmœ1™˜>Kšœ9žœ˜UKšœ8žœ˜RKšœ,˜,Kšœ˜Kšœ˜K˜——™ š  œžœžœ)˜CKšœ žœžœ4˜Mšžœ žœžœ˜Kšœ+˜+Kšœ0˜0Kšœ žœžœQ˜xšžœ žœžœ˜Kšžœ"˜(Kšœ$˜$Kšžœ žœžœžœ˜Kšœ˜Kšžœ˜K˜—Kšœnžœ˜vKšžœžœ9žœžœ˜JKšœ˜Kšœ˜Kšœ)˜)Kšœ(˜(Kšœ"˜"Kšœ$˜$Kšœ˜K˜—Kšžœ˜K˜K˜—š  œžœžœ žœ˜KKšœžœ˜!Kšœ+˜+Kšœ.˜.Kšžœ žœžœ*˜?Kšœ˜Kšœ˜K˜—š œžœžœ žœ:˜mKšœ žœ ˜Kšžœžœžœ˜(Kšœ žœ5˜Fšžœ žœžœ˜Kšœ žœ˜!Kšžœžœ9žœžœ˜JKšœ˜KšœS˜SKšœ)˜)Kšœ(˜(K˜—K˜K˜—š œžœžœE˜bKšœ žœ˜Kšœ žœžœ˜#Kšœžœ2˜IKšœ žœP˜bKšœ#˜#K˜K˜—š  œžœžœ=˜SKšœžœžœ)˜>šžœžœžœ˜Kšœ˜Kšœdžœ˜lKšžœžœ+žœžœ˜Kšœ˜Kšžœžœ ˜(K˜—Kšžœ˜K˜K˜—š  œžœžœ žœžœ˜:Kšœžœ ˜Kšžœžœžœ˜$Kšœžœ-˜:šžœžœžœ˜Kšœžœ˜Kšžœžœ-žœžœ˜>K˜—K˜K˜—š  œžœžœžœ˜2Kšœžœžœ+˜@šžœžœžœ˜Kšœfžœ˜nKšžœžœ-žœžœ˜>Kšœ˜Kšžœ˜Kšžœ‘0˜LKšžœ˜K˜—Kšžœ˜K˜K˜—š  œžœžœ žœžœ˜:Kšœžœ ˜Kšžœžœžœ˜$Kšœžœ-˜:šžœžœžœ˜Kšœžœ˜#Kšžœžœ-žœžœ˜>K˜—K˜K˜—š  œžœžœžœžœžœ˜AKšœžœ˜š žœžœžœžœžœžœž˜5Kšœ˜Kšžœ˜—Kšœ˜š žœžœžœžœžœžœž˜5Kšœ˜Kšžœ˜—K˜K˜—š œžœžœ žœ žœžœžœ˜IKšœžœ˜Kš œžœžœžœžœ˜šžœžœžœ ž˜Kšœžœ˜Kšžœ˜—š žœžœžœžœžœžœž˜3Kšœžœ˜Kšžœ˜—K˜K˜—š œžœžœžœ˜/Kšžœžœ ˜&K˜K˜—š  œžœžœ žœžœ˜7Kšœžœ˜K˜K˜—š  œžœžœžœ˜2Kšžœžœžœ ˜1K˜K˜—š  œžœžœ žœžœ˜:Kšœžœžœ˜%K˜K˜—š  œžœžœžœ˜2Kšžœžœžœžœ˜.Kšžœ˜K˜K˜—š  œžœžœ žœžœ˜:šœžœžœž˜'Kšœžœ˜ Kšœžœ˜ Kšžœžœ˜—Kšœžœ˜K˜K˜—š œžœžœA˜\K˜š œ˜&Kšœ˜K˜K˜—Kšœ&˜&Kšžœ"žœžœ˜/K˜K˜—š   œžœžœBžœžœžœ˜₯Kšœ3˜3šžœž˜Kšœ žœžœžœ˜K˜Kšžœžœ%žœžœ˜6Kšžœ˜—Kšœ˜K˜—š œžœ˜-Kšœžœžœ˜Kšœžœ˜(Kšœ˜Kšœ˜K˜K˜—š œžœ˜+Kšœ˜Kšœ˜Kšœ˜K˜—š œžœ˜)Kšœžœžœ˜Kšœžœžœ˜Kšœ˜Kšœ˜K˜K˜—š œžœ˜'Kšœ˜Kšœ˜Kšœ˜K˜—š œžœ˜)Kšœžœžœ˜Kšœžœžœ˜Kšœ˜Kšœ˜K˜K˜—š œžœ˜'Kšœ˜Kšœ˜Kšœ˜K˜——™ š œ˜#Kšœ"žœ˜8K˜Kšœ&˜&šžœžœžœž˜Kšœ-˜-Kšœ)˜)Kšœ(˜(K˜ Kšžœ˜—K˜K™—š œ˜!Kšœ"žœ,˜QKšœ&˜&šžœžœžœž˜Kšœ%žœ˜FKšœ˜Kšœ*˜*Kšœ(˜(Kšœ ˜ Kšžœ˜—Kšœ˜K˜K™—š œ˜#Kšœžœ˜5Kšœ7˜7Kšœ˜Kšœ˜K˜K™—š œ˜!Kšœžœ˜>Kšœžœ ˜šžœžœž˜Bšžœ6žœ˜>K˜Kšžœ˜K˜—Kšžœžœžœ˜Kšžœ˜—Kšœ˜Kšœ˜Kšœ˜K˜K˜—š œ˜&K™—š œ#žœ˜7K™—š  œ˜!K˜š œžœ#˜9Kšžœžœžœ˜šžœ˜Kšœ˜šžœžœžœž˜ Kšœ˜Kšžœ˜—K˜—K˜K˜—Kšœ$žœ˜:Kšœ˜Kšœ˜Kšœ˜Kšœ#˜#Kšœ˜K™—š  œ˜K˜š œžœžœ!žœ˜FKšœžœ˜šžœ žœ˜Kšœžœ%˜.šžœžœžœž˜ Kšœ˜Kšžœ˜—K˜—K˜K˜—Kšœ$žœ"˜IKšœ˜Kšœ˜Kšœ!˜!Kšœ%˜%Kšœ˜Kšœ˜——™KšœQ˜QKšœU˜UKšœX˜XKšœO˜OKšœ=˜=—K˜Kšžœ˜K˜K™AK˜Kšœ žœ˜)šœ@˜@K˜—š  œžœžœ)˜CKšœ žœžœ4˜Mšžœ žœžœ˜Kšœžœžœ8˜Všžœžœžœ˜Kšœ+˜+Kšœ0˜0Kšœ žœžœQ˜xšžœ žœžœ˜Kšžœ"˜(Kšœ$˜$Kšžœ žœžœžœ˜Kšœ˜Kšžœ˜K˜—Kšœnžœ˜vKšžœžœ9žœžœ˜JKšœ˜Kšœ˜Kšœ)˜)Kšœ(˜(Kšœ"˜"Kšœ$˜$Kšœ˜K˜—šžœ˜Kšœnžœ˜vKšžœžœ9žœžœ˜JKšœ˜Kšœ˜K˜—K˜—Kšžœ˜K˜K˜—š œžœžœ žœ:˜mKšœ žœ ˜Kšœ žœ5˜Fšžœ žœžœ˜šžœž˜"šœžœ˜Kšœ žœ˜!Kšžœžœ9žœžœ˜JKšœ˜KšœS˜SKšœ)˜)Kšœ(˜(K˜—Kšœ8˜8Kšžœžœ˜—K˜—K˜K˜—K˜—…—MΌg0