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šœ˜Kšœ˜Kšœ\˜\KšœX˜XKšœX˜XKšœ0˜0Kšœ!˜!Kšœ˜K˜K˜�—šŸœ˜!Kšœœ˜Kšœ œ˜Kšœ%˜%K˜ K˜K˜�—šŸœ˜'Kšœœ˜Kšœ!˜!Kšœœ˜4Jšœ˜K˜�—šŸœ˜K˜�šŸœ˜"Kšœœœ˜Kšœœ˜ Kšœ˜Kšœ˜K˜K˜�—Kšœœ˜'Kšœ˜Kšœœ˜'Kšœ<˜<Kšœ4˜4Kšœ4˜4Kšœ4˜4Kšœ%˜%K˜K™�—šŸ œ˜K˜�šŸœ˜ Kšœ˜Kšœ˜Kšœ˜K˜�—Kšœœ˜KšœœÏc!˜8Kšœ œ !˜4Kšœ˜Kšœ(˜(Kšœ$˜&Kšœj˜jKšœb˜bKšœb˜bKšœb˜bKšœ%˜%Kšœ˜K˜K˜�——šœ™ šŸœœœ,œ˜MšŸœ˜*Kšœ˜šœœ˜Kšœœœ˜9—K˜—Kšœœ ˜Kšœ*˜*Kšœœ˜,Kšœ"˜"KšœX˜XKšœ˜Kšœ%˜%Kšœ,˜,Kšœ˜K˜K™�—š Ÿœœœœœ%˜YKšœœ˜Kšœœ˜ Kšœ*˜*Kšœ˜Kšœ˜Kšœ\˜\KšœX˜XKšœX˜XKšœ˜Kšœ&˜&šœ ˜Kšœœ˜K˜*Kšœ*˜*Kšœ˜—Kšœ˜K˜——šœ ™šŸ œœœEœ ˜†Kšœ˜Kšœ:œ˜WKšœ9œ˜TKšœ4˜4Kšœ˜K˜�—šŸœœœœ,œœ˜qKšœ>˜>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˜�—�…—����T��p€��