<> <> <> <> <> <<>> DIRECTORY Atom, Ascii, BasicTime, Commander, CD, CDBasics, CDCells, CDDirectory, CDEnvironment, CDEvents, CDInstances, CDIO, CDSequencer USING [CheckAborted], CDOps, CDPrivate, CDProperties, CDRects, CDValue, Convert, FileNames, FS, IO, PropertyLists, RefTab, Rope, RuntimeError USING [UNCAUGHT], TerminalIO, TokenIO, CDOldInterestRects; CDIn: CEDAR PROGRAM IMPORTS Atom, BasicTime, Commander, Convert, CD, CDBasics, CDCells, CDDirectory, CDEnvironment, CDEvents, CDInstances, CDIO, CDOps, CDPrivate, CDProperties, CDRects, CDSequencer, CDValue, FileNames, FS, IO, PropertyLists, RefTab, Rope, RuntimeError, TerminalIO, TokenIO, CDOldInterestRects EXPORTS CDIO SHARES CD, CDDirectory = BEGIN <<>> xChipndaleFile: INT = 12121983; xVersion: INT = 16; 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 setManually: INT _ 0; --used for saving old designs specialForVersion4: BOOL _ FALSE; 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 }; }; 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 _ PropertyLists.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 _ PropertyLists.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 _ PropertyLists.PutProp[props, key, propertieProps]; }; $layer => { layer: CD.Layer _ ReadLayer[h]; props _ PropertyLists.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 _ PropertyLists.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 _ PropertyLists.PutProp[props, atom.value, ropex.value]; atomx: TokenIO.Token.atom => props _ PropertyLists.PutProp[props, atom.value, atomx.value]; intx: TokenIO.Token.int => props _ PropertyLists.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 _ PropertyLists.PutProp[props, key, rope.value]; atom: TokenIO.Token.atom => props _ PropertyLists.PutProp[props, key, atom.value]; int: TokenIO.Token.int => props _ PropertyLists.PutProp[props, key, NEW[INT_int.value]]; pop: TokenIO.Token.pop => { TokenIO.ReadAgain[h, token]; props _ PropertyLists.PutProp[props, key, key] }; push: TokenIO.Token.push => { IF push.value=NIL OR push.value=$properties THEN { propertieProps: CD.PropList _ ReadProperties[h]; props _ PropertyLists.PutProp[props, key, propertieProps]; } ELSE IF push.value=$layer THEN { layer: CD.Layer _ ReadLayer[h]; props _ PropertyLists.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; }; DirectoryOp: PROC [me: CD.Object, design: CD.Design, name: Rope.ROPE, function: CDDirectory.DirectoryFunction] RETURNS [proceed: BOOL] ~ INLINE { IF proceed_me.class.inDirectory THEN { dp: CDDirectory.DirectoryProc _ CDDirectory.ObToDirectoryProcs[me].directoryOp; IF dp#NIL THEN proceed _ dp[me, design, name, function] } }; ReadObjectDefinition: PROC [h: TokenIO.Handle, pushRec: BOOL _ FALSE] RETURNS [obj: CD.Object_NIL] = { index: INT _ -1; name: Rope.ROPE; 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]; RETURN }; IF versionKey>=15 THEN { IF class.inDirectory THEN { index _ TokenIO.ReadInt[h]; } ELSE { token: TokenIO.Token _ TokenIO.Read[h]; WITH token SELECT FROM atom: TokenIO.Token.atom => 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>0 THEN { IF class.inDirectory 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 => { TokenIO.ReadAgain[h, token]; obj.properties _ ReadProperties[h]; TokenIO.ReadPop[h]; IF versionKey<8 THEN CDOldInterestRects.AdjustInterest[h, obj]; }; END; IF obj.class.inDirectory THEN { [] _ DirectoryOp[obj, NIL, name, rename]; IF versionKey>=15 THEN { IF ~CDDirectory.IsOwner[design, obj] AND ~pushRec THEN [] _ CDDirectory.Include[design, obj, name]; }; }; }; 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[]; }; Get23Table: PROC [h: TokenIO.Handle] RETURNS [RefTab.Ref_NIL] = { rt: RefTab.Ref; WITH PropertyLists.GetProp[h.properties^, $convert23] SELECT FROM tab: RefTab.Ref => rt _ tab; ENDCASE => { rt _ RefTab.Create[201]; h.properties^ _ PropertyLists.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.inDirectory 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]; <> < IF cp.specifiedIr THEN >> <> < NULL;>> trans.orient _ orientation; trans.off _ CDBasics.SubPoints[location, CDBasics.BaseOfRect[CDBasics.MapRect[oldR, [[0, 0], orientation]]]]; }; 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.inDirectory THEN absoluteMode_TRUE ELSE absoluteMode_FALSE ELSE absoluteMode_FALSE } ELSE IF versionKey=3 THEN { IF ob.class.inDirectory 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.inDirectory; 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]] }; }; }; 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 { 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; 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 } ELSE IF obj.class.inDirectory THEN { <<--hack to simplify some read procedures... >> IF ~CDDirectory.IsOwner[design, obj] THEN { name: Rope.ROPE = CDDirectory.Name[obj]; [] _ CDDirectory.Include[design, obj, name]; } } 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; IF TokenIO.ReadAtom[h]#$EndOfDesign THEN SIGNAL TokenIO.EncodingError; }; 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] 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[ev: 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]; 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 { IF TokenIO.ReadInt[h]#-1 THEN { 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]; }; ReadDesignName: PROC [h: TokenIO.Handle] RETURNS [name: Rope.ROPE] = { name _ TokenIO.ReadRope[h]; IF Rope.IsEmpty[name] THEN { name _ FileNames.GetShortName[fileName, TRUE]; name _ Rope.Substr[name, 0, Rope.Index[name, 0, ".dale", FALSE]] } }; <<-- DoInner>> VersionAndSealCheck[h]; technologyKey _ TokenIO.ReadAtom[h]; technologyName _ TokenIO.ReadRope[h]; technology _ CDEnvironment.LoadTechnology[technologyKey, technologyName]; IF technology=NIL THEN GOTO NotDone; h.clientData _ design _ CDOps.CreateDesign[technology]; TechnologyCheck[h]; IF design=NIL THEN GOTO NotDone; design.name _ ReadDesignName[h]; ReadDesignVersion[h, design]; --read before check, fixed again later IF check#NIL THEN IF NOT check[h] THEN GOTO NotDone; ReadDesignData[h, design]; CDEnvironment.SetWorkingDirectory[design, wDirUsed]; CDValue.Store[boundTo: design, key: $CDxFromFile, value: fileName]; CDValue.Store[boundTo: design, key: $CDxLastFile, value: fileName]; TokenIO.Close[h, FALSE]; EXITS NotDone => RETURN [design_NIL]; }; <<-- begin ReadDesign>> h: TokenIO.Handle; technology: CD.Technology; technologyKey: ATOM; technologyName: Rope.ROPE; binfile: IO.STREAM; fileName: Rope.ROPE; iDidTheOpen: BOOL _ FALSE; name: Rope.ROPE; streamOptions: FS.StreamOptions _ ALL[TRUE]; streamOptions[tiogaRead] _ FALSE; streamOptions[commitAndReopenTransOnFlush] _ FALSE; streamOptions[truncatePagesOnClose] _ TRUE; streamOptions[finishTransOnClose] _ TRUE; streamOptions[closeFSOpenFileOnClose] _ TRUE; <<-- open file; assign fileName and binfile>> IF wDir=NIL THEN wDir _ FileNames.CurrentWorkingDirectory[]; IF from#NIL AND ISTYPE[from, IO.STREAM] THEN { fileName _ NIL; binfile _ NARROW[from, IO.STREAM] } ELSE { ReadName: PROC [wDir: Rope.ROPE] RETURNS [name: Rope.ROPE] = { TerminalIO.PutRopes[" input file (", wDir, ")"]; name _ TerminalIO.RequestRope[" > "]; }; IF from=NIL THEN name _ ReadName[wDir] ELSE IF ISTYPE[from, Rope.ROPE] THEN { name _ NARROW[from, Rope.ROPE]; IF Rope.IsEmpty[name] THEN name _ ReadName[wDir]; } ELSE { TerminalIO.PutRope["ReadDesign: bad parameter\n"]; GOTO NotOpened; }; fileName _ CDEnvironment.MakeName[name, "dale", wDir]; binfile _ FS.StreamOpen[fileName, $read, streamOptions ! FS.Error => IF error.group # bug THEN { TerminalIO.PutRope[Rope.Cat[fileName, " not opened: ", error.explanation, "\n"]]; GOTO NotOpened; }]; fileName _ RealFileName[binfile, fileName]; wDirUsed _ FileNames.Directory[fileName]; iDidTheOpen _ TRUE; TerminalIO.PutRopes[fileName, " opened \n"]; }; <<-- do the actual work>> IF stop=NIL THEN stop _ NEW[BOOL_FALSE]; h _ TokenIO.CreateReader[stream: binfile, stop: stop ! TokenIO.EncodingError => { TerminalIO.PutRope["**TokenIO says file not ok; maybe not a ChipNDale file\n"]; GOTO NotOpened }; ]; design _ DoInner[h]; IF design#NIL THEN [] _ CDEvents.ProcessEvent[ev: afterInputEvent, design: design, x: h, listenToDont: FALSE]; TokenIO.Close[h, iDidTheOpen]; EXITS NotOpened => RETURN [NIL]; }; RealFileName: PROC [s: IO.STREAM, default: Rope.ROPE_NIL] RETURNS [n: Rope.ROPE] = { file: FS.OpenFile; n _ default; file _ FS.OpenFileFromStream[s ! IO.Error => GOTO Oops]; n _ FS.GetName[file! FS.Error => GOTO Oops].fullFName; EXITS Oops => n _ default }; 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] = { TrailingDot: PROC [base: Rope.ROPE] RETURNS [INT] = { <<--position of last dot>> len: INT _ Rope.Length[base]; pos: INT _ len; WHILE pos > 0 DO SELECT Rope.Fetch[base, pos _ pos - 1] FROM '. => RETURN [pos]; '!, '], '>, '/ => EXIT; ENDCASE; ENDLOOP; RETURN [len]; }; SuggestedModule: PROC [base: Rope.ROPE] RETURNS [Rope.ROPE] = { <<--given a filename, suggests a modulename>> len, dot: INT; base _ FileNames.GetShortName[base]; len _ Rope.Length[base]; dot _ TrailingDot[base]; IF len>dot AND Rope.Equal[Rope.Substr[base, dot+1], "dale", FALSE] THEN base _ Rope.Substr[base, 0, dot]; RETURN [base] }; <<--MakeShortName>> WITH CDValue.Fetch[boundTo: design, key: $CDxFromFile] SELECT FROM r: Rope.ROPE => name _ SuggestedModule[r]; ENDCASE => NULL; IF name=NIL THEN name _ design.name; IF name=NIL THEN name _ "noname" }; <<>> CD18Input: Commander.CommandProc = { <<--fix an old old problem>> specialForVersion4 _ ~specialForVersion4; IF specialForVersion4 THEN cmd.out.PutRope["Fileformat: switch to old version of cd18\n"] ELSE cmd.out.PutRope["Fileformat: switch to last version of cd18\n"]; }; 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]; }; readEvent: CDEvents.EventRegistration = CDEvents.RegisterEventType[$ReadTechnologyPrivate]; afterInputEvent: CDEvents.EventRegistration = CDEvents.RegisterEventType[$AfterInput]; Commander.Register["///Commands/CD18InputToggle", CD18Input, "toggle input mode of cd18"]; END. <> <<>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<(CD22)>> <> <> <<(CD22)>> <> <> <<(CD23)>> <> <> <> <> <> <> <> <> <> <> <> <> <> <<>> <<>>