CDExtrasImpl.mesa (part of ChipNDale)
Copyright © 1983, 1985 by Xerox Corporation. All rights reserved.
by Christian Jacobi, September 8, 1983 9:45 am
last edited by Christian Jacobi, March 14, 1986 7:13:11 pm PST
DIRECTORY
Atom,
CD,
CDCells,
CDDirectory,
CDExtras,
CDOps,
CDPrivate,
CDProperties,
CDSimpleOps,
Rope;
CDExtrasImpl: CEDAR MONITOR
IMPORTS Atom, CD, CDCells, CDDirectory, CDOps, CDProperties, CDSimpleOps, Rope
EXPORTS CDExtras
SHARES CD =
BEGIN
CreateDummyObject: PUBLIC PROC[design: CD.Design] RETURNS [CD.Object] =
--create a dummy cell object which contains the whole design.
--On future changes of the design, the dummy object may or may not
--get obsolete.
BEGIN
cellOb: CD.Object ← CDCells.CreateEmptyCell[];
cptr: CD.CellPtr ← NARROW[cellOb.specificRef];
FOR l: LIST OF CD.PushRec ← design.actual, l.rest WHILE l#NIL DO
cptr.contents ← CONS[
NEW[CD.InstanceRep ← [
ob: l.first.dummyCell.ob,
location: [0, 0],
orientation: CD.original,
selected: FALSE
]],
cptr.contents
];
ENDLOOP;
RETURN [cellOb]
END;
Pair: TYPE = RECORD [p: CDDirectory.EnumerateObjectsProc, x: REF, key: REF];
EnumerationEnteredWhileInProgress: ERROR = CODE;
entered: BOOL FALSE;
Enter: ENTRY PROC [] =
BEGIN
IF entered THEN RETURN WITH ERROR EnumerationEnteredWhileInProgress;
entered←TRUE;
END;
Leave: ENTRY PROC [] =
BEGIN
entered←FALSE;
END;
EnumerateChildrenObjects: PUBLIC PROC[me: CD.Object, p: CDDirectory.EnumerateObjectsProc, x: REF] =
--enumerate me and its children objects
BEGIN ENABLE UNWIND => Leave[];
pair: REF Pair ← NEW[Pair];
pair^ ← [p, x, pair];
Enter[];
MyEnum[me, pair];
Leave[];
END;
MyEnum: PROC [me: CD.Object, x: REF] =
BEGIN
pair: REF Pair ← NARROW[x];
v: REF ← CDProperties.GetProp[me, $CDExtrasImplsTouched];
IF v=pair.key THEN RETURN; -- already visited
--mark visited
CDProperties.PutProp[me, $CDExtrasImplsTouched, pair.key];
--enumerate my children first
IF me.class.inDirectory THEN CDDirectory.EnumerateChildObjects[me, MyEnum, x];
pair.p[me, pair.x]; -- call clients enumerator proc
END;
EnumerateDesignObjects: PUBLIC PROC [design: CD.Design, p: CDDirectory.EnumerateObjectsProc, x: REF] =
BEGIN ENABLE UNWIND => Leave[];
EachChild: CDDirectory.EachEntryAction = {MyEnum[ob, pair]};
pair: REF Pair ← NEW[Pair];
pair^ ← [p, x, pair];
Enter[];
[] ← CDDirectory.Enumerate[design, EachChild];
FOR l: LIST OF CD.PushRec ← design.actual, l.rest WHILE l#NIL DO
MyEnum[l.first.dummyCell.ob, pair];
IF l.first.mightReplace#NIL THEN MyEnum[l.first.mightReplace.ob, pair];
ENDLOOP;
Leave[];
END;
PopToTopLayer: PUBLIC PROC [design: CD.Design] =
--if "design" is pushed in, it will be popped out, either by flushing,
--replacing cells or creating new cells
BEGIN
WHILE design.actual.rest#NIL DO
IF NOT CDCells.PopFromCell[design, newcell] THEN EXIT
ENDLOOP;
IF design.actual.rest#NIL THEN ERROR
END;
PopToTopLevel: PUBLIC PROC [design: CD.Design] =
BEGIN
WHILE CDCells.IsPushedIn[design] DO
[] ← CDCells.PopFromCell[design, newcell, "--wasPushedIn--"];
ENDLOOP;
END;
Cellize: PUBLIC PROC [design: CD.Design, name: Rope.ROPENIL] RETURNS [cell: CD.Object←NIL, pos: CD.Position] =
--makes a single "cell" of of the "design", removes all instances;
--pos: if "cell" is included at position "pos" in an empty design we would get "design" again
--if "design" is pushed in, it will be popped out, either by flushing,
--replacing cells or creating new cells
BEGIN
done: BOOL;
il: CD.InstanceList;
PopToTopLayer[design];
CDSimpleOps.SelectAll[design];
IF (il�Ops.InstList[design])#NIL THEN {
IF il.rest=NIL AND ISTYPE[il.first.ob.specificRef, CD.CellPtr] AND il.first.orientation=CD.original THEN {
cell ← il.first.ob;
IF name#NIL THEN [] ← CDDirectory.Rename[design, cell, name];
done ← TRUE
}
ELSE {
IF name=NIL THEN name ← design.name;
IF name=NIL THEN name ← "no named design";
[done, cell] ← CDCells.CreateCellSelected[design, name];
};
IF done THEN {
pos ← CDOps.InstList[design].first.location;
}
ELSE cell ← NIL
};
CDOps.SetInstList[design, NIL]
END;
GetTechnology: PUBLIC PROC [name: Rope.ROPE] RETURNS [t: CD.Technology] =
--far more friendly version of CD.GetTechnology
--NIL if not found
BEGIN
EachTechnology: CD.TechnologyEnumerator = {
IF Rope.Equal[tech.name, name, FALSE]
OR Rope.Equal[Atom.GetPName[tech.key], name, FALSE]
THEN {quit ← TRUE; t ← tech}
};
[] ← CD.EnumerateTechnologies[EachTechnology];
END;
END.