DIRECTORY Ascii, Atom, CedarProcess, Convert, Core, CoreClasses, CoreDirectory, CoreIO, CoreOps, CoreProperties, FS, GList, IO, ProcessProps, RefTab, RefTabExtras, Rope, SymTab; CoreIOImpl: CEDAR PROGRAM IMPORTS Atom, CedarProcess, Convert, CoreClasses, CoreOps, CoreProperties, FS, GList, IO, ProcessProps, RefTab, RefTabExtras, Rope, SymTab EXPORTS CoreIO = BEGIN OPEN CoreIO; coreWriteProcProp: ATOM = $CoreWriteProc; coreReadProcProp: ATOM = $CoreReadProc; calledFromDir: Core.ROPE _ NIL; classRegistry: RefTab.Ref _ RefTab.Create[equal: RefTabExtras.EqualRope, hash: RefTabExtras.HashRope]; PutSpace: PROC [h: Handle] = INLINE {IO.PutChar[h.stream, Ascii.SP]}; 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 => { IF NOT GList.Member[propKey, props] THEN props _ CONS [propKey, props]; RESUME; }; UnknownCellClass => { IF NOT GList.Member[class, classes] THEN classes _ CONS [class, classes]; 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 _ RefTab.Create[]; h.ropeIDTab _ RefTab.Create[equal: RefTabExtras.EqualRope, hash: RefTabExtras.HashRope]; h.atomIDTab _ RefTab.Create[]; WriteCellType[h, cellType]; IO.Close[h.stream]; }; importCellClass: PUBLIC Core.CellClass _ CoreOps.SetClassPrintProc[NEW [Core.CellClassRec _ [name: "Import", recast: RecastImport, layersProps: TRUE]], PrintImport]; ReadFile: PROC [name: Core.ROPE] RETURNS [s: IO.STREAM _ NIL] ~ { s _ FS.StreamOpen[fileName: name ! FS.Error => CONTINUE]; IF s=NIL THEN s _ FS.StreamOpen[fileName: name, wDir: calledFromDir]; }; 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 _ ReadFile[fileName]; h.cellTypeIDTab _ RefTab.Create[equal: RefTabExtras.EqualRope, hash: RefTabExtras.HashRope]; h.ropeIDTab _ RefTab.Create[equal: RefTabExtras.EqualRope, hash: RefTabExtras.HashRope]; h.atomIDTab _ RefTab.Create[equal: RefTabExtras.EqualRope, hash: RefTabExtras.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 _ ReadFile[child.fileName]; IO.SetIndex[child.stream, ReadInt[h]]; child.cellTypeIDTab _ ReadHashTable[h, ReadCellTypeIDPair, RefTabExtras.EqualRope, RefTabExtras.HashRope]; child.ropeIDTab _ ReadHashTable[h, ReadRopeIDPair, RefTabExtras.EqualRope, RefTabExtras.HashRope]; child.atomIDTab _ ReadHashTable[h, ReadAtomIDPair, RefTabExtras.EqualRope, RefTabExtras.HashRope]; child.wireIDTab _ ReadHashTable[h, ReadWireIDPair, RefTabExtras.EqualRope, RefTabExtras.HashRope]; child.properties _ ReadProperties[h]; cellType.data _ child; }; SaveLibrary: PUBLIC PROC [library: CoreDirectory.Library, fileName: ROPE] = { EachLibraryItem: SymTab.EachPairAction = { WriteRope[h, key]; WriteCellType[h, NARROW [val] ! UnknownProperty => RESUME; UnknownCellClass => RESUME]; }; h: Handle _ NEW [HandleRec]; fileName _ Rope.Cat[fileName, ".corelib"]; h.stream _ FS.StreamOpen[fileName, $create]; h.cellTypeIDTab _ RefTab.Create[]; h.ropeIDTab _ RefTab.Create[equal: RefTabExtras.EqualRope, hash: RefTabExtras.HashRope]; h.atomIDTab _ RefTab.Create[]; WriteInt[h, SymTab.GetSize[library]]; [] _ SymTab.Pairs[library, EachLibraryItem]; IO.Close[h.stream]; }; RestoreLibrary: PUBLIC PROC [fileName: ROPE] RETURNS [library: CoreDirectory.Library] = { h: Handle _ NEW[HandleRec]; size: INT; fileName _ Rope.Cat[fileName, ".corelib"]; h.fileName _ fileName; h.stream _ ReadFile[fileName]; h.cellTypeIDTab _ RefTab.Create[equal: RefTabExtras.EqualRope, hash: RefTabExtras.HashRope]; h.ropeIDTab _ RefTab.Create[equal: RefTabExtras.EqualRope, hash: RefTabExtras.HashRope]; h.atomIDTab _ RefTab.Create[equal: RefTabExtras.EqualRope, hash: RefTabExtras.HashRope]; size _ ReadInt[h]; library _ SymTab.Create[(size/2)*2+1]; THROUGH [0 .. size) DO key: ROPE _ ReadRope[h]; cellType: Core.CellType _ ReadCellType[h]; [] _ SymTab.Store[library, key, cellType]; ENDLOOP; IO.Close[h.stream]; }; 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]]; [] _ RefTab.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 [RefTab.Fetch[h.cellTypeIDTab, cellType].val]; IF cellTypeID=NIL THEN { parentCellType: Core.CellType _ h.cellType; wireIDTab: RefTab.Ref _ RefTab.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: RefTab.GetSize[h.cellTypeIDTab], base: 16, showRadix: FALSE]]; IF NOT RefTab.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: RefTab.Ref _ 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: RefTab.Ref] = { cellTypeID: ROPE _ ReadID[h]; IF Rope.Fetch[cellTypeID]#'C THEN ERROR; cellType _ NARROW[RefTab.Fetch[h.cellTypeIDTab, cellTypeID].val]; IF cellType=NIL THEN { cellType _ NEW[Core.CellTypeRec]; IF NOT RefTab.Insert[h.cellTypeIDTab, cellTypeID, cellType] THEN ERROR; h.cellType _ cellType; wireIDTab _ RefTab.Create[equal: RefTabExtras.EqualRope, hash: RefTabExtras.HashRope]; cellType.public _ ReadWire[h, wireIDTab]; cellType.properties _ ReadProperties[h]; }; }; ReadCellTypeRest: PUBLIC PROC [h: Handle, cellType: Core.CellType, wireIDTab: RefTab.Ref] = { className: ROPE _ ReadRope[h]; classRead: REF ClassReadProc _ NIL; cellType.class _ NARROW[RefTab.Fetch[classRegistry, className].val]; classRead _ NARROW[CoreProperties.GetCellClassProp[from: cellType.class, prop: coreReadProcProp]]; classRead^[h, cellType, wireIDTab]; }; WriteWire: PUBLIC PROC [h: Handle, wireIDTab: RefTab.Ref, wire: Core.Wire] = { wireID: ROPE _ NARROW[RefTab.Fetch[wireIDTab, wire].val]; IF wireID=NIL THEN { parentWire: Core.Wire _ h.wire; wireID _ Rope.Cat["W", Convert.RopeFromInt[from: RefTab.GetSize[wireIDTab], base: 16, showRadix: FALSE]]; IF NOT RefTab.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: RefTab.Ref] RETURNS [wire: Core.Wire] = { wireID: ROPE _ ReadID[h]; IF Rope.Fetch[wireID]#'W THEN ERROR; wire _ NARROW[RefTab.Fetch[wireIDTab, wireID].val]; IF wire=NIL THEN { parentWire: Core.Wire _ h.wire; wireSize: NAT _ ReadInt[h]; wire _ NEW[Core.WireRec[wireSize]]; IF NOT RefTab.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] OR ISTYPE[propVal, REF BOOL] 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"]; WriteInt[h, i^]}; n: REF NAT => {StartProp["n"]; WriteInt[h, n^]}; a: ATOM => {StartProp["a"]; WriteAtom[h, a]}; real: REF REAL => {StartProp["real"]; WriteReal[h, real^]}; rb: REF BOOL => {StartProp["rb"]; WriteBool[h, rb^]}; 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 _ ReadInt[h]], Rope.Equal["n", type] => NEW[NAT _ ReadInt[h]], Rope.Equal["a", type] => ReadAtom[h], Rope.Equal["real", type] => NEW[REAL _ ReadReal[h]], Rope.Equal["rb", type] => NEW[BOOL _ ReadBool[h]], 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]; PutSpace[h]; }; ReadID: PUBLIC PROC [h: Handle] RETURNS [id: ROPE] = { id _ IO.GetID[h.stream]; }; WriteAtom: PUBLIC PROC [h: Handle, atom: ATOM] = { atomID: ROPE _ NARROW[RefTab.Fetch[h.atomIDTab, atom].val]; IF atomID=NIL THEN { atomID _ Rope.Cat["A", Convert.RopeFromInt[from: RefTab.GetSize[h.atomIDTab], base: 16, showRadix: FALSE]]; IF NOT RefTab.Insert[h.atomIDTab, atom, atomID] THEN ERROR; WriteID[h, atomID]; IO.Put1[h.stream, IO.atom[atom]]; PutSpace[h]; } 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[RefTab.Fetch[h.atomIDTab, atomID].val]; IF atom=NIL THEN { atom _ IO.GetAtom[h.stream]; IF NOT RefTab.Insert[h.atomIDTab, atomID, atom] THEN ERROR; }; }; doubleQuote: CHAR = '"; backSlash: CHAR = '\\; doubleQuoteRope: ROPE = Rope.FromChar[doubleQuote]; WriteRope: PUBLIC PROC [h: Handle, rope: ROPE] = { ropeID: ROPE _ NARROW[RefTab.Fetch[h.ropeIDTab, rope].val]; IF ropeID=NIL THEN { ropeID _ Rope.Cat["R", Convert.RopeFromInt[from: RefTab.GetSize[h.ropeIDTab], base: 16, showRadix: FALSE]]; IF NOT RefTab.Insert[h.ropeIDTab, rope, ropeID] THEN ERROR; WriteID[h, ropeID]; IO.PutChar[h.stream, doubleQuote]; WHILE NOT Rope.IsEmpty[rope] DO index: INT _ Rope.Find[rope, doubleQuoteRope]; IF index<0 THEN {IO.PutRope[h.stream, rope]; rope _ NIL} ELSE { IO.PutRope[h.stream, rope, 0, index]; IO.PutChar[h.stream, backSlash]; IO.PutChar[h.stream, doubleQuote]; rope _ Rope.Substr[rope, index+1]; }; ENDLOOP; IO.PutChar[h.stream, doubleQuote]; PutSpace[h]; } 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[RefTab.Fetch[h.ropeIDTab, ropeID].val]; IF rope=NIL THEN { rope _ IO.GetRopeLiteral[h.stream]; IF NOT RefTab.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.Put1[h.stream, IO.int[int]]; PutSpace[h]; }; ReadInt: PUBLIC PROC [h: Handle] RETURNS [int: INT] = { int _ IO.GetInt[h.stream]; }; WriteReal: PUBLIC PROC [h: Handle, real: REAL] = { IO.Put1[h.stream, IO.real[real]]; PutSpace[h]; }; ReadReal: PUBLIC PROC [h: Handle] RETURNS [real: REAL] = { real _ IO.GetReal[h.stream]; }; WriteBool: PUBLIC PROC [h: Handle, bool: BOOL] = { WriteInt[h, IF bool THEN 1 ELSE 0]; }; ReadBool: PUBLIC PROC [h: Handle] RETURNS [bool: BOOL] = { bool _ ReadInt[h]#0; }; WriteHashTable: PUBLIC PROC [h: Handle, table: RefTab.Ref, eachPair: HashWriteProc] = { HashPair: RefTab.EachPairAction = { eachPair[h, key, val]; }; WriteInt[h, RefTab.GetSize[table]]; IF RefTab.Pairs[table, HashPair] THEN ERROR; }; ReadHashTable: PUBLIC PROC [h: Handle, eachPair: HashReadProc, equal: RefTab.EqualProc _ NIL, hash: RefTab.HashProc _ NIL] RETURNS [table: RefTab.Ref] = { table _ RefTab.Create[equal: equal, hash: hash]; THROUGH [1..ReadInt[h]] DO key, value: REF ANY _ NIL; [key, value] _ eachPair[h]; IF NOT RefTab.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]]; }; 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; 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]; calledFromDir _ NARROW[ProcessProps.GetProp[$WorkingDirectory]]; END. restoreProp: ATOM = $CoreRestoreCellType; CoreProperties.PutCellTypeProp[cellType, restoreProp, fileName]; WriteCellType: PUBLIC PROC [h: Handle, cellType: Core.CellType] = { cellTypeID: ROPE _ NARROW [RefTab.Fetch[h.cellTypeIDTab, cellType].val]; IF cellTypeID=NIL THEN { restoreFileName: ROPE _ NARROW[CoreProperties.GetCellTypeProp[cellType, restoreProp]]; IF restoreFileName=NIL THEN { parentCellType: Core.CellType _ h.cellType; wireIDTab: RefTab.Ref _ RefTab.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: RefTab.GetSize[h.cellTypeIDTab], base: 16, showRadix: FALSE]]; IF NOT RefTab.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: RefTab.GetSize[h.cellTypeIDTab], base: 16, showRadix: FALSE]]; IF NOT RefTab.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: RefTab.Ref] = { cellTypeID: ROPE _ ReadID[h]; cellType _ NARROW[RefTab.Fetch[h.cellTypeIDTab, cellTypeID].val]; IF cellType=NIL THEN { SELECT Rope.Fetch[cellTypeID] FROM 'C => { cellType _ NEW[Core.CellTypeRec]; IF NOT RefTab.Insert[h.cellTypeIDTab, cellTypeID, cellType] THEN ERROR; h.cellType _ cellType; wireIDTab _ RefTab.Create[equal: RefTabExtras.EqualRope, hash: RefTabExtras.HashRope]; cellType.public _ ReadWire[h, wireIDTab]; cellType.properties _ ReadProperties[h]; }; 'I => cellType _ RestoreCellType[fileName: ReadRope[h]]; ENDCASE => ERROR; }; }; ,CoreIOImpl.mesa Copyright Σ 1985, 1987 by Xerox Corporation. All rights reserved. Barth, April 16, 1987 4:03:41 pm PDT Bertrand Serlet May 3, 1988 3:16:46 pm PDT Mike Spreitzer February 27, 1987 2:54:07 pm PST Louis Monier September 24, 1987 2:51:06 pm PDT Prerequisites Cell Type IO Library IO IO Registration IO Utilities we cannot use IO.PutF that truncates long ropes, and we have to beware of "! We use Put1 instead of PutF to be faster. Cell Class IO Initialization The following is a memorial to not thinking things through first. ΚB– "cedar" style˜codešœ™KšœB™BKšœ!Οk™$Kšœ*™*Kšœ,™/Kšœ+™.K™—š ˜ Kšœ$˜$KšœC˜CKšœ œ3˜@—K˜•StartOfExpansion[]šΠbn œœ˜KšœDœ œ2˜ŠKšœ˜Kšœœœ˜—head™ Kšœœ˜)Kšœœ˜'K˜Kšœœœ˜šœf˜fK˜—Kš Οnœœœœœ˜E—šœ ™ Kš Ÿœœœ œœ˜6šŸœœœœ˜?K˜—šŸœœœ%œœœ œœœœ œœœ˜žšœ!˜!šœ˜K–$[ref: REF ANY, list: GList.List]šœœœ œ˜GKšœ˜K˜—šœ˜K–$[ref: REF ANY, list: GList.List]šœœœ œ˜IKšœ˜K˜——K˜K™—š Ÿ œœœ%œœ˜MKšœ œ ˜Kšœ œœA˜UKšœ œ˜,Kšœ"˜"KšœX˜XKšœ˜Kšœ˜Kšœ˜K˜K™—šœœ,œJœ˜₯K˜—šŸœœ œœœœœ˜AKšœœœ œ˜9Kšœœœœ1˜EK˜—K˜šŸœœœ œœ œœœ˜oKšœ œ ˜Kš œ œœ œœœ˜,Kšœ œœ(˜˜>Kšœ9œ˜UKšœ8œ˜RKšœ,˜,Kšœ˜Kšœ˜K˜——šœ ™ šŸ œœœ)˜CKšœ œœ/˜Hšœ œœ˜Kšœ+˜+Kšœ(˜(Kšœ œœQ˜xšœ œœ˜Kšœ"˜(Kšœ$˜$Kšœ œœœ˜Kšœ˜Kšœ˜K˜—Kšœkœ˜sKšœœ6œœ˜GKšœ˜Kšœ˜Kšœ)˜)Kšœ(˜(Kšœ"˜"Kšœ$˜$Kšœ˜K˜—Kšœ˜K˜K˜—šŸ œœœ œ˜KKšœœ˜Kšœ+˜+Kšœ.˜.Kšœ œœ*˜?Kšœ˜Kšœ˜K˜—šŸœœœ œ5˜hKšœ œ ˜Kšœœœ˜(Kšœ œ0˜Ašœ œœ˜Kšœ œ˜!Kšœœ6œœ˜GKšœ˜KšœV˜VKšœ)˜)Kšœ(˜(K˜—K˜K˜—šŸœœœ@˜]Kšœ œ˜Kšœ œœ˜#Kšœœ-˜DKšœ œP˜bKšœ#˜#K˜K˜—šŸ œœœ8˜NKšœœœ$˜9šœœœ˜Kšœ˜Kšœaœ˜iKšœœ(œœ˜9Kšœ˜K˜Kšœ˜Kšœ$˜$šœœœ˜!Kšœ!˜!Kšœ˜—Kšœ˜K˜—Kšœ˜K˜K˜—šŸœœœ$œ˜VKšœœ ˜Kšœœœ˜$Kšœœ&˜3šœœœ˜Kšœ˜Kšœ œ˜Kšœœ˜#Kšœœ(œœ˜9Kšœ˜Kšœ$˜$šœœœ˜!Kšœ!˜!Kšœ˜—Kšœ˜K˜—K˜K˜—šŸœœœ-˜IKšœ œ˜Kšœ˜šœ1œœ˜FKšœ œœ˜(Kšœ œœ˜#Kšœ œœa˜†Kš<œ œœœ œœœ œœœœœ œœœœ œœœœ œœœ œœœœ œœœ˜υKšœ˜—Kšœ˜šœ1œœ˜FK˜šŸ œœœ˜ Jšœ˜Jšœœœ˜"K˜K˜—Kšœ œœ˜(Kšœ œœa˜†š œ œœœœ˜6Kšœœ&˜-Kšœœœœ0˜AKšœœœ&˜0Kšœœœ&˜0Kšœœ&˜-Kšœœœ-˜;Kšœœœ)˜5Kšœœ˜*—Kšœ œ,˜?Kšœ˜—K˜K˜—š Ÿœœœ œ œ˜WKšœ œ˜Kšœ˜šœœœ˜Kšœœ˜Kšœœœ˜ Kšœ œœ\˜šœ œœ˜Kšœœ ˜šœœœ˜Kšœ%˜%Kšœ-˜-Kšœœœ˜/Kšœœœ˜/Kšœ%˜%Kšœœœ˜4Kšœœœ˜2Kšœœ&˜6—K˜—Kšœ˜Kšœ œ˜+Kšœ˜—Kšœ˜K˜—šŸœœœœ˜.Kšœ$˜&K˜K˜—š Ÿœœœ œœ˜6Kšœœ˜K˜K˜—šŸ œœœœ˜2Kšœœœ&˜;šœœœ˜Kšœcœ˜kKšœœ*œœ˜;Kšœ˜Kšœœ˜.K˜—Kšœ˜K˜K˜—š Ÿœœœ œœ˜:Kšœœ ˜Kšœœœ˜$Kšœœ(˜5šœœœ˜Kšœœ˜Kšœœ*œœ˜;K˜—K˜K˜—Kšœ œ˜Kšœ œ˜šœœ˜3K˜—šŸ œœœœ˜2Kšœœœ&˜;šœœœ˜Kšœcœ˜kKšœœ*œœ˜;Kšœ˜Kšœ ˜"KšœL™Lšœœ˜Kšœœ$˜.šœ ˜ Kšœœ!œ˜-Kšœ˜Kšœ#˜%Kšœ˜ Kšœ ˜"Kšœ"˜"K˜—Kšœ˜—Kšœ ˜"Kšœ ˜ K˜—Kšœ˜K˜K˜—š Ÿœœœ œœ˜:Kšœœ ˜Kšœœœ˜$Kšœœ(˜5šœœœ˜Kšœœ˜#Kšœœ*œœ˜;K˜—K˜K˜—š Ÿœœœœœœ˜AKšœœ˜š œœœœœœ˜5Kšœ˜Kšœ˜—Kšœ˜š œœœœœœ˜5Kšœ˜Kšœ˜—K˜K˜—šŸœœœ œ œœœ˜IKšœœ˜Kš œœœœœ˜šœœœ ˜Kšœœ˜Kšœ˜—š œœœœœœ˜3Kšœœ˜Kšœ˜—K˜K˜—šŸœœœœ˜/Kšœ)™)Kšœœ˜,K˜K˜—š Ÿœœœ œœ˜7Kšœœ˜K˜K˜—šŸ œœœœ˜2Kšœœ˜.K˜K˜—š Ÿœœœ œœ˜:Kšœœ˜K˜K˜—šŸ œœœœ˜2Kšœ œœœ˜#K˜K˜—š Ÿœœœ œœ˜:Kšœ˜K˜K˜—šŸœœœ<˜WK˜šŸœ˜#Kšœ˜K˜K˜—Kšœ#˜#Kšœœœ˜,K˜K˜—š Ÿ œœœ?œœœ˜šKšœ0˜0šœ˜Kšœ œœœ˜K˜Kšœœ"œœ˜3Kšœ˜—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šœœ ˜šœœ˜Bšœ6œ˜>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˜K™AK˜Kšœ œ˜)šœ@˜@K˜—šŸ œœœ)˜CKšœ œœ/˜Hšœ œœ˜Kšœœœ8˜Všœœœ˜Kšœ+˜+Kšœ(˜(Kšœ œœQ˜xšœ œœ˜Kšœ"˜(Kšœ$˜$Kšœ œœœ˜Kšœ˜Kšœ˜K˜—Kšœkœ˜sKšœœ6œœ˜GKšœ˜Kšœ˜Kšœ)˜)Kšœ(˜(Kšœ"˜"Kšœ$˜$Kšœ˜K˜—šœ˜Kšœkœ˜sKšœœ6œœ˜GKšœ˜Kšœ˜K˜—K˜—Kšœ˜K˜K˜—šŸœœœ œ5˜hKšœ œ ˜Kšœ œ0˜Ašœ œœ˜šœ˜"šœ˜Kšœ œ˜!Kšœœ6œœ˜GKšœ˜KšœV˜VKšœ)˜)Kšœ(˜(K˜—Kšœ8˜8Kšœœ˜—K˜—K˜K˜—K˜—…—Tp€