CDIn.mesa
Last Edited by: Kimr, November 28, 1983 10:22 am
Last Edited by: Jacobi, February 8, 1984 9:41 am
DIRECTORY
Atom,
CD,
CDApplications,
CDDirectory,
CDEvents,
CDExtras,
CDIO,
CDIOExtras,
CDOps USING [CreateDesign],
CDPrivate,
CDProperties,
CDRects,
CDValue,
FileNames,
FS,
IO,
Rope USING [ROPE, IsEmpty, Length, Fetch],
RuntimeError USING [UNCAUGHT],
TerminalIO,
TokenIO;
CDIn:
CEDAR
MONITOR
IMPORTS Atom, CD, CDApplications, CDDirectory, CDEvents, CDExtras, CDIO, CDOps, CDPrivate, CDProperties, CDRects, CDValue, FileNames, FS, IO, Rope, RuntimeError, TerminalIO, TokenIO
EXPORTS CDIO, CDIOExtras
SHARES CDDirectory =
BEGIN
xChipndaleFile: INT = 12121983;
xVersion: INT = 3;
-- global vars
versionKey: PUBLIC INT;
designInReadOperation: PUBLIC CD.Design ← NIL;
binfile: IO.STREAM;
fileName: Rope.ROPE;
indexTable: REF IndexTable ← NIL;
IndexTable: TYPE = RECORD[table: SEQUENCE max: CARDINAL OF CD.ObPtr];
ReadProperties:
PUBLIC PROC []
RETURNS [props:
CD.Properties←
NIL] =
BEGIN
key: ATOM;
propProcs: CDProperties.PropertyProcs;
token: TokenIO.Token;
DO
token ← TokenIO.ReadToken[];
IF token.ref#$Property
THEN {
TokenIO.ReadAgain[];
RETURN [props];
};
key ← TokenIO.ReadPushFlag[];
propProcs ← CDProperties.FetchProcs[key];
IF propProcs#
NIL
AND propProcs.internalRead#
NIL
THEN {
props ← Atom.PutPropOnList[propList: props, prop: key, val: propProcs.internalRead[key]];
}
ELSE {
token ← TokenIO.ReadToken[];
IF token.kind=rope
OR token.kind=atom
OR token.kind=int
THEN
props ← Atom.PutPropOnList[propList: props, prop: key, val: token.ref]
ELSE
IF token.kind=popFlag
THEN {
TokenIO.ReadAgain[];
props ← Atom.PutPropOnList[propList: props, prop: key, val: key]
}
ELSE {
TerminalIO.WriteRope["**property not readable \n"];
ERROR TokenIO.EncodingError;
};
};
TokenIO.ReadPopFlag[];
ENDLOOP;
END;
SkipThrough:
PROC [] =
BEGIN
token: TokenIO.Token;
level: INT ← 0;
DO
token ← TokenIO.ReadToken[];
IF token.kind=pushFlag THEN level ← level+1
ELSE IF token.kind=popFlag THEN level ← level-1;
IF level<0 THEN EXIT;
ENDLOOP;
END;
SetName:
PROC[me:
CD.ObPtr, r: Rope.
ROPE] ~
INLINE {
IF me.p.hasChildren THEN CDDirectory.ObToDirectoryProcs[me].setName[me, r]
};
SetKey:
PROC[me:
CD.ObPtr, r: Rope.
ROPE] ~
INLINE {
IF me.p.hasChildren THEN CDDirectory.ObToDirectoryProcs[me].setKey[me, r]
};
ReadObjectDefinition:
PROC []
RETURNS [obj:
CD.ObPtr←
NIL] =
BEGIN
token: TokenIO.Token;
atom: ATOM = TokenIO.ReadPushFlag[];
p: REF READONLY CD.ObjectProcs ← CD.FetchObjectProcs[atom, designInReadOperation.technology];
IF p=
NIL
OR p.internalRead=
NIL
THEN {
TerminalIO.WriteRope["unknown object "];
TerminalIO.WriteRope[Atom.GetPName[atom]];
TerminalIO.WriteLn[];
SkipThrough[];
obj ← CDRects.CreateBareRect[[10, 10], CD.highLightError];
}
ELSE {
obj ← p.internalRead[];
IF obj=NIL THEN obj ← CDRects.CreateBareRect[[10, 10], CD.highLightError];
IF versionKey>0
THEN {
IF p.hasChildren
THEN {
name: Rope.ROPE ← TokenIO.ReadRope[];
key: Rope.ROPE ← TokenIO.ReadRope[];
SetName[obj, name];
SetKey[obj, key];
};
};
token ← TokenIO.ReadToken[];
IF token.kind#popFlag
THEN {
TokenIO.ReadAgain[];
obj.properties ← ReadProperties[];
TokenIO.ReadPopFlag[];
}
}
END;
ReadObject:
PUBLIC
PROC []
RETURNS [
CD.ObPtr] =
BEGIN
t: TokenIO.Token = TokenIO.ReadToken[];
IF t.kind=int
THEN {
-- instance
ins: INT ← NARROW[t.ref, REF INT]^;
RETURN [indexTable.table[ins]]
};
TokenIO.ReadAgain;
RETURN [ReadObjectDefinition[]]
END;
ReadApplicationPtr:
PUBLIC
PROC []
RETURNS [
CD.ApplicationPtr] =
BEGIN
RelativeMode:
PROC []
RETURNS [
BOOL] =
INLINE {
RETURN [versionKey>=3]
};
ap: CD.ApplicationPtr;
location: CD.DesignPosition ← ReadPosition[];
orientation: CD.Orientation ← CDIO.ReadOrientation[];
properties: CD.Properties ← ReadProperties[];
ob: CD.ObPtr ← ReadObject[];
IF RelativeMode[]
THEN
ap ← CDApplications.NewApplicationI[ob: ob, location: location, orientation: orientation, properties: properties]
ELSE
ap ← NEW[CD.Application ← [location: location, orientation: orientation, properties: properties, ob: ob, selected: FALSE]];
RETURN [ap];
END;
ReadApplicationList:
PUBLIC PROC []
RETURNS [list:
CD.ApplicationList←
NIL] =
BEGIN
num: INT = TokenIO.ReadInt[];
THROUGH [0..num)
DO
list ← CONS[ReadApplicationPtr[], list];
ENDLOOP
END;
ReadPushRec:
PROC []
RETURNS [pr:
CD.PushRec] =
BEGIN
token: TokenIO.Token ← TokenIO.ReadToken[];
dummy: CD.ObPtr;
IF token.ref=$Nil THEN pr.mightReplace←NIL
ELSE {
TokenIO.ReadAgain[];
pr.mightReplace ← ReadApplicationPtr[];
};
dummy ← ReadObjectDefinition[];
pr.changed ← pr.indirectlyChanged ← TRUE;
pr.specific ← NARROW[dummy.specificRef, CD.CellPtr];
pr.dummyCell ← CDApplications.NewApplicationI[ob: dummy];
END;
ReadPosition:
PROC []
RETURNS [pos:
CD.DesignPosition] =
BEGIN
pos.x ← TokenIO.ReadInt[];
pos.y ← TokenIO.ReadInt[];
END;
ReadLevel:
PUBLIC
PROC []
RETURNS [
CD.Level] =
BEGIN
key: ATOM = TokenIO.ReadAtom[];
RETURN [CD.FetchLevel[designInReadOperation.technology, key]];
END;
ReadDesignData:
PROC [] =
BEGIN
index, directoryCount: INT;
token: TokenIO.Token;
obj: CD.ObPtr;
directoryCount ← TokenIO.ReadInt[];
indexTable ← NEW[IndexTable[directoryCount+1]]; -- ???
FOR n:
INT
IN [1..directoryCount]
DO
index ← TokenIO.ReadInt[];
obj ← ReadObjectDefinition[];
indexTable.table[index] ← obj;
IF versionKey=0
THEN {
token ← TokenIO.ReadToken[];
WHILE token.kind=rope
DO
name: Rope.ROPE = NARROW[token.ref];
obx: INT = TokenIO.ReadInt[];
[] ← CDDirectory.Include[designInReadOperation, indexTable.table[obx], name];
token ← TokenIO.ReadToken[];
ENDLOOP;
TokenIO.ReadAgain[];
}
ELSE
IF obj.p.hasChildren
THEN {
name: Rope.ROPE = CDDirectory.Name[obj];
[] ← CDDirectory.Include[designInReadOperation, obj, name];
}
ENDLOOP;
designInReadOperation.properties ← ReadProperties[];
designInReadOperation.actual ← NIL;
DO
token ← TokenIO.ReadToken[];
IF token.ref#$Push
THEN {
TokenIO.ReadAgain[];
EXIT;
};
designInReadOperation.actual ← CONS[ReadPushRec[], designInReadOperation.actual];
ENDLOOP;
token ← TokenIO.ReadToken[];
IF token.ref#$EndOfDesign THEN ERROR TokenIO.EncodingError;
END;
ReadDesign:
PUBLIC
ENTRY
PROC [from:
REF←
NIL, check:
PROC [
CD.Design]
RETURNS [
BOOL] ←
NIL]
RETURNS [
CD.Design] =
--from is either a IO.STREAM, a Rope.ROPE, or NIL
--check: (called if non NIL), is called after technology and design-name is initialized
-- read proceeds only if check returns TRUE
--returns NIL if design not read in successfully
--viewer is not opened
BEGIN
ENABLE
UNWIND => {
indexTable ← NIL;
designInReadOperation ← NIL;
};
design: CD.Design; -- is initialized before return only
-- all internal routines use designInReadOperation in place of design
DoReadDesign:
INTERNAL
PROC [check:
PROC [
CD.Design]
RETURNS [
BOOL]] =
-- result design returned in designInReadOperation
-- handles all the TokenIO business
BEGIN
ENABLE {
RuntimeError.
UNCAUGHT => {
designInReadOperation ← NIL;
TerminalIO.WriteRope["unknown problem while reading; it is ok to abort\n"];
CDPrivate.Debug["unknown error in reading"];
GOTO DoReturn;
};
TokenIO.EncodingError => {
designInReadOperation ← NIL;
TerminalIO.WriteRope["TokenIO encoding problem; it is ok to abort\n"];
CDPrivate.Debug["read error in encoding"];
GOTO DoReturn;
};
};
DoWhileAttached:
INTERNAL
PROC [] =
--and always Release
BEGIN
ENABLE
UNWIND => {
designInReadOperation ← NIL;
TokenIO.ReleaseReader[];
};
TechnologyCheck:
INTERNAL
PROC [] =
--Side-effect: if bad, designInReadOperation is set to NIL
BEGIN
ENABLE UNWIND => {designInReadOperation ← NIL};
dont:
BOOL ← CDEvents.ProcessEvent[
ev: readEvent,
design: designInReadOperation,
x: NIL,
listenToDont: TRUE
].dont;
IF dont
THEN {
designInReadOperation ← NIL;
TerminalIO.WriteRope["Technology rejects read\n"];
}
END;
VersionAndSealCheck:
INTERNAL PROC [] =
BEGIN
--chipndale check
IF TokenIO.ReadInt[]#xChipndaleFile
THEN {
TerminalIO.WriteRope["File is not a chipndale design\n"];
ERROR TokenIO.Error[other, "chipndale filekey"];
};
--version check
versionKey ← TokenIO.ReadInt[];
IF versionKey#xVersion
THEN {
IF versionKey>xVersion
THEN {
-- too new
TerminalIO.WriteRope["design was written with newer chipndaleversion\n"];
TerminalIO.WriteRope["get a new chipndale version\n"];
ERROR TokenIO.Error[other, "chipndale versionkey"];
}
ELSE
IF versionKey
IN [2..xVersion]
THEN {
-- not new but dont tell it
NULL
}
ELSE
IF versionKey
IN [1..xVersion]
THEN {
-- not new but everything ok
TerminalIO.WriteRope["design was written with older chipndaleversion\n"];
}
ELSE
IF versionKey
IN [0..xVersion]
THEN {
-- not new but please convert
TerminalIO.WriteRope["design was written with older chipndaleversion\n"];
TerminalIO.WriteRope["Please convert also your other designs\n"];
}
ELSE {
-- too old
TerminalIO.WriteRope["design was written with older chipndaleversion\n"];
TerminalIO.WriteRope["This version is no more supported\n"];
ERROR TokenIO.Error[other, "chipndale versionkey"];
};
};
--seal check
IF versionKey>0
THEN {
IF TokenIO.ReadInt[]#-1
THEN {
TerminalIO.WriteRope["File had not been properly closed; has bad seal\n"];
ERROR TokenIO.Error[other, "file had not been properly closed"];
};
};
END;
-- DoWhileAttached
VersionAndSealCheck[];
technologyKey ← TokenIO.ReadAtom[];
technologyName ← TokenIO.ReadRope[];
technology ← CD.FetchTechnology[technologyKey];
IF technology=
NIL
THEN {
TerminalIO.WriteRope["technology '"];
TerminalIO.WriteRope[technologyName];
TerminalIO.WriteRope["' not loded\n"];
GOTO NotDoneAndRelease
};
designInReadOperation ← CDOps.CreateDesign[technology];
TechnologyCheck[];
IF designInReadOperation=NIL THEN GOTO NotDoneAndRelease;
designInReadOperation.name ← TokenIO.ReadRope[];
IF Rope.IsEmpty[designInReadOperation.name] THEN designInReadOperation.name ← fileName;
IF check#
NIL
THEN {
IF NOT check[designInReadOperation] THEN GOTO NotDoneAndRelease;
};
ReadDesignData[];
TokenIO.ReleaseReader[];
EXITS
NotDoneAndRelease => {
designInReadOperation ← NIL;
TokenIO.ReleaseReader[];
};
END;
-- DoReadDesign
technology: CD.Technology;
technologyKey: ATOM;
technologyName: Rope.ROPE;
designInReadOperation ← NIL;
TokenIO.AttachReader[binfile !
TokenIO.Error => {
r: Rope.ROPE ← "bad explanation";
IF ISTYPE[explanation, Rope.ROPE] THEN r←NARROW[explanation];
TerminalIO.WriteRope[r];
TerminalIO.WriteRope["... not attached\n"];
GOTO NotAttached
}
];
DoWhileAttached[];
EXITS
NotAttached, DoReturn => RETURN
END;
ReadName:
PROC []
RETURNS [name: Rope.
ROPE] =
BEGIN
wDir: Rope.ROPE 𡤏ileNames.CurrentWorkingDirectory[];
TerminalIO.WriteRope[" input file"];
IF wDir#
NIL
THEN {
TerminalIO.WriteRope[" ("];
TerminalIO.WriteRope[wDir];
TerminalIO.WriteRope[")"];
};
name ← TerminalIO.RequestRope[" > "];
END;
-- begin ReadDesign
iDidTheOpen: BOOL ← FALSE;
name: Rope.ROPE;
-- open file; assign fileName and binfile
IF from#
NIL
AND
ISTYPE[from,
IO.
STREAM]
THEN {
fileName ← NIL;
binfile ← NARROW[from, IO.STREAM]
}
ELSE {
IF from=NIL THEN name ← ReadName[]
ELSE
IF
ISTYPE[from, Rope.
ROPE]
THEN {
name ← NARROW[from, Rope.ROPE];
IF Rope.IsEmpty[name] THEN name ← ReadName[];
}
ELSE {
TerminalIO.WriteRope["ReadDesign does not support type of 'from' parameter\n"];
GOTO NotOpened;
};
fileName ← CDExtras.AppendExt[name, "dale"];
binfile ←
FS.StreamOpen[fileName !
FS.Error =>
IF error.group # bug
THEN {
TerminalIO.WriteRope[fileName];
TerminalIO.WriteRope[" not opened: "];
TerminalIO.WriteRope[error.explanation];
TerminalIO.WriteLn[];
GOTO NotOpened;
}];
iDidTheOpen ← TRUE;
TerminalIO.WriteRope[fileName];
TerminalIO.WriteRope[" opened \n"];
};
-- do the actual work
DoReadDesign[check];
design ← designInReadOperation;
-- finalize
designInReadOperation ← NIL;
indexTable ← NIL;
IF iDidTheOpen THEN IO.Close[binfile];
RETURN [design];
EXITS
NotOpened =>
{
indexTable ← NIL;
designInReadOperation ← NIL;
TerminalIO.WriteRope["Read not done\n"];
RETURN [NIL];
}
END;
CheckWorkingDirectory:
PROC [wDir: Rope.
ROPE]
RETURNS [slashWDir: Rope.
ROPE] =
--if wDir is a directory, assign it to slashWDir
--else slashWDir ← nil
INLINE BEGIN
IF FileNames.IsADirectory[wDir]
AND
NOT FileNames.IsAPattern[wDir]
THEN {
length: INT;
slashWDir ← FileNames.ConvertToSlashFormat[wDir];
length ← slashWDir.Length[];
IF slashWDir = wDir
AND length > 0
AND slashWDir.Fetch[length - 1] = '/
THEN {
RETURN [slashWDir];
}
};
RETURN [NIL]
END;
GetDesignsWorkingDirectory:
PUBLIC PROC [design:
CD.Design]
RETURNS [wDir: Rope.
ROPE] =
BEGIN
x: REF = CDValue.Fetch[boundTo: design, key: $CDxWorkingDirectory, propagation: design];
IF
ISTYPE[x, Rope.
ROPE]
AND x#
NIL
THEN
RETURN [CheckWorkingDirectory[NARROW[x]].slashWDir];
END;
SetDesignsWorkingDirectory:
PUBLIC PROC [design:
CD.Design, wDir: Rope.
ROPE] =
BEGIN
wDir ← CheckWorkingDirectory[wDir].slashWDir;
IF wDir#NIL THEN CDValue.Store[boundTo: design, key: $CDxWorkingDirectory, value: wDir];
END;
NewDesignHasBeenCreated: CDEvents.EventProc =
-- PROC [event: REF, design: CD.Design, x: REF] --
--repaint captions and sometimes the contents
BEGIN
SetDesignsWorkingDirectory[design, FileNames.CurrentWorkingDirectory[]];
END;
-- Module Initialization
readEvent: CDEvents.EventRegistration = CDEvents.RegisterEventType[$ReadTechnologyPrivate];
CDEvents.RegisterEventProc[$CreateNewDesign, NewDesignHasBeenCreated];
END.
versionKey 0
versionKey 1: objects with children carry names
versionKey 2:
versionKey 3: June 15, 1984 3:46:13 pm PDT; applications position is its innerrect; this allows to shrink or grow the nwell from cmos