CoreGeometryIOImpl.mesa 
Copyright Ó 1986, 1987 by Xerox Corporation. All rights reserved.
Bertrand Serlet March 14, 1987 1:06:01 am PST
Barth, December 4, 1986 6:01:02 pm PST
DIRECTORY
CD, CDAtomicObjects, CDCells, CDPrivate, CDRects, CDTexts, CDSymbolicObjects,
Convert,
Core, CoreIO, CoreProperties, CoreGeometry, CoreGeometryBackdoor,
GList, HashTable, IO, Rope, PWObjects;
CoreGeometryIOImpl: CEDAR PROGRAM
IMPORTS CD, CDAtomicObjects, CDCells, CDPrivate, CDRects, CDSymbolicObjects, CDTexts, Convert, CoreIO, CoreGeometry, CoreGeometryBackdoor, CoreProperties, GList, HashTable, IO, Rope, PWObjects
EXPORTS CoreGeometryBackdoor
SHARES CDCells, CDRects, CDTexts, CDSymbolicObjects, CoreGeometry =
BEGIN OPEN CoreIO, CoreGeometry, CoreGeometryBackdoor;
The following classes are not saved even though they are loaded with CMosB. This assumes that they are not atomic objects.
CDImportsImpl $Import
CDRepetitionsImpl $Repetitions
CDRectsImpl $SaveRect
CDCurvesImpl $FilledCurve0, $Line0, $Polygon0, $Spline0
CDOpsImpl $GCollected
CDPolygonsImpl $Polygon
Object Class Registration
objectClassRegistry: HashTable.Table ← HashTable.Create[];
ObjectClassData: TYPE = REF ObjectClassDataRec;
ObjectClassDataRec: TYPE = RECORD [
write: ObjectClassWriteProc ← NIL,
read: ObjectClassReadProc ← NIL];
ObjectClassWriteProc: TYPE = PROC [h: Handle, me: CD.Object];
ObjectClassReadProc: TYPE = PROC [h: Handle] RETURNS [obj: CD.Object];
RegisterObjectClass: PUBLIC PROC [objectClass: CD.ObjectClass, write: ObjectClassWriteProc, read: ObjectClassReadProc] = {
data: ObjectClassData ← NEW[ObjectClassDataRec ← [write, read]];
IF write=NIL OR read=NIL THEN ERROR; -- if only one NIL then invariant for object write/read is broken
[] ← HashTable.Store[objectClassRegistry, objectClass.objectType, data];
};
Low Level IO Utilities
WriteBool: PUBLIC PROC [h: Handle, bool: BOOL] = {
IO.PutChar[h.stream, IF bool THEN '1 ELSE '0];
IO.PutChar[h.stream, ' ];
};
ReadBool: PUBLIC PROC [h: Handle] RETURNS [bool: BOOL] = {
bool ← SELECT IO.GetInt[h.stream] FROM
0 => FALSE,
1 => TRUE,
ENDCASE => ERROR;
[] ← IO.GetChar[h.stream];
};
WritePosition: PUBLIC PROC [h: Handle, position: CD.Position] = {
WriteInt[h, position.x];
WriteInt[h, position.y];
};
ReadPosition: PUBLIC PROC [h: Handle] RETURNS [position: CD.Position] = {
position.x ← ReadInt[h];
position.y ← ReadInt[h];
};
WriteRect: PUBLIC PROC [h: Handle, rect: CD.Rect] = {
WriteInt[h, rect.x1]; WriteInt[h, rect.y1];
WriteInt[h, rect.x2]; WriteInt[h, rect.y2];
};
ReadRect: PUBLIC PROC [h: Handle] RETURNS [rect: CD.Rect] = {
rect.x1 ← ReadInt[h]; rect.y1 ← ReadInt[h];
rect.x2 ← ReadInt[h]; rect.y2 ← ReadInt[h];
};
WriteTechnology: PUBLIC PROC [h: Handle, technology: CD.Technology] = {
WriteAtom[h, IF technology=NIL THEN $NILTechnology ELSE technology.key];
};
ReadTechnology: PUBLIC PROC [h: Handle] RETURNS [technology: CD.Technology] = {
atom: ATOM ← ReadAtom[h];
technology ← IF atom=$NILTechnology THEN NIL ELSE CD.FetchTechnology[atom];
};
WriteLayer: PUBLIC PROC [h: Handle, layer: CD.Layer] = {
WriteTechnology[h, CDPrivate.layers[layer].technology];
WriteAtom[h, CD.LayerKey[layer]];
};
ReadLayer: PUBLIC PROC [h: Handle] RETURNS [layer: CD.Layer] = {
technology: CD.Technology ← ReadTechnology[h];
layer ← CD.FetchLayer[technology, ReadAtom[h]];
};
WriteOrient: PUBLIC PROC [h: Handle, orient: CD.Orientation] = {
WriteInt[h, ORD[orient]];
};
ReadOrient: PUBLIC PROC [h: Handle] RETURNS [orient: CD.Orientation] = {
aux: [ORD[FIRST[CD.Orientation]] .. ORD[LAST[CD.Orientation]]] ← NAT [ReadInt[h]];
orient ← LOOPHOLE [aux];
};
WriteTrans: PUBLIC PROC [h: Handle, trans: CD.Transformation] = {
WritePosition[h, trans.off];
WriteOrient[h, trans.orient];
};
ReadTrans: PUBLIC PROC [h: Handle] RETURNS [trans: CD.Transformation] = {
off: CD.Position ← ReadPosition[h];
trans ← [off, ReadOrient[h]];
};
WriteCDProperties: PUBLIC PROC [h: Handle, properties: CD.PropList] = {
props: Core.Properties ← NIL;
WHILE properties#NIL DO
IF ISTYPE [properties.first.key, ATOM] THEN props ← CoreProperties.PutProp[props, NARROW [properties.first.key], properties.first.val];
properties ← properties.rest;
ENDLOOP;
WriteProperties[h, props];
};
ReadCDProperties: PUBLIC PROC [h: Handle] RETURNS [properties: CD.PropList ← NIL] = {
Consume: PROC [key: ATOM, val: REF] = {
properties ← CONS [[key, val], properties];
};
CoreProperties.Enumerate[ReadProperties[h], Consume];
};
Object Class IO Utilities
WriteCDInstance: PUBLIC PROC [h: Handle, instance: CD.Instance] = {
WriteObject[h, instance.ob];
WriteTrans[h, instance.trans];
WriteCDProperties[h, instance.properties];
};
ReadCDInstance: PUBLIC PROC [h: Handle] RETURNS [instance: CD.Instance] = {
instance ← NEW [CD.InstanceRep ← [ob: ReadObject[h]]];
instance.trans ← ReadTrans[h];
instance.properties ← ReadCDProperties[h];
};
WriteCDInstances: PUBLIC PROC [h: Handle, instances: LIST OF CD.Instance] = {
WriteInt[h, GList.Length[instances]];
WHILE instances#NIL DO
WriteCDInstance[h, instances.first];
instances ← instances.rest;
ENDLOOP;
};
ReadCDInstances: PUBLIC PROC [h: Handle] RETURNS [instances: LIST OF CD.Instance ← NIL] = {
THROUGH [1 .. ReadInt[h]] DO
instances ← CONS [ReadCDInstance[h], instances];
ENDLOOP;
};
WriteInstance: PUBLIC PROC [h: Handle, instance: Instance] = {
WriteObject[h, instance.obj];
WriteTrans[h, instance.trans];
};
ReadInstance: PUBLIC PROC [h: Handle] RETURNS [instance: Instance] = {
obj: CD.Object ← ReadObject[h];
instance ← [obj, ReadTrans[h]];
};
WriteInstances: PUBLIC PROC [h: Handle, instances: Instances] = {
WriteInt[h, Length[instances]];
WHILE instances#NIL DO
WriteInstance[h, instances.first];
instances ← instances.rest;
ENDLOOP;
};
ReadInstances: PUBLIC PROC [h: Handle] RETURNS [instances: Instances ← NIL] = {
THROUGH [0 .. ReadInt[h]) DO
instances ← CONS [ReadInstance[h], instances];
ENDLOOP;
};
WriteObjectIDPair: HashWriteProc = {
id: ROPENARROW[key];
object: CD.Object ← NARROW[value];
WriteID[h, id];
WriteObject[h, object];
};
ReadObjectIDPair: HashReadProc = {
key ← ReadID[h];
value ← ReadObject[h];
};
A HashTable [CD.Object -> Rope ID] is stored on the handle under the key objectsAtom
CMosBObsImpl $C2DifShortCon, $C2LargeSimpleCon, $C2LargeVia, $C2LargeWellSimpleCon, $C2LTrans, $C2LWellTrans, $C2SimpleCon, $C2Trans, $C2Via, $C2WellDifShortCon, $C2WellSimpleCon, $C2WellTrans, $CLWellTrans
WriteObject: PUBLIC PROC [h: Handle, obj: CD.Object] = {
objects: HashTable.Table ← NARROW [CoreProperties.GetProp[h.properties, objectsAtom]];
objectID: ROPENIL;
IF objects=NIL THEN {
objects ← HashTable.Create[];
h.properties ← CoreProperties.PutProp[h.properties, objectsAtom, objects];
};
objectID ← NARROW [HashTable.Fetch[objects, obj].value];
IF objectID=NIL THEN {
classData: ObjectClassData ← NARROW[HashTable.Fetch[objectClassRegistry, obj.class.objectType].value];
objectID ← Rope.Cat["O", Convert.RopeFromInt[from: HashTable.GetSize[objects], base: 16, showRadix: FALSE]];
IF NOT HashTable.Insert[objects, obj, objectID] THEN ERROR;
WriteID[h, objectID];
WriteAtom[h, obj.class.objectType];
IF classData=NIL THEN {
IF CDAtomicObjects.IsAtomicOb[obj] THEN {
WriteTechnology[h, obj.class.technology];
WritePosition[h, CD.InterestSize[obj]];
WriteLayer[h, obj.layer];
}
ELSE ERROR; -- no write proc and not atomic
}
ELSE classData.write[h, obj];
WriteCDProperties[h, obj.properties];
}
ELSE WriteID[h, objectID];
};
A HashTable [Rope ID -> CD.Object] is stored on the handle under the key objectsAtom
ReadObject: PUBLIC PROC [h: Handle] RETURNS [obj: CD.Object] = {
objects: HashTable.Table ← NARROW [CoreProperties.GetProp[h.properties, objectsAtom]];
objectID: ROPE;
IF objects=NIL THEN {
objects ← HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope];
h.properties ← CoreProperties.PutProp[h.properties, objectsAtom, objects];
};
objectID ← ReadID[h];
IF Rope.Fetch[objectID]#'O THEN ERROR;
obj ← NARROW [HashTable.Fetch[objects, objectID].value];
IF obj=NIL THEN {
classAtom: ATOM ← ReadAtom[h];
classData: ObjectClassData ← NARROW[HashTable.Fetch[objectClassRegistry, classAtom].value];
IF classData=NIL THEN {
technology: CD.Technology ← ReadTechnology[h];
pos: CD.Position ← ReadPosition[h];
layer: CD.Layer ← ReadLayer[h];
obj ← CDAtomicObjects.CreateAtomicOb[classAtom, pos, technology, layer];
}
ELSE obj ← classData.read[h];
obj.properties ← ReadCDProperties[h];
IF NOT HashTable.Insert[objects, objectID, obj] THEN ERROR;
};
};
CoreIO Object Property IO
PinsInstancesPropWrite: PropWriteProc = {
count: INT ← 0;
Incr: EachInstanceProc = {count ← count+1};
Write: EachInstanceProc = {WriteInstance[h, instance]};
[] ← RawEnumeratePins[prop, value, Incr];
WriteInt[h, count];
[] ← RawEnumeratePins[prop, value, Write];
};
GeometryInstancesPropWrite: PropWriteProc = {
count: INT ← 0;
Incr: EachInstanceProc = {count ← count+1};
Write: EachInstanceProc = {WriteInstance[h, instance]};
[] ← RawEnumerateGeometry[prop, value, Incr];
WriteInt[h, count];
[] ← RawEnumeratePins[prop, value, Write];
};
InstancesPropRead: PropReadProc = {
value ← ReadInstances[h];
};
ObjectPropWrite: PropWriteProc = {WriteObject[h, NARROW [value]]};
ObjectPropRead: PropReadProc = {value ← ReadObject[h]};
TransPropWrite: PropWriteProc = {WriteTrans[h, NARROW [value, REF CD.Transformation]^]};
TransPropRead: PropReadProc = {value ← NEW [CD.Transformation ← ReadTrans[h]]};
WriteObjectsProp: PropWriteProc = {
WriteHashTable[h, NARROW[value], WriteObjectIDPair];
};
ReadObjectsProp: PropReadProc = {
value ← ReadHashTable[h, ReadObjectIDPair, HashTable.RopeEqual, HashTable.HashRope];
};
Object Class IO
CMosBWellDifImpl $C2NDifRect, $C2PDifRect; CDRectsImpl $Rect
WriteRectangle: ObjectClassWriteProc = {
WritePosition[h, CD.InterestSize[me]];
WriteLayer[h, me.layer];
};
ReadRectangle: ObjectClassReadProc = {
sz: CD.Position = ReadPosition[h];
l: CD.Layer = ReadLayer[h];
ob: CD.Object = CDRects.CreateRect[sz, l];
RETURN [ob]
};
CDCellsImpl $Cell
WriteCell: ObjectClassWriteProc = {
ConsInstance: CDCells.InstEnumerator = {insts ← CONS [inst, insts]};
insts: LIST OF CD.Instance ← NIL;
cellPtr: CD.CellSpecific ← NARROW [me.specific];
[] ← CDCells.EnumerateInstances[me, ConsInstance];
WriteRect[h, me.bbox];
WriteCDInstances[h, insts];
WriteRect[h, cellPtr.ir];
WriteRope[h, cellPtr.name];
WriteReal[h, cellPtr.simplifyOn];
WriteBool[h, cellPtr.drawBorder];
WriteBool[h, cellPtr.specifiedIr];
};
ReadCell: ObjectClassReadProc = {
cellPtr: CD.CellSpecific ← NEW [CD.CellRep];
obj ← NEW [CD.ObjectRep ← [class: CDCells.pCellClass]];
obj.bbox ← ReadRect[h];
cellPtr.contents ← ReadCDInstances[h];
cellPtr.ir ← ReadRect[h];
cellPtr.name ← ReadRope[h];
cellPtr.simplifyOn ← ReadReal[h];
cellPtr.drawBorder ← ReadBool[h];
cellPtr.specifiedIr ← ReadBool[h];
obj.specific ← cellPtr;
CDCells.ToSequenceMode[obj];
};
PWObjects $AbutX $AbutY
WriteAbut: ObjectClassWriteProc = {
count: INT ← 0;
Count: PWObjects.EachSubObjectProc = {count ← count + 1};
Write: PWObjects.EachSubObjectProc = {WriteObject[h, subObject]};
WriteRect[h, me.bbox];
WriteBool[h, me.class=PWObjects.abutXClass];
PWObjects.EnumerateSubObjects[me, Count];
WriteInt[h, count];
PWObjects.EnumerateSubObjects[me, Write];
};
ReadAbut: ObjectClassReadProc = {
bbox: CD.Rect ← ReadRect[h];
inX: BOOL ← ReadBool[h];
size: INT ← ReadInt[h];
subObjects: LIST OF CD.Object ← NIL;
THROUGH [0 .. size) DO subObjects ← CONS [ReadObject[h], subObjects] ENDLOOP;
obj ← (IF inX THEN PWObjects.CreateNewAbutX ELSE PWObjects.CreateNewAbutY)[NARROW [GList.Reverse[subObjects]]];
IF obj.bbox#bbox THEN ERROR;
};
PWObjects $RoutingClass
WriteRouting: ObjectClassWriteProc = {
routing: PWObjects.RoutingSpecific ← NARROW [me.specific];
WriteRect[h, me.bbox];
WriteInt[h, routing.size];
WriteRect[h, routing.ir];
FOR i: NAT IN [0 .. routing.size) DO
node: PWObjects.Node = routing[i];
WriteInt[h, node.size];
WriteCDProperties[h, node.properties];
FOR j: NAT IN [0 .. node.size) DO
WriteObject[h, node[j].object];
WritePosition[h, node[j].position];
ENDLOOP;
ENDLOOP;
};
ReadRouting: ObjectClassReadProc = {
bbox: CD.Rect ← ReadRect[h];
size: NATNAT [ReadInt[h]];
routing: PWObjects.RoutingSpecific ← NEW [PWObjects.RoutingRep[size]];
routing.ir ← ReadRect[h];
FOR i: NAT IN [0 .. size) DO
nb: NATNAT [ReadInt[h]];
node: PWObjects.Node = NEW [PWObjects.NodeRep[nb]];
node.properties ← ReadCDProperties[h];
FOR j: NAT IN [0 .. nb) DO
object: CD.Object ← ReadObject[h];
node[j] ← [object: object, position: ReadPosition[h]];
ENDLOOP;
routing[i] ← node;
ENDLOOP;
obj ← NEW [CD.ObjectRep ← [class: PWObjects.routingClass, specific: routing, bbox: bbox]];
};
PWObjects $Indirect
WriteIndirect: ObjectClassWriteProc = {
indirect: CD.Object ← NARROW [me.specific];
WriteRect[h, me.bbox];
WriteObject[h, indirect];
};
ReadIndirect: ObjectClassReadProc = {
bbox: CD.Rect ← ReadRect[h];
indirect: CD.Object ← ReadObject[h];
IF indirect.bbox#bbox THEN ERROR;
obj ← PWObjects.CreateIndirect[indirect];
};
CDSymbolicObjectsImpl $AlignmentMarkOb, $PinOb0, $SymbolicSegment
WriteMark: ObjectClassWriteProc = {
};
ReadMark: ObjectClassReadProc = {
RETURN[CDSymbolicObjects.CreateMark[]];
};
WriteSegment: ObjectClassWriteProc = {
WritePosition[h, CD.InterestSize[me]];
};
ReadSegment: ObjectClassReadProc = {
p: CD.Position ← ReadPosition[h];
RETURN [CDSymbolicObjects.CreateSegment[p.y, p.x]]
};
WritePin: ObjectClassWriteProc = {
WritePosition[h, CD.InterestSize[me]];
};
ReadPin: ObjectClassReadProc = {
RETURN [CDSymbolicObjects.CreatePin[ReadPosition[h]]]
};
CDTextsImpl $FlipText, $RigidText
WriteText: ObjectClassWriteProc = {
text: CDTexts.TextSpecific ← NARROW [me.specific];
WriteRope[h, text.text];
WriteRope[h, text.cdFont.supposedName];
WriteInt[h, text.cdFont.scaleI];
};
ReadText: ObjectClassReadProc = {
text: ROPE ← ReadRope[h];
fontName: ROPE ← ReadRope[h];
scale: INT ← ReadInt[h];
font: CDTexts.CDFont ← CDTexts.MakeFont[fontName, scale];
obj ← CDTexts.Create[text, font];
};
Hack for Pins (one more time!)
WriteLayerRef: PropWriteProc = {
WriteLayer[h, NARROW [value, CDPrivate.LayerRef].number];
};
ReadLayerRef: PropReadProc = {
value ← CDPrivate.layers[ReadLayer[h]];
};
Initialization
RegisterDecorationIO: PUBLIC PROC [decoration: Decoration] = {
[] ← RegisterProperty[decoration.objectProp, ObjectPropWrite, ObjectPropRead];
[] ← RegisterProperty[decoration.pinsProp, PinsInstancesPropWrite, InstancesPropRead];
[] ← RegisterProperty[decoration.geometryProp, GeometryInstancesPropWrite, InstancesPropRead];
[] ← RegisterProperty[decoration.transProp, TransPropWrite, TransPropRead];
};
objectsAtom: ATOM = RegisterProperty[$CoreGeometryIOObjects, WriteObjectsProp, ReadObjectsProp];
The prop write and read procedures are only called when the hash tables are initialized for reading, never for writing.
[] ← RegisterProperty[$layerOfPin, WriteLayerRef, ReadLayerRef];
RegisterObjectClass[CDRects.bareRectClass, WriteRectangle, ReadRectangle];
RegisterObjectClass[CDCells.pCellClass, WriteCell, ReadCell];
RegisterObjectClass[PWObjects.abutXClass, WriteAbut, ReadAbut];
RegisterObjectClass[PWObjects.abutYClass, WriteAbut, ReadAbut];
RegisterObjectClass[PWObjects.routingClass, WriteRouting, ReadRouting];
RegisterObjectClass[PWObjects.indirectClass, WriteIndirect, ReadIndirect];
RegisterObjectClass[CDSymbolicObjects.markClass, WriteMark, ReadMark];
RegisterObjectClass[CDSymbolicObjects.segmentClass, WriteSegment, ReadSegment];
RegisterObjectClass[CDSymbolicObjects.pinClass, WritePin, ReadPin];
RegisterObjectClass[CD.FetchObjectClass[$C2NDifRect, CD.FetchTechnology[$cmosB]], WriteRectangle, ReadRectangle]; -- HACK!
RegisterObjectClass[CD.FetchObjectClass[$C2PDifRect, CD.FetchTechnology[$cmosB]], WriteRectangle, ReadRectangle]; -- HACK!
RegisterObjectClass[CDTexts.flipTextClass, WriteText, ReadText];
RegisterObjectClass[CDTexts.rigidTextClass, WriteText, ReadText];
END.