<> <> <> <> <> <> <<>> DIRECTORY Ascii, Atom, BrineIO, CedarProcess, Core, CoreClasses, CoreDirectory, CoreIO, CoreOps, CoreProperties, FS, GList, IO, ProcessProps, RefTab, RefTabExtras, Rope, SymTab; CoreIOImpl: CEDAR PROGRAM IMPORTS Atom, BrineIO, CedarProcess, CoreClasses, CoreOps, CoreProperties, FS, GList, IO, ProcessProps, RefTab, RefTabExtras, Rope, SymTab EXPORTS CoreIO = BEGIN OPEN CoreIO, BrineIO; <> ROPE: TYPE = Rope.ROPE; STREAM: TYPE = IO.STREAM; coreWriteProcProp: ATOM = $CoreWriteProc; coreReadProcProp: ATOM = $CoreReadProc; calledFromDir: Core.ROPE _ NIL; classRegistry: RefTab.Ref _ RefTab.Create[equal: RefTabExtras.EqualRope, hash: RefTabExtras.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 => { 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] = { stream: STREAM; IF fileName=NIL THEN fileName _ Rope.Cat[CoreOps.GetCellTypeName[cellType], ".core"]; stream _ FS.StreamOpen[fileName, $create]; WriteCellType[stream, cellType]; IO.Close[stream]; }; <<>> importCellClass: PUBLIC Core.CellClass _ CoreOps.SetClassPrintProc[NEW [Core.CellClassRec _ [name: "Import", recast: RecastImport, layersProps: TRUE]], PrintImport]; ReadFile: PROC [name: Core.ROPE] RETURNS [s: 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] = { stream: STREAM; wireIDTable: RefTab.Ref; IF fileName=NIL AND cellName=NIL THEN ERROR; IF fileName=NIL THEN fileName _ Rope.Cat[cellName, ".core"]; stream _ ReadFile[fileName]; stream.propList _ Atom.PutPropOnList[stream.propList, $CoreIOFileName, fileName]; [cellType, wireIDTable] _ ReadCellTypePublic[stream]; stream.propList _ Atom.PutPropOnList[stream.propList, $CoreIOWireTable, wireIDTable]; cellType.class _ importCellClass; cellType.data _ stream; }; RecastImport: Core.RecastProc = { stream: STREAM _ NARROW [me.data]; wireIDTable: RefTab.Ref _ GetRefTab[stream, $CoreIOWireTable]; me.data _ NIL; ReadCellTypeRest[stream, me, wireIDTable]; new _ me; }; PrintImport: CoreOps.PrintClassProc = { stream: STREAM _ NARROW [data]; CoreOps.PrintIndent[indent, out]; IO.PutF[out, "Import of : %g", IO.rope[NARROW [Atom.GetPropFromList[stream.propList, $CoreIOFileName]]]]; }; <> SaveLibrary: PUBLIC PROC [library: CoreDirectory.Library, fileName: ROPE] = { EachLibraryItem: SymTab.EachPairAction = { WriteRope[stream, key]; WriteCellType[stream, NARROW [val] ! UnknownProperty => RESUME; UnknownCellClass => RESUME]; }; stream: STREAM; fileName _ Rope.Cat[fileName, ".corelib"]; stream _ FS.StreamOpen[fileName, $create]; WriteInt[stream, SymTab.GetSize[library]]; [] _ SymTab.Pairs[library, EachLibraryItem]; IO.Close[stream]; }; <<>> RestoreLibrary: PUBLIC PROC [fileName: ROPE] RETURNS [library: CoreDirectory.Library] = { stream: STREAM; size: INT; fileName _ Rope.Cat[fileName, ".corelib"]; stream _ ReadFile[fileName]; stream.propList _ Atom.PutPropOnList[stream.propList, $CoreIOFileName, fileName]; size _ ReadInt[stream]; library _ SymTab.Create[(size/2)*2+1]; THROUGH [0 .. size) DO key: ROPE _ ReadRope[stream]; cellType: Core.CellType _ ReadCellType[stream]; [] _ SymTab.Store[library, key, cellType]; ENDLOOP; IO.Close[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 [stream: STREAM, cellType: Core.CellType] = { cellTypeIDTable: RefTab.Ref _ GetRefTab[stream, $CoreIOCellTypeTable]; cellTypeID: ROPE _ NARROW [RefTab.Fetch[cellTypeIDTable, cellType].val]; IF cellTypeID=NIL THEN { wireIDTable: 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[stream, cellType]; RETURN; }; cellTypeID _ MakeID["C", RefTab.GetSize[cellTypeIDTable]]; IF NOT RefTab.Insert[cellTypeIDTable, cellType, cellTypeID] THEN ERROR; WriteID[stream, cellTypeID]; WriteWire[stream, wireIDTable, cellType.public]; WriteProperties[stream, cellType.properties]; WriteRope[stream, cellType.class.name]; classWrite^[stream, cellType, wireIDTable]; } ELSE WriteID[stream, cellTypeID]; }; ReadCellType: PUBLIC PROC [stream: STREAM] RETURNS [cellType: Core.CellType] = { wireIDTable: RefTab.Ref _ NIL; [cellType, wireIDTable] _ ReadCellTypePublic[stream]; IF wireIDTable#NIL THEN ReadCellTypeRest[stream, cellType, wireIDTable]; }; ReadCellTypePublic: PUBLIC PROC [stream: STREAM] RETURNS [cellType: Core.CellType, wireIDTable: RefTab.Ref] = { cellTypeIDTable: RefTab.Ref _ GetRefTab[stream, $CoreIOCellTypeTable, RefTabExtras.EqualRope, RefTabExtras.HashRope]; cellTypeID: ROPE _ ReadID[stream]; IF Rope.Fetch[cellTypeID]#'C THEN ERROR; cellType _ NARROW[RefTab.Fetch[cellTypeIDTable, cellTypeID].val]; IF cellType=NIL THEN { cellType _ NEW[Core.CellTypeRec]; IF NOT RefTab.Insert[cellTypeIDTable, cellTypeID, cellType] THEN ERROR; wireIDTable _ RefTab.Create[equal: RefTabExtras.EqualRope, hash: RefTabExtras.HashRope]; cellType.public _ ReadWire[stream, wireIDTable]; cellType.properties _ ReadProperties[stream]; }; }; ReadCellTypeRest: PUBLIC PROC [stream: STREAM, cellType: Core.CellType, wireIDTable: RefTab.Ref] = { className: ROPE _ ReadRope[stream]; classRead: REF ClassReadProc _ NIL; cellType.class _ NARROW[RefTab.Fetch[classRegistry, className].val]; classRead _ NARROW[CoreProperties.GetCellClassProp[from: cellType.class, prop: coreReadProcProp]]; classRead^[stream, cellType, wireIDTable]; }; WriteWire: PUBLIC PROC [stream: STREAM, wireIDTable: RefTab.Ref, wire: Core.Wire] = { wireID: ROPE _ NARROW[RefTab.Fetch[wireIDTable, wire].val]; IF wireID=NIL THEN { wireID _ MakeID["W", RefTab.GetSize[wireIDTable]]; IF NOT RefTab.Insert[wireIDTable, wire, wireID] THEN ERROR; WriteID[stream, wireID]; WriteInt[stream, wire.size]; WriteProperties[stream, wire.properties]; FOR w: NAT IN [0 .. wire.size) DO WriteWire[stream, wireIDTable, wire[w]]; ENDLOOP; } ELSE WriteID[stream, wireID]; }; ReadWire: PUBLIC PROC [stream: STREAM, wireIDTable: RefTab.Ref] RETURNS [wire: Core.Wire] = { wireID: ROPE _ ReadID[stream]; IF Rope.Fetch[wireID]#'W THEN ERROR; wire _ NARROW[RefTab.Fetch[wireIDTable, wireID].val]; IF wire=NIL THEN { wireSize: NAT _ ReadInt[stream]; wire _ NEW[Core.WireRec[wireSize]]; IF NOT RefTab.Insert[wireIDTable, wireID, wire] THEN ERROR; wire.properties _ ReadProperties[stream]; FOR w: NAT IN [0 .. wire.size) DO wire[w] _ ReadWire[stream, wireIDTable]; ENDLOOP; }; }; WriteProperties: PUBLIC PROC [stream: STREAM, 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[stream, propCount]; FOR props: Core.Properties _ properties, props.rest UNTIL props=NIL DO StartProp: PROC [type: ROPE] = { WriteAtom[stream, propKey]; IF type#NIL THEN WriteID[stream, 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[stream, r]}; lor: LIST OF ROPE => {StartProp["lor"]; WriteRopes[stream, lor]}; i: REF INT => {StartProp["i"]; WriteInt[stream, i^]}; n: REF NAT => {StartProp["n"]; WriteInt[stream, n^]}; a: ATOM => {StartProp["a"]; WriteAtom[stream, a]}; real: REF REAL => {StartProp["real"]; WriteReal[stream, real^]}; rb: REF BOOL => {StartProp["rb"]; WriteBool[stream, rb^]}; ENDCASE => SIGNAL UnknownProperty[propKey] ELSE {StartProp[NIL]; propWrite^[stream, propKey, props.first.val]}; ENDLOOP; }; ReadProperties: PUBLIC PROC [stream: STREAM] RETURNS [properties: Core.Properties _ NIL] = { propCount: INT _ ReadInt[stream]; CedarProcess.CheckAbort[]; FOR c: INT IN [0..propCount) DO key: ATOM _ ReadAtom[stream]; val: REF ANY; propRead: REF PropReadProc _ NARROW[CoreProperties.GetProp[from: CoreProperties.FetchProperties[key], prop: coreReadProcProp]]; IF propRead=NIL THEN { type: ROPE _ ReadID[stream]; val _ SELECT TRUE FROM Rope.Equal["r", type] => ReadRope[stream], Rope.Equal["lor", type] => ReadRopes[stream], Rope.Equal["i", type] => NEW[INT _ ReadInt[stream]], Rope.Equal["n", type] => NEW[NAT _ ReadInt[stream]], Rope.Equal["a", type] => ReadAtom[stream], Rope.Equal["real", type] => NEW[REAL _ ReadReal[stream]], Rope.Equal["rb", type] => NEW[BOOL _ ReadBool[stream]], ENDCASE => ERROR UnknownProperty[Atom.MakeAtom[type]]; } ELSE val _ propRead^[stream, key]; properties _ CONS [[key, val], properties]; ENDLOOP; }; <> WriteRecordCell: ClassWriteProc = { rct: CoreClasses.RecordCellType _ NARROW[cellType.data]; WriteInt[stream, rct.size]; WriteWire[stream, wireIDTable, rct.internal]; FOR in: NAT IN [0..rct.size) DO instance: CoreClasses.CellInstance _ rct[in]; WriteWire[stream, wireIDTable, instance.actual]; WriteProperties[stream, instance.properties]; WriteCellType[stream, instance.type]; ENDLOOP; }; <<>> ReadRecordCell: ClassReadProc = { rct: CoreClasses.RecordCellType _ NEW[CoreClasses.RecordCellTypeRec[ReadInt[stream]]]; rct.internal _ ReadWire[stream, wireIDTable]; FOR in: NAT IN [0..rct.size) DO instance: CoreClasses.CellInstance _ NEW[CoreClasses.CellInstanceRec]; rct[in] _ instance; instance.actual _ ReadWire[stream, wireIDTable]; instance.properties _ ReadProperties[stream]; instance.type _ ReadCellType[stream]; ENDLOOP; cellType.data _ rct; }; <<>> WriteTransistor: ClassWriteProc = { tran: CoreClasses.Transistor _ NARROW[cellType.data]; WriteID[stream, CoreClasses.transistorTypeNames[tran.type]]; }; <<>> ReadTransistor: ClassReadProc = { tran: CoreClasses.Transistor _ NEW[CoreClasses.TransistorRec]; type: ROPE _ ReadID[stream]; 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[stream, -1] ELSE { WriteInt[stream, set.length]; FOR i: NAT IN [0..set.length) DO WriteInt[stream, set[i]]; ENDLOOP; }; }; seq: CoreClasses.SequenceCellType _ NARROW[cellType.data]; WriteCellType[stream, seq.base]; WriteInt[stream, seq.count]; WriteSequenceSet[seq.sequence]; WriteSequenceSet[seq.flatSequence]; }; <<>> ReadSequence: ClassReadProc = { ReadSequenceSet: PROC RETURNS [set: CoreClasses.SequenceSet _ NIL] = { length: INT _ ReadInt[stream]; IF length >= 0 THEN { set _ NEW[CoreClasses.SequenceSetRec[length]]; FOR i: NAT IN [0..set.length) DO set[i] _ ReadInt[stream]; ENDLOOP; }; }; seq: CoreClasses.SequenceCellType _ NEW[CoreClasses.SequenceCellTypeRec]; seq.base _ ReadCellType[stream]; seq.count _ ReadInt[stream]; 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]; calledFromDir _ NARROW[ProcessProps.GetProp[$WorkingDirectory]]; END.