<> <> <> <> <> <<>> DIRECTORY Atom, Ascii, BasicTime, Commander, CD, CDBasics, CDCells, CDDirectory, CDEnvironment, CDEvents, CDInstances, CDImports, CDIO, CDRepetitions, CDSequencer USING [CheckAborted], CDOps, CDPrivate, CDProperties, CDRects, CDValue, Convert, FileNames, FS, IO, Properties, RefTab, Rope, RuntimeError USING [UNCAUGHT], TerminalIO, TokenIO; CDIn: CEDAR PROGRAM IMPORTS Atom, BasicTime, Convert, CD, CDBasics, CDCells, CDDirectory, CDEnvironment, CDEvents, CDInstances, CDIO, CDOps, CDPrivate, CDProperties, CDRects, CDSequencer, CDValue, FileNames, FS, IO, Properties, RefTab, Rope, RuntimeError, TerminalIO, TokenIO EXPORTS CDIO SHARES CD, CDDirectory = BEGIN <<>> xChipndaleFile: INT = 12121983; xVersion: INT = 18; Version: PROC [h: TokenIO.Handle] RETURNS [INT] = INLINE { RETURN [IF h.oldVersion THEN VersionKey[h] ELSE xVersion ] }; IndexTable: TYPE = RECORD[table: SEQUENCE max: CARDINAL OF CD.Object]; TableTable: TYPE = RECORD[tt: SEQUENCE max: CARDINAL OF REF IndexTable]; maxTableSize: INT = 32000; signalOnPropertyProblem: BOOL _ TRUE; --set variable with debugger GetTableEntry: PROC[h: TokenIO.Handle, i: INT] RETURNS [ob: CD.Object_NIL] = INLINE { IF i=maxTableSize THEN { tableTable: REF TableTable _ NEW[TableTable[i/maxTableSize]]; CDProperties.PutPRefProp[h.properties, $TableTable, tableTable]; FOR n: INT IN [0..i/maxTableSize) DO -- don't be picky with size if it is anyway as big tableTable.tt[n] _ NEW[IndexTable[maxTableSize]] ENDLOOP }; }; NoteError: PROC [h: TokenIO.Handle, x: REF] = { IF x=NIL THEN x _ $TRUE; CDProperties.PutPRefProp[h.properties, $errorObject, x]; }; ReadProperties: PUBLIC PROC [h: TokenIO.Handle] RETURNS [props: CD.PropList_NIL] = { PropertyProblem: PROC [h: TokenIO.Handle, key: ATOM_NIL, skip: BOOL_FALSE] = { TerminalIO.PutRope["**** property not readable"]; IF key#NIL THEN { TerminalIO.PutRopes["; probably ", Atom.GetPName[key]]; }; TerminalIO.PutRope["\n"]; IF signalOnPropertyProblem THEN SIGNAL TokenIO.EncodingError; IF skip THEN TokenIO.Skip[h]; }; CheckNoRegistration: PROC [a: ATOM] RETURNS [ok: BOOL] = { <<--ok means NOT registered>> propProcs: CDProperties.PropertyProcs _ CDProperties.FetchProcs[a]; ok _ propProcs=NIL OR propProcs.internalRead=NIL; IF ~ok THEN { TerminalIO.PutRope["**** property registered and not readable"]; PropertyProblem[h, a]; }; }; ExplicitProperty: PROC [h: TokenIO.Handle] = { key: ATOM; propProcs: CDProperties.PropertyProcs; token: TokenIO.Token _ TokenIO.Read[h]; WITH token SELECT FROM push2: TokenIO.Token.push2 => key _ push2.value; push: TokenIO.Token.push => { <<--only old version may use that !>> IF Version[h]>=16 THEN SIGNAL TokenIO.EncodingError; key _ push.value; }; ENDCASE => SIGNAL TokenIO.EncodingError; propProcs _ CDProperties.FetchProcs[key]; IF propProcs#NIL AND propProcs.internalRead#NIL THEN { props _ Properties.PutProp[props, key, propProcs.internalRead[h, key]]; } ELSE IF Version[h]>=12 THEN { n: Rope.ROPE _ Atom.GetPName[key]; TerminalIO.PutRopes["**** property ", n, " not registered\n"]; CDEnvironment.ExecFileEntry[n, CDIO.DesignInReadOperation[h].technology]; propProcs _ CDProperties.FetchProcs[key]; IF propProcs#NIL AND propProcs.internalRead#NIL THEN { props _ Properties.PutProp[props, key, propProcs.internalRead[h, key]]; } ELSE { TerminalIO.PutRope["failed"]; IF signalOnPropertyProblem THEN SIGNAL TokenIO.EncodingError; }; } ELSE OldDefaultProperty[key]; TokenIO.ReadPop[h ! TokenIO.EncodingError => PropertyProblem[h, key, TRUE]]; }; DefaultProperty: PROC [h: TokenIO.Handle] = { PushCase: PROC [key: ATOM] = { IF CheckNoRegistration[key] THEN { SELECT TokenIO.ReadAtom[h] FROM $properties => { propertieProps: CD.PropList _ ReadProperties[h]; props _ Properties.PutProp[props, key, propertieProps]; }; $layer => { layer: CD.Layer _ ReadLayer[h]; props _ Properties.PutProp[props, key, CDPrivate.layers[layer]] }; $ropeList => { rList: LIST OF Rope.ROPE _ NIL; DO token: TokenIO.Token _ TokenIO.Read[h]; WITH token SELECT FROM rope: TokenIO.Token.rope => rList _ CONS[rope.value, rList]; ENDCASE => { TokenIO.ReadAgain[h, token]; props _ Properties.PutProp[props, key, rList]; EXIT; } ENDLOOP }; ENDCASE => PropertyProblem[h, key, FALSE]; TokenIO.ReadPop[h ! TokenIO.EncodingError => PropertyProblem[h, key, TRUE]]; }; }; token: TokenIO.Token _ TokenIO.Read[h]; WITH token SELECT FROM atom: TokenIO.Token.atom => IF CheckNoRegistration[atom.value] THEN { token: TokenIO.Token _ TokenIO.Read[h]; WITH token SELECT FROM ropex: TokenIO.Token.rope => props _ Properties.PutProp[props, atom.value, ropex.value]; atomx: TokenIO.Token.atom => props _ Properties.PutProp[props, atom.value, atomx.value]; intx: TokenIO.Token.int => props _ Properties.PutProp[props, atom.value, NEW[INT_intx.value]]; ENDCASE => PropertyProblem[h, atom.value]; }; push2: TokenIO.Token.push2 => PushCase[push2.value]; push: TokenIO.Token.push => { IF Version[h]>=16 THEN SIGNAL TokenIO.EncodingError; PushCase[push.value]; }; ENDCASE => PropertyProblem[h, NIL]; }; OldDefaultProperty: PROC [key: ATOM] = { token: TokenIO.Token _ TokenIO.Read[h]; WITH token SELECT FROM rope: TokenIO.Token.rope => props _ Properties.PutProp[props, key, rope.value]; atom: TokenIO.Token.atom => props _ Properties.PutProp[props, key, atom.value]; int: TokenIO.Token.int => props _ Properties.PutProp[props, key, NEW[INT_int.value]]; pop: TokenIO.Token.pop => { TokenIO.ReadAgain[h, token]; props _ Properties.PutProp[props, key, key] }; push: TokenIO.Token.push => { IF push.value=NIL OR push.value=$properties THEN { propertieProps: CD.PropList _ ReadProperties[h]; props _ Properties.PutProp[props, key, propertieProps]; } ELSE IF push.value=$layer THEN { layer: CD.Layer _ ReadLayer[h]; props _ Properties.PutProp[props, key, CDPrivate.layers[layer]] } ELSE PropertyProblem[h, key]; TokenIO.ReadPop[h ! TokenIO.EncodingError => PropertyProblem[h, key]]; }; ENDCASE => PropertyProblem[h, key]; }; DO token: TokenIO.Token _ TokenIO.Read[h]; WITH token SELECT FROM atom: TokenIO.Token.atom => SELECT atom.value FROM $Property => ExplicitProperty[h]; $DefaultProperty => DefaultProperty[h]; ENDCASE => {TokenIO.ReadAgain[h, token]; RETURN}; ENDCASE => {TokenIO.ReadAgain[h, token]; RETURN}; ENDLOOP; }; ReadObjectDefinition: PROC [h: TokenIO.Handle, pushRec: BOOL _ FALSE] RETURNS [obj: CD.Object_NIL] = { index: INT _ -1; name: Rope.ROPE _ NIL; versionKey: INT ~ Version[h]; atom: ATOM _ TokenIO.ReadPush[h]; design: CD.Design ~ InlineDesignInReadOperation[h]; class: CD.ObjectClass _ CD.FetchObjectClass[atom, design.technology]; CDSequencer.CheckAborted[design]; IF class=NIL OR class.internalRead=NIL THEN { IF atom=NIL THEN {TerminalIO.PutRope["NIL is a bad object class\n"]; RETURN} ELSE { n: Rope.ROPE ~ Atom.GetPName[atom]; TerminalIO.PutRopes["object class ", n, " not registered\n"]; CDEnvironment.ExecFileEntry[n, design.technology]; class _ CD.FetchObjectClass[atom, design.technology]; } }; IF class=NIL OR class.internalRead=NIL THEN { TerminalIO.PutF1["reading object class %g failed\n", [atom[atom]]]; TokenIO.Skip[h]; obj _ CDRects.CreateBareRect[[10, 10], CD.errorLayer]; NoteError[h, obj]; RETURN }; IF versionKey>=15 THEN { IF class.composed THEN { token: TokenIO.Token _ TokenIO.Read[h]; WITH token SELECT FROM r: TokenIO.Token.rope => { name _ r.value; index _ TokenIO.ReadInt[h]; }; i: TokenIO.Token.int => index _ i.value; ENDCASE => TokenIO.EncodingError; } ELSE { token: TokenIO.Token _ TokenIO.Read[h]; WITH token SELECT FROM atom: TokenIO.Token.atom => IF atom.value=$CDIOUseDir THEN { name _ TokenIO.ReadRope[h]; index _ TokenIO.ReadInt[h] } ELSE IF atom.value=$CDIOUseTable THEN index _ TokenIO.ReadInt[h] ELSE TokenIO.ReadAgain[h, token]; ENDCASE => TokenIO.ReadAgain[h, token]; }; }; obj _ class.internalRead[h, atom]; IF obj=NIL OR obj.class=NIL THEN { obj _ NEW[CD.ObjectRep _ CDRects.CreateRect[[10, 10], CD.errorLayer]^]; }; IF index>0 THEN SetTableEntry[h, index, obj]; IF versionKey<17 AND versionKey>0 THEN { IF class.composed THEN { name _ TokenIO.ReadRope[h]; IF versionKey<=4 THEN [] _ TokenIO.ReadRope[h]; --ignore an old versionkey feature }; }; BEGIN token: TokenIO.Token _ TokenIO.Read[h]; WITH token SELECT FROM pop: TokenIO.Token.pop => NULL; ENDCASE => { props: CD.PropList; TokenIO.ReadAgain[h, token]; <<--read in explicite properties>> props _ ReadProperties[h]; <<--save the properties put on the object by the class, but only if not explicitely read>> FOR pl: Properties.PropList _ obj.properties, pl.rest WHILE pl#NIL DO IF Properties.GetProp[props, pl.first.key]=NIL THEN props _ Properties.PutProp[props, pl.first.key, pl.first.val]; <<--explicite PutProp is ok since props is not yet available to any forked process>> ENDLOOP; <<--put back the combined properties>> obj.properties _ props; TokenIO.ReadPop[h]; IF versionKey<8 THEN OldAdjustInterest[h, obj]; }; END; IF versionKey>=17 THEN { IF name#NIL THEN [] _ CDDirectory.Include[design, obj, name] ELSE IF obj.class.composed THEN CDDirectory.SetOwner[design, obj]; } ELSE --old version-- { IF obj.class.composed THEN { DirectoryOp: PROC [me: CD.Object, design: CD.Design, name: Rope.ROPE, function: CDDirectory.DirectoryFunction] ~ { IF me.class.composed THEN { dp: CDDirectory.DirectoryProc _ CDDirectory.ObToDirectoryProcs[me].directoryOp; IF dp#NIL THEN dp[me, design, name, function] } }; DirectoryOp[obj, NIL, name, rename]; IF versionKey>=15 THEN { IF ~CDDirectory.IsIncluded[design, obj] AND ~pushRec THEN [] _ CDDirectory.Include[design, obj, name]; }; } }; IF obj.layer=CD.errorLayer THEN NoteError[h, obj]; }; ReadObject: PUBLIC PROC [h: TokenIO.Handle] RETURNS [ob: CD.Object_NIL] = { t: TokenIO.Token ~ TokenIO.Read[h]; WITH t SELECT FROM int: TokenIO.Token.int => ob _ GetTableEntry[h, int.value]; push: TokenIO.Token.push => { TokenIO.ReadAgain[h, t]; ob _ ReadObjectDefinition[h]; }; ENDCASE => SIGNAL TokenIO.EncodingError[]; }; ReadInstance: PUBLIC PROC [h: TokenIO.Handle] RETURNS [inst: CD.Instance] = { IF Version[h]<=15 THEN RETURN [OldReadInstance[h]] ELSE { location: CD.Position _ ReadPos[h]; orientation: CD.Orientation _ ReadOrientation[h]; properties: CD.PropList _ ReadProperties[h]; ob: CD.Object _ ReadObject[h]; inst _ NEW[CD.InstanceRep _ [trans: [location, orientation], properties: properties, ob: ob]] } }; ReadPos: PUBLIC PROC [h: TokenIO.Handle] RETURNS [p: CD.Position] = { p.x _ TokenIO.ReadInt[h]; p.y _ TokenIO.ReadInt[h]; }; ReadRect: PUBLIC PROC [h: TokenIO.Handle] RETURNS [r: CD.Rect] = { r.x1 _ TokenIO.ReadInt[h]; r.y1 _ TokenIO.ReadInt[h]; r.x2 _ TokenIO.ReadInt[h]; r.y2 _ TokenIO.ReadInt[h]; }; <> <> <> <> <> <> <<};>> ReadPushRec: PROC [h: TokenIO.Handle] RETURNS [pr: CD.PushRec] = { dummy: CD.Object; token: TokenIO.Token _ TokenIO.Read[h]; WITH token SELECT FROM atom: TokenIO.Token.atom => { IF atom.value=$Nil THEN pr.mightReplace_NIL ELSE { <<--old>> TokenIO.ReadAgain[h, token]; pr.mightReplace _ ReadInstance[h]; } }; ENDCASE =>{ TokenIO.ReadAgain[h, token]; pr.mightReplace _ ReadInstance[h]; }; dummy _ ReadObjectDefinition[h, TRUE]; pr.specific _ NARROW[dummy.specific, CD.CellSpecific]; pr.specific.changed _ TRUE; IF ~Version[h]<17 THEN { atom: ATOM _ TokenIO.ReadAtom[h]; pr.specific.changed _ atom=$T; IF atom=$EndOfDesign THEN { TokenIO.ReadAgain[h, [atom[atom]]]; TerminalIO.PutRope["****THIS FILE SHOULD BE CONVERTED AGAIN !!!"]; }; }; ToListMode[pr.specific]; pr.specific.dummyCell _ TRUE; IF Version[h]<=15 AND Version[h]>=11 THEN { pr.specific.ir _ ReadRect[h]; }; pr.dummyCell _ CDInstances.NewInst[ob: dummy]; }; ToListMode: PROC [cp: CD.CellSpecific] = { old: CD.InstanceSequence _ cp.sequence; cp.sequence _ NIL; IF old#NIL THEN FOR n: NAT IN [0..old.length) DO cp.contents _ CONS[old[n], cp.contents] ENDLOOP; }; ReadLayer: PUBLIC PROC [h: TokenIO.Handle] RETURNS [CD.Layer] = { key: ATOM _ TokenIO.ReadAtom[h]; IF Version[h]<=12 THEN { <<--The layer keys have changed from ChipNDale 2.2 to ChipNDale 2.3. >> SELECT key FROM $combined => key _ $undefLayer; $highLightShade => key _ $shadeLayer; $highLightError => key _ $errorLayer; $backGround => key _ $backGround; ENDCASE => NULL; }; RETURN [CD.FetchLayer[InlineDesignInReadOperation[h].technology, key]]; }; ReadSubObjects: PROC [h: TokenIO.Handle] = { obj: CD.Object; DO token: TokenIO.Token _ TokenIO.Read[h]; TokenIO.ReadAgain[h, token]; WITH token SELECT FROM push: TokenIO.Token.push => obj _ ReadObject[h]; int: TokenIO.Token.int => obj _ ReadObject[h]; ENDCASE => EXIT; ENDLOOP; }; ReadDesignData: PROC [h: TokenIO.Handle, design: CD.Design] = { versionKey: INT _ Version[h]; index, directoryCount: INT; obj: CD.Object; directoryCount _ TokenIO.ReadInt[h]; AllocateTables[h, directoryCount+1]; IF versionKey>=15 THEN ReadSubObjects[h] ELSE { FOR n: INT IN [1..directoryCount] DO index _ TokenIO.ReadInt[h]; obj _ ReadObject[h]; SetTableEntry[h, index, obj]; IF versionKey=0 THEN { DO token: TokenIO.Token _ TokenIO.Read[h]; WITH token SELECT FROM rope: TokenIO.Token.rope => { obx: INT = TokenIO.ReadInt[h]; [] _ CDDirectory.Include[design, GetTableEntry[h, obx], rope.value]; } ENDCASE => {TokenIO.ReadAgain[h, token]; EXIT}; ENDLOOP } ENDLOOP; }; design.properties _ NEW[CD.PropList_ReadProperties[h]]; <<--this overwrites an previous $FileVersion property read in the normal (wrong) way>> CDProperties.PutDesignProp[design, $FileVersion, CDProperties.GetProp[h.properties, $FileVersion]]; design.actual _ NIL; DO token: TokenIO.Token _ TokenIO.Read[h]; WITH token SELECT FROM atom: TokenIO.Token.atom => IF atom.value=$Push THEN {design.actual _ CONS[ReadPushRec[h], design.actual]} ELSE {TokenIO.ReadAgain[h, token]; EXIT}; ENDCASE => {TokenIO.ReadAgain[h, token]; EXIT}; ENDLOOP; <=17 THEN {>> <> <> <<};>> IF TokenIO.ReadAtom[h]#$EndOfDesign THEN SIGNAL TokenIO.EncodingError; }; <> <> <> <> <> <> <> <> <> <<};>> GetFile: PROC [from: REF_NIL, wDir: Rope.ROPE _ NIL] RETURNS [stream: IO.STREAM_NIL, iDidTheOpen: BOOL _ FALSE] = { ReadName: PROC [wDir: Rope.ROPE] RETURNS [name: Rope.ROPE] = { IF Rope.IsEmpty[wDir] THEN TerminalIO.PutRope[" input file"] ELSE TerminalIO.PutRopes[" input file (", wDir, ")"]; name _ TerminalIO.RequestRope[" > "]; }; nameAsSpecified, nameAsFound: Rope.ROPE_NIL; IF from#NIL AND ISTYPE[from, IO.STREAM] THEN { RETURN [NARROW[from, IO.STREAM], FALSE]; }; IF from=NIL THEN nameAsSpecified _ ReadName[wDir] ELSE IF ISTYPE[from, Rope.ROPE] THEN { nameAsSpecified _ NARROW[from, Rope.ROPE]; IF Rope.IsEmpty[nameAsSpecified] THEN nameAsSpecified _ ReadName[(IF wDir#NIL THEN wDir ELSE FileNames.CurrentWorkingDirectory[])]; } ELSE { TerminalIO.PutRope["ReadDesign: bad parameter\n"]; GOTO NotOpened }; nameAsFound _ CDEnvironment.FindFile[nameAsSpecified, ".dale", wDir]; IF Rope.IsEmpty[nameAsFound] THEN { TerminalIO.PutRopes[nameAsSpecified, " not found\n"]; GOTO NotOpened; }; stream _ FS.StreamOpen[nameAsFound, $read, FS.binaryStreamOptions ! FS.Error => IF error.group # bug THEN { TerminalIO.PutF["%g not opened: %g\n", [rope[nameAsFound]], [rope[error.explanation]]]; GOTO NotOpened; }]; iDidTheOpen _ TRUE; TerminalIO.PutRopes[nameAsFound, " opened \n"]; EXITS NotOpened => {} }; ReadDesign: PUBLIC PROC [from: REF_NIL, check: PROC [h: TokenIO.Handle] RETURNS [BOOL] _ NIL, wDir: Rope.ROPE _ NIL, stop: REF BOOL _ NIL] RETURNS [design: CD.Design_NIL] = { wDirUsed: Rope.ROPE _ NIL; DoInner: PROC [h: TokenIO.Handle, iDidTheOpen: BOOL] RETURNS [design: CD.Design_NIL] = { ENABLE { TokenIO.EncodingError => { TerminalIO.PutRope["** TokenIO encoding problem\n"]; REJECT; }; RuntimeError.UNCAUGHT => { TerminalIO.PutRope["** problem while reading; abort or proceed\n"]; REJECT }; UNWIND => { TokenIO.Close[h, iDidTheOpen]; }; }; TechnologyCheck: PROC [h: TokenIO.Handle] = { <<--Side-effect: if bad, design is set to NIL>> ENABLE UNWIND => design _ NIL; dont: BOOL _ CDEvents.ProcessEvent[eventRegistration: readEvent, design: design, x: h, listenToDont: TRUE].dont; IF dont THEN { design _ NIL; TerminalIO.PutRope["**technology rejects read\n"]; } }; VersionAndSealCheck: PROC [h: TokenIO.Handle] = { <<--ChipNDale check>> versionKey: INT; IF TokenIO.ReadInt[h]#xChipndaleFile THEN { TerminalIO.PutRope["File is not a ChipNDale design\n"]; ERROR TokenIO.EncodingError; }; <<--version check>> versionKey _ TokenIO.ReadInt[h]; IF versionKey<0 THEN { TerminalIO.PutF["****design was written with a ChipNDale version which was NOT released; dont expect any help if problems occur; [filekey = %g]\n", [integer[versionKey]]]; versionKey _ -versionKey; }; CDProperties.PutProp[h.properties, $VersionKey, NEW[INT_versionKey]]; IF versionKey#xVersion THEN { OldMsg: PROC [versionKey: INT, bar: BOOL_FALSE, conv: BOOL_FALSE, extra: Rope.ROPE_NIL] = { IF bar THEN TerminalIO.PutRope["****\n"]; TerminalIO.PutF1["design was written with old ChipNDale version; filekey = %g\n", [integer[versionKey]]]; IF conv THEN TerminalIO.PutRope["please convert all your designs (by reading and subsequent writing)\n"]; IF extra#NIL THEN TerminalIO.PutRope[extra]; IF bar THEN TerminalIO.PutRope["****\n"]; }; h.oldVersion _ TRUE; IF versionKey>xVersion THEN { -- too new TerminalIO.PutRope["design has newer file format version\n; bringover ChipNDale !!\n"]; ERROR TokenIO.EncodingError; } ELSE IF versionKey IN [13..xVersion] THEN { -- not new but dont tell it NULL } ELSE IF versionKey IN [6..xVersion] THEN { -- not new but everything ok OldMsg[versionKey]; } ELSE IF versionKey=4 THEN { -- known problem versions OldMsg[versionKey, TRUE, TRUE, "check carefully the alignment of cells which have n-well; if you have troubles, try CD18InputToggle and repeat the input\n"]; } ELSE IF versionKey=3 THEN { -- known problem versions OldMsg[versionKey, TRUE, TRUE, "check carefully the alignment of cells which have n-well\n"]; } ELSE IF versionKey IN [0..xVersion] THEN { -- not new but please convert OldMsg[versionKey, TRUE, TRUE]; } ELSE { -- too old OldMsg[versionKey, TRUE, FALSE, "sorry this version is no more supported\n"]; ERROR TokenIO.EncodingError; }; }; <<--seal check>> IF versionKey>0 THEN { SELECT TokenIO.ReadInt[h] FROM -1 => {}; -2 => {TerminalIO.PutRope["file is cached; not the truth\n"]; h.truth _ FALSE; }; ENDCASE => { TerminalIO.PutRope["**file had not been properly closed\n"]; ERROR TokenIO.EncodingError; }; }; }; ReadDesignVersion: PROC [h: TokenIO.Handle, design: CD.Design] = { designVersionKey: Rope.ROPE_NIL; IF Version[h]>=7 THEN designVersionKey _ TokenIO.ReadRope[h]; IF Rope.IsEmpty[designVersionKey] THEN designVersionKey _ Convert.RopeFromTime[from: BasicTime.Now[], end: seconds]; CDProperties.PutDesignProp[design, $FileVersion, designVersionKey]; CDProperties.PutProp[h.properties, $FileVersion, designVersionKey]; }; <<-- DoInner>> VersionAndSealCheck[h]; technologyKey _ TokenIO.ReadAtom[h]; technologyName _ TokenIO.ReadRope[h]; technology _ CDEnvironment.LoadTechnology[technologyKey, technologyName]; IF technology=NIL THEN GOTO Oops; h.clientData _ design _ CDOps.CreateDesign[technology]; TechnologyCheck[h]; IF design=NIL THEN GOTO Oops; design.name _ TokenIO.ReadRope[h]; ReadDesignVersion[h, design]; --read before check, fixed again later IF iDidTheOpen THEN { fullFName: Rope.ROPE; created: BasicTime.GMT; [fullFName, created] _ FileIdentification[stream]; CDValue.Store[boundTo: design, key: $CDxFromFile, value: fullFName]; CDValue.Store[boundTo: design, key: $CDxLastFile, value: fullFName]; SetWorkingDirectory[design, FileNames.Directory[fullFName]]; IF created#BasicTime.nullGMT THEN CDValue.Store[boundTo: design, key: $CDxFileCreated, value: NEW[INT_LOOPHOLE[created]]]; IF Rope.IsEmpty[design.name] THEN { name: Rope.ROPE _ FileNames.GetShortName[fullFName, TRUE]; name _ Rope.Substr[name, 0, Rope.Index[name, 0, ".dale", FALSE]]; design.name _ name; }; }; IF check#NIL THEN IF NOT check[h] THEN GOTO Oops; ReadDesignData[h, design]; EXITS Oops => RETURN [design_NIL]; }; <<-- begin ReadDesign>> stream: IO.STREAM; h: TokenIO.Handle; iDidTheOpen: BOOL; technology: CD.Technology; technologyKey: ATOM; technologyName: Rope.ROPE; [stream, iDidTheOpen] _ GetFile[from, wDir]; IF stream=NIL THEN RETURN; IF stop=NIL THEN stop _ NEW[BOOL_FALSE]; h _ TokenIO.CreateReader[stream: stream, stop: stop ! TokenIO.EncodingError => { TerminalIO.PutRope["**TokenIO says file not ok; maybe not a ChipNDale file\n"]; GOTO Oops }; ]; design _ DoInner[h, iDidTheOpen]; IF design#NIL THEN { IF CDProperties.GetPRefProp[h.properties, $errorObject]#NIL THEN { TerminalIO.PutRope[" **design includes some error message(s)\n"]; }; [] _ CDEvents.ProcessEvent[eventRegistration: afterInputEvent, design: design, x: h, listenToDont: FALSE]; }; TokenIO.Close[h, iDidTheOpen]; EXITS Oops => RETURN [NIL]; }; FileIdentification: PROC [s: IO.STREAM] RETURNS [fullFName: Rope.ROPE _ NIL, created: BasicTime.GMT _ BasicTime.nullGMT] = { file: FS.OpenFile; file _ FS.OpenFileFromStream[s ! IO.Error => GOTO Oops]; fullFName _ FS.GetName[file! FS.Error => GOTO Oops].fullFName; fullFName _ FileNames.ConvertToSlashFormat[fullFName]; created _ FS.GetInfo[file! FS.Error => GOTO Oops].created; EXITS Oops => {fullFName _ NIL; created _ BasicTime.nullGMT} }; ReadOrientation: PUBLIC PROC [h: TokenIO.Handle] RETURNS [orientation: CD.Orientation] = { i: NAT _ TokenIO.ReadInt[h]; IF Version[h]<=3 THEN { IF i IN [0..15] THEN orientation _ VAL[i/4*2 + i MOD 2] ELSE SIGNAL TokenIO.EncodingError; } ELSE IF i IN [0..7] THEN orientation _ VAL[i] ELSE SIGNAL TokenIO.EncodingError }; <<>> MakeName: PUBLIC PROC [base: Rope.ROPE, ext: Rope.ROPE_NIL, wDir: Rope.ROPE_NIL, modifier: Rope.ROPE_NIL] RETURNS [Rope.ROPE] = { RETURN [CDEnvironment.MakeName[base, ext, wDir, modifier]]; }; SetWorkingDirectory: PUBLIC PROC [design: REF, wDir: Rope.ROPE] = { CDEnvironment.SetWorkingDirectory[design, wDir]; }; GetWorkingDirectory: PUBLIC PROC [design: REF] RETURNS [wDir: Rope.ROPE_NIL] = { RETURN [CDEnvironment.GetWorkingDirectory[design]]; }; MakeShortName: PUBLIC PROC [design: CD.Design] RETURNS [name: Rope.ROPE _ NIL] = { Translator: PROC [old: CHAR] RETURNS [new: CHAR] = { SELECT TRUE FROM old IN ['0..'9] => RETURN [old]; old IN ['a..'z] => RETURN [old]; old IN ['A..'Z] => RETURN [old]; ENDCASE => RETURN ['x]; }; name _ Rope.Translate[base: CD.DesignName[design], translator: Translator]; }; InlineDesignInReadOperation: PUBLIC PROC [h: TokenIO.Handle] RETURNS [CD.Design] = INLINE { RETURN [NARROW[h.clientData]] }; VersionKey: PUBLIC PROC [h: TokenIO.Handle] RETURNS [INT] = { WITH CDProperties.GetProp[h.properties, $VersionKey] SELECT FROM i: REF INT => RETURN [i^]; ENDCASE => RETURN [0]; }; <<--================================================================>> <<-- old stuff>> setManually: INT _ 0; --used for saving old designs specialForVersion4: BOOL _ FALSE; FitObjectO: PROC [ob: CD.Object, location: CD.Position _ [0, 0], orientation: CD.Orientation _ CD.Orientation[original]] RETURNS [trans: CD.Transformation] = { trans.orient _ orientation; trans.off _ CDBasics.SubPoints[location, CDBasics.BaseOfRect[CDBasics.MapRect[ob.bbox, [[0, 0], orientation]]]]; }; OldReadInstance: PROC [h: TokenIO.Handle] RETURNS [inst: CD.Instance] = { location: CD.Position _ ReadPos[h]; orientation: CD.Orientation _ CDIO.ReadOrientation[h]; properties: CD.PropList _ ReadProperties[h]; ob: CD.Object _ ReadObject[h]; versionKey: INT ~ Version[h]; IF versionKey>=8 THEN { inst _ NEW[CD.InstanceRep _ [trans: FitObject23[ob, location, orientation, h], properties: properties, ob: ob]] } ELSE { IF versionKey>=5 THEN { <> inst _ NEW[CD.InstanceRep _ [trans: CDOps.FitObjectI[ob, location, orientation], properties: properties, ob: ob]] } ELSE { --ancient cases absoluteMode: BOOL _ TRUE; IF versionKey<3 THEN absoluteMode_TRUE ELSE IF versionKey=4 THEN { IF specialForVersion4 THEN IF ob.class.composed THEN absoluteMode_TRUE ELSE absoluteMode_FALSE ELSE absoluteMode_FALSE } ELSE IF versionKey=3 THEN { IF ob.class.composed THEN absoluteMode_TRUE ELSE absoluteMode_FALSE }; IF setManually=1 THEN absoluteMode_TRUE ELSE IF setManually=2 THEN absoluteMode_FALSE ELSE IF setManually=3 THEN absoluteMode_ob.class.composed; IF absoluteMode THEN inst _ NEW[CD.InstanceRep _ [trans: FitObjectO[ob, location, orientation], properties: properties, ob: ob]] ELSE inst _ NEW[CD.InstanceRep _ [trans: CDOps.FitObjectI[ob, location, orientation], properties: properties, ob: ob]] }; }; }; Get23Table: PROC [h: TokenIO.Handle] RETURNS [RefTab.Ref_NIL] = { rt: RefTab.Ref; WITH Properties.GetProp[h.properties^, $convert23] SELECT FROM tab: RefTab.Ref => rt _ tab; ENDCASE => { rt _ RefTab.Create[201]; h.properties^ _ Properties.PutProp[h.properties^, $convert23, rt] }; RETURN [rt]; }; BBox23: PROC [ob: CD.Object, h: TokenIO.Handle] RETURNS [bbox: CD.Rect] = { bbox_ob.bbox; IF ob.class.composed THEN WITH RefTab.Fetch[Get23Table[h], ob].val SELECT FROM rr: REF CD.Rect => RETURN [rr^] ENDCASE => NULL; }; FitObject23: PROC [ob: CD.Object, location: CD.Position _ [0, 0], orientation: CD.Orientation _ CD.Orientation[original], h: TokenIO.Handle] RETURNS [trans: CD.Transformation] = { <<--for the conversion from cd2.3 to cd2.4 use bbox with interest rect excluded>> oldR: CD.Rect _ ob.bbox; IF CDCells.IsCell[ob] THEN oldR _ BBox23[ob, h]; trans.orient _ orientation; trans.off _ CDBasics.SubPoints[location, CDBasics.BaseOfRect[CDBasics.MapRect[oldR, [[0, 0], orientation]]]]; }; OldCD18Input: Commander.CommandProc = { <<--fix an old old problem>> specialForVersion4 _ ~specialForVersion4; IF specialForVersion4 THEN cmd.out.PutRope["Fileformat: switch to first versions of cd18\n"] ELSE cmd.out.PutRope["Fileformat: switch to last versions of cd18\n"]; }; OldAdjustInterest: PROC [h: TokenIO.Handle, ob: CD.Object] = { OldSetInterest: PROC [ob: CD.Object, r: CD.Rect] = { WITH ob.specific SELECT FROM s: CDRepetitions.RepSpecific => s.ir _ r; s: CDImports.ImportSpecific => s.ir _ r; s: CDRepetitions.RepSpecific => s.ir _ r; ENDCASE => NULL; }; IF ob.class.composed AND CDIO.VersionKey[h]<8 THEN { WITH CDProperties.GetObjectProp[from: ob, prop: oldInterestRectProperty] SELECT FROM pp: REF CD.Rect => { IF CDBasics.NonEmpty[pp^] THEN OldSetInterest[ob, pp^]; CDProperties.PutProp[ob, oldInterestRectProperty, NIL]; }; ENDCASE => NULL; }; }; OldInternalReadOrigin: PROC [h: TokenIO.Handle, prop: ATOM] RETURNS [val: REF_NIL] = { [] _ ReadPos[h]; }; OldInternalReadRProperty: PROC [h: TokenIO.Handle, prop: ATOM] RETURNS [val: REF] = { val _ NEW[CD.Rect_ReadRect[h]] }; oldOriginProperty: ATOM = $origin; oldInterestRectProperty: ATOM = $interestRect; OldInit: PROC [] = { [] _ CDProperties.RegisterProperty[oldInterestRectProperty]; CDProperties.InstallProcs[prop: oldInterestRectProperty, procs: CDProperties.PropertyProcsRec[ makeCopy: CDProperties.DontCopy, internalRead: OldInternalReadRProperty, exclusive: TRUE ] ]; [] _ CDProperties.RegisterProperty[oldOriginProperty]; CDProperties.InstallProcs[prop: oldOriginProperty, procs: CDProperties.PropertyProcsRec[ makeCopy: CDProperties.DontCopy, internalRead: OldInternalReadOrigin, exclusive: TRUE ] ]; CDEnvironment.RegisterCommander["CD18InputToggle", OldCD18Input, "Toggle input mode of old ChipNDale version CD18"]; }; <<--================================================================>> readEvent: CDEvents.EventRegistration = CDEvents.RegisterEventType[$ReadTechnologyPrivate]; afterInputEvent: CDEvents.EventRegistration = CDEvents.RegisterEventType[$AfterInput]; OldInit[]; END. <> <<>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<(CD22)>> <> <> <<(CD22)>> <> <> <<(CD23)>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<>>