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€��