DIRECTORY BasicTime, CDIO, CDIOExtras, CD, CDDirectory, CDEvents, CDExtras, CDPrivate, CDProperties, CDValue, Convert, FileNames, FS, IO, Process, Rope, TerminalIO, TokenIO; CDOut: CEDAR PROGRAM --monitored by TokenIO IMPORTS BasicTime, CD, CDIO, CDDirectory, CDEvents, CDExtras, CDProperties, CDValue, Convert, FileNames, FS, IO, Process, Rope, TerminalIO, TokenIO EXPORTS CDIO, CDIOExtras SHARES CDProperties = BEGIN xChipndaleFile: INT = 12121983; xVersion: INT = 12; propKeyForKey: REF = NEW[INT]; gDesign: CD.Design _ NIL; gDirectoryNum: INT; gDirectoryMark: TokenIO.Mark; gThisKey: REF _ NIL; gLastKey: REF _ NIL; gQuiet: BOOL _ FALSE; WriteRope: PROC [r: Rope.ROPE] = INLINE BEGIN IF ~gQuiet THEN TerminalIO.WriteRope[r] END; WriteLayer: PUBLIC PROC [l: CD.Layer] = BEGIN TokenIO.WriteAtom[CD.LayerKey[l]]; END; WritePos: PUBLIC PROC [p: CD.Position] = BEGIN TokenIO.WriteInt[p.x]; TokenIO.WriteInt[p.y]; END; WriteRect: PUBLIC PROC[r: CD.Rect] = BEGIN TokenIO.WriteInt[r.x1]; TokenIO.WriteInt[r.y1]; TokenIO.WriteInt[r.x2]; TokenIO.WriteInt[r.y2]; END; FakeCopyProperties: PROC[propList: CD.PropList] RETURNS [newList: CD.PropList_NIL] = INLINE BEGIN DoFakeCopy: PROC[] = { FOR l: CD.PropList _ propList, l.rest WHILE l#NIL DO IF ISTYPE[l.first.key, ATOM] THEN newList _ CONS[l.first, newList]; ENDLOOP; }; IF propList#NIL THEN CDProperties.DoWithinLock[DoFakeCopy] END; WriteProperties: PUBLIC PROC [props: CD.PropList] = BEGIN FOR l: CD.PropList _ FakeCopyProperties[props], l.rest WHILE l#NIL DO IF ISTYPE[l.first.key, ATOM] THEN { pp: CDProperties.PropertyProcs = CDProperties.FetchProcs[l.first.key]; IF pp#NIL AND pp.internalWrite#NIL THEN { TokenIO.WriteAtom[$Property]; TokenIO.WritePushFlag[NARROW[l.first.key, ATOM]]; pp.internalWrite[l.first.key, l.first.val]; TokenIO.WritePopFlag[]; } ELSE WITH l.first.val SELECT FROM r: Rope.ROPE => { TokenIO.WriteAtom[$DefaultProperty]; TokenIO.WriteAtom[NARROW[l.first.key, ATOM]]; TokenIO.WriteRope[r]; }; at: ATOM => { TokenIO.WriteAtom[$DefaultProperty]; TokenIO.WriteAtom[NARROW[l.first.key, ATOM]]; TokenIO.WriteAtom[at]; }; ri: REF INT => { TokenIO.WriteAtom[$DefaultProperty]; TokenIO.WriteAtom[NARROW[l.first.key, ATOM]]; TokenIO.WriteInt[ri^]; }; pl: CDPrivate.LayerRef => { TokenIO.WriteAtom[$DefaultProperty]; TokenIO.WritePushFlag[NARROW[l.first.key, ATOM]]; TokenIO.WriteAtom[$layer]; -- now comes a property list WriteLayer[pl.number]; TokenIO.WritePopFlag[]; }; pl: CD.PropList => { TokenIO.WriteAtom[$DefaultProperty]; TokenIO.WritePushFlag[NARROW[l.first.key, ATOM]]; TokenIO.WriteAtom[$properties]; -- now comes a property list WriteProperties[pl]; TokenIO.WritePopFlag[]; }; rl: LIST OF Rope.ROPE => { TokenIO.WriteAtom[$DefaultProperty]; TokenIO.WritePushFlag[NARROW[l.first.key, ATOM]]; TokenIO.WriteAtom[$ropeList]; -- now comes a property list FOR l: LIST OF Rope.ROPE _ rl, l.rest WHILE l#NIL DO TokenIO.WriteRope[l.first]; ENDLOOP; TokenIO.WritePopFlag[]; }; ENDCASE => NULL; }; ENDLOOP; END; WriteInstance: PUBLIC PROC [ap: CD.Instance] = BEGIN TokenIO.WriteInt[ap.location.x]; TokenIO.WriteInt[ap.location.y]; CDIO.WriteOrientation[ap.orientation]; WriteProperties[ap.properties]; WriteObject[ap.ob]; END; Length: PROC [il: CD.InstanceList] RETURNS [leng: INT_0] = INLINE BEGIN FOR list: CD.InstanceList _ il, list.rest WHILE list#NIL DO leng _ leng+1; ENDLOOP; END; WriteInstanceList: PUBLIC PROC [list: CD.InstanceList] = BEGIN TokenIO.WriteInt[Length[list]]; FOR l: CD.InstanceList _ list, l.rest WHILE l#NIL DO WriteInstance[l.first]; ENDLOOP; END; WriteObject: PUBLIC PROC [ob: CD.Object] = BEGIN Process.Yield[]; --should make output slower than redraw... WITH CDProperties.GetPropFromObject[from: ob, prop: gThisKey] SELECT FROM key: REF INT => { WriteRope["."]; TokenIO.WriteInt[key^]; }; ENDCASE => { WriteRope["x"]; DoWriteObject[ob] }; END; DoWriteObject: PROC [ob: CD.Object, number: INT_-1] = BEGIN IF ob.class.internalWrite=NIL THEN { ob1: CD.Object _ CDDirectory.ExpandHard[ob, gDesign, NIL]; IF ob1#NIL THEN { WriteRope["*"]; WriteObject[ob1]; } ELSE { TokenIO.WritePushFlag[$Unknown]; TokenIO.WritePopFlag[]; WriteRope["*object not written\n"]; }; } ELSE { TokenIO.WritePushFlag[ob.class.objectType]; ob.class.internalWrite[ob]; IF ob.class.inDirectory THEN { TokenIO.WriteRope[CDDirectory.Name[ob]]; }; WriteProperties[ob.properties]; TokenIO.WritePopFlag[]; }; IF number#-1 THEN CDProperties.PutPropOnObject[onto: ob, prop: gThisKey, val: NEW[INT_number]]; CDProperties.PutPropOnObject[onto: ob, prop: gLastKey, val: NIL]; END; WritePushLevel: PROC [pl: LIST OF CD.PushRec] = BEGIN IF pl=NIL THEN RETURN; IF pl.rest#NIL THEN WritePushLevel[pl.rest]; TokenIO.WriteAtom[$Push]; IF pl.first.mightReplace#NIL THEN WriteInstance[pl.first.mightReplace] ELSE TokenIO.WriteAtom[$Nil]; WriteObject[pl.first.dummyCell.ob]; WriteRect[pl.first.specific.dIr]; END; EachChild: CDDirectory.EnumerateObjectsProc --PROC [me: Object, x: REF]-- = BEGIN xx: REF = CDProperties.GetPropFromObject[from: me, prop: gThisKey]; IF xx#NIL THEN RETURN; -- it and its children are already out IF me.class.inDirectory THEN CDDirectory.EnumerateChildObjects[me: me, p: EachChild, x: x]; gDirectoryNum _ gDirectoryNum+1; TokenIO.WriteInt[gDirectoryNum]; DoWriteObject[me, gDirectoryNum]; END; EachDirectoryEntry: CDDirectory.EachEntryAction --[name: Rope.ROPE, ob: CD.Object] RETURNS [quit: BOOL_FALSE]-- = BEGIN EachChild[ob, NIL]; END; InnerWriteDesign: PROC [] = BEGIN ENABLE TokenIO.WritingStopped => { RemoveOldProperties: PROC[design: CD.Design, key: REF] = { CDExtras.RemoveProperties[design, key]; }; RemoveOldProperties[gDesign, gLastKey]; REJECT }; PrepareOutput: PROC = { gThisKey _ NEW[INT]; gLastKey _ CDValue.Fetch[boundTo: gDesign, key: propKeyForKey, propagation: design]; IF gLastKey=NIL THEN {gLastKey_NEW[INT]}; CDValue.Store[boundTo: gDesign, key: propKeyForKey, value: gThisKey]; gDirectoryNum _ 0; }; NameForOutput: PROC [d: CD.Design] RETURNS [Rope.ROPE] = { IF Rope.Length[d.name]<=0 OR Rope.Fetch[d.name]='/ OR Rope.Fetch[d.name]='[ THEN RETURN[NIL] ELSE RETURN [d.name]; }; TimeKey: PROC [] RETURNS [Rope.ROPE] = { RETURN [Convert.RopeFromTime[from: BasicTime.Now[], end: seconds]]; }; PrepareOutput[]; TokenIO.WriteRope[NameForOutput[gDesign]]; TokenIO.WriteRope[TimeKey[]]; gDirectoryMark _ TokenIO.MarkAndWriteInt[gDirectoryNum]; -- number of entries in directory [] _ CDDirectory.Enumerate[design: gDesign, action: EachDirectoryEntry]; WriteProperties[gDesign.properties^]; WritePushLevel[gDesign.actual]; TokenIO.UpdateMark[mark: gDirectoryMark, value: gDirectoryNum]; TokenIO.WriteAtom[$EndOfDesign]; END; WriteHelpMessage: PROC [] = BEGIN Write: PROC [r: Rope.ROPE] = { TerminalIO.WriteRopes[r, "\n"]; }; Write["****************************************"]; Write["Help for saving a design:"]; Write["wait until the background saving is done and make a copy of it! (but don't rely on background saving alone; background saving is done WITHOUT requiring monitor locks, for obvious reasons.)"]; Write["then, try regular output again, before you proceed to any of the more drastic methods following:\n"]; Write["SHIFT-SHIFT-SWAT (>2 seconds) should save all designs"]; Write["or use a command tool: (the command tool commands require you to bringover the necesarry sources and bcd's first)"]; Write[" ""_ CDSequencerImpl.savePeriod _ -1"" "]; Write[" prevents any further un-monitored automatic saving in parallel with your other command tool commands."]; Write[" ""_ CDEmergencyHandling.SaveAll[]"" "]; Write[" or"]; Write[" ""_ TokenIO.ReleaseWriter[]"" "]; Write[" to release the locks; after this try a regular output command"]; Write["****************************************"]; END; OpenFile: PROC [design: CD.Design, to: REF, emergency: BOOL_FALSE] RETURNS [stream: IO.STREAM, mustClose: BOOL_TRUE, name: Rope.ROPE_NIL] = BEGIN CheckForOverWrite: PROC [name: Rope.ROPE] = BEGIN temfile: IO.STREAM; temfile _ FS.StreamOpen[name ! FS.Error => IF error.group#bug THEN GOTO ok]; TerminalIO.WriteRopes["File ", name, " exists already; overwrite?"]; IF ~TerminalIO.Confirm[choice: "overwrite", label: "file exists"] THEN ERROR ABORTED; TerminalIO.WriteRope[" yes\n"]; EXITS ok => NULL --this is the "normal" case of an not yet existing file END; InteractiveName: PROC [wDir: Rope.ROPE_NIL] RETURNS [name: Rope.ROPE] = BEGIN TerminalIO.WriteRope["file name:"]; IF ~Rope.IsEmpty[wDir] THEN TerminalIO.WriteRopes[" (", wDir, ")"]; name _ TerminalIO.RequestRope[" > "]; name _ CDIO.MakeName[name, "dale", wDir]; CheckForOverWrite[name]; END; wDir: Rope.ROPE _ CDIO.GetWorkingDirectory[design]; IF Rope.IsEmpty[wDir] THEN wDir _ FileNames.CurrentWorkingDirectory[]; IF to#NIL THEN WITH to SELECT FROM s: IO.STREAM => RETURN [stream_s, mustClose_FALSE, name_NIL]; r: Rope.ROPE => name _ r; ENDCASE => TerminalIO.WriteRope["bad file parameter in WriteDesign\n"]; IF Rope.IsEmpty[name] THEN IF emergency THEN name _ "///temp/ChipNDale/emergency/emergency.dale" ELSE name _ InteractiveName[wDir]; name _ CDIO.MakeName[name, "dale", wDir]; stream _ FS.StreamOpen[fileName: name, accessOptions: $create, keep: 2 ! FS.Error => { mustClose _ FALSE; stream _ NIL; IF error.group#bug THEN CONTINUE; } ]; END; Attach: PROC [stream: IO.STREAM, emergency: BOOL_FALSE, quiet: BOOL_FALSE] RETURNS [done: BOOL_TRUE] = BEGIN TokenIO.AttachWriter[stream ! TokenIO.Error => {done_FALSE; CONTINUE}]; IF ~done AND emergency THEN { FOR i: INT IN [0..5] DO TokenIO.StopWriting[]; Process.Pause[Process.SecondsToTicks[1]]; TokenIO.StopWriting[]; Process.Pause[Process.SecondsToTicks[2]]; TerminalIO.WriteRope["TRIES TO BREAK THE LOCK\n"]; TokenIO.ReleaseWriter[]; -- XXXXXXX DANGEROUS Process.Pause[Process.SecondsToTicks[1]]; done_TRUE; TokenIO.AttachWriter[stream ! TokenIO.Error => {done_FALSE; CONTINUE}]; IF done THEN RETURN; ENDLOOP; }; IF ~done AND ~quiet THEN { TerminalIO.WriteRope["ChipNDale internal locks are hold\n"]; WriteHelpMessage[]; }; END; WriteDesign: PUBLIC PROC [design: CD.Design, to: REF, quiet: BOOL, emergency: BOOL] RETURNS [done: BOOL_FALSE] = BEGIN mustClose: BOOL_FALSE; binFile: IO.STREAM; fileName: Rope.ROPE; sealMark: TokenIO.Mark; [binFile, mustClose, fileName] _ OpenFile[design, to, emergency]; IF binFile=NIL THEN { IF ~quiet THEN TerminalIO.WriteRope["file not created\n"]; RETURN }; IF ~Attach[binFile, emergency, quiet] THEN RETURN; [] _ CDEvents.ProcessEvent[ev: beforeOutputEvent, design: design, x: NIL, listenToDont: FALSE]; gQuiet _ quiet; gDesign _ design; TokenIO.WriteInt[xChipndaleFile]; TokenIO.WriteInt[xVersion]; sealMark _ TokenIO.MarkAndWriteInt[0]; -- this is an invalid seal; it will be fixed at the end TokenIO.WriteAtom[gDesign.technology.key]; TokenIO.WriteRope[gDesign.technology.name]; IF CDEvents.ProcessEvent[ev: writeEvent, design: gDesign, x: NIL, listenToDont: TRUE].dont THEN { WriteRope["write not done\n"]; TokenIO.ReleaseWriter[]; IO.Close[binFile]; RETURN }; InnerWriteDesign[]; TokenIO.UpdateMark[sealMark, -1]; -- validate seal TokenIO.ReleaseWriter[]; IF mustClose THEN IO.Close[binFile]; WriteRope["\n"]; TerminalIO.WriteRopes["design ", gDesign.name, " written on file "]; TerminalIO.WriteRopes[fileName, "\n"]; done _ TRUE; END; writeEvent: CDEvents.EventRegistration = CDEvents.RegisterEventType[$WriteTechnologyPrivate]; beforeOutputEvent: CDEvents.EventRegistration = CDEvents.RegisterEventType[$BeforeOutput]; END. ώCDOut.mesa Copyright c 1983, 1986 by Xerox Corporation. All rights reserved. by Ch. Jacobi, December 12, 1983 2:02 pm some code from Kim Rachmeler Last Edited by: Jacobi, January 29, 1986 11:52:04 am PST -- global variables -- protected through attachment with TokenIO --we make a copy! so GetProp's reorder does not fool us --object has internalWrite proc --at this place we know that CDExtras will fork and will set the priority down --uses globals --opens the file but does not any output to it --Errors DontOverWrite if necessary --file exists already --to is either a IO.STREAM, a Rope.ROPE, or NIL --if emergency, some locks are ignored, interactive input is skipped; you better --roll back after an emergency write is done -- Module initialization Κ΄˜codešœ ™ Kšœ Οmœ7™BKšœ(™(Kšœ™Kšœ8™8K™—šΟk ˜ Kšœ ž˜ Kšžœ˜Kšœ ˜ Kšžœ˜Kšœ ˜ Kšœ ˜ K˜ K˜ K˜ Kšœ˜Kšœ˜Kšœ ž˜ Kšžœ˜Kšžœ˜K˜K˜K˜ K˜—K˜šΠblœžœžœΟc˜+Kš žœ žœžœLžœžœ$˜“Kšžœžœ ˜Kšžœ˜—Kšž˜K˜Kšœžœ ˜Kšœ žœ˜K˜Kšœžœžœžœ˜K˜Kšœ™Kšœ,™,Kšœ žœžœ˜Kšœžœ˜Kšœ˜Kšœ ž œ˜Kšœ ž œ˜Kšœž œ˜K˜K˜šΟn œžœ žœ˜ Kšž ˜ Kšžœ žœ˜'Kšž˜—K˜š‘ œž œžœ ˜'Kšž˜Kšœžœ˜"Kšžœ˜—K˜š‘œžœžœžœ ˜(Kšž˜Kšœ˜Kšœ˜Kšžœ˜—K˜š‘ œžœžœžœ˜$Kšž˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšžœ˜—K˜š ‘œžœ žœ žœ žœ žœž˜[Kšž˜š‘ œžœ˜š žœžœžœžœž˜4Kš žœžœžœžœ žœ˜CKšžœ˜—Kšœ˜—Kšžœ žœžœ&˜:Kšžœ˜—K˜š‘œžœžœ žœ ˜3Kšž˜Kšœ7™7š žœžœ.žœžœž˜Ešžœžœžœžœ˜#KšœF˜Fš žœžœžœžœžœ˜)K˜Kšœžœžœ˜1Kšœ+˜+Kšœ˜K˜—šžœžœ žœž˜!šœžœ˜K˜$Kšœžœžœ˜-Kšœ˜K˜—šœžœ˜ K˜$Kšœžœžœ˜-Kšœ˜K˜—šœžœžœ˜K˜$Kšœžœžœ˜-Kšœ˜K˜—šœ˜K˜$Kšœžœžœ˜1Kšœ ˜8Kšœ˜Kšœ˜K˜—šœžœ˜K˜$Kšœžœžœ˜1Kšœ! ˜=Kšœ˜Kšœ˜K˜—šœžœžœžœ˜K˜$Kšœžœžœ˜1Kšœ ˜;š žœžœžœžœžœžœž˜4Kšœ˜Jšžœ˜—Kšœ˜K˜—Kšžœžœ˜—K˜—Kšžœ˜—Kšžœ˜—K˜š‘ œžœžœžœ ˜.Kšž˜Kšœ ˜ Kšœ ˜ Kšžœ"˜&K˜K˜Kšžœ˜K˜—š ‘œžœžœžœžœžœ˜BKšž˜š žœžœžœžœž˜;Kšœ˜Kšžœ˜—Kšžœ˜—K˜š‘œžœžœžœ˜8Kšž˜Kšœ˜š žœžœžœžœž˜4Kšœ˜Kšžœ˜—Kšžœ˜—K˜š‘ œžœžœžœ ˜*Kšž˜Kšœ *˜;šžœ:žœž˜Išœžœžœ˜!Kšœ˜K˜—šžœ˜Kšœ˜K˜——Kšžœ˜—K˜š‘ œžœžœžœ˜6Kšž˜šžœžœžœ˜$Kšœžœ.žœ˜:šžœžœžœ˜Kšœ˜Kšœ˜K˜—šžœ˜Kšœ ˜ Kšœ˜Kšœ#˜#Kšœ˜—Kšœ˜—šžœ˜Kšœ™Kšœ+˜+Kšœ˜šžœžœ˜Kšœ(˜(K˜—Kšœ˜Kšœ˜K˜—šžœ žœ˜Kšœ<žœžœ ˜M—Kšœ<žœ˜AKšžœ˜—K˜š ‘œžœžœžœžœ ˜/Kšž˜Kšžœžœžœžœ˜Kšžœ žœžœ˜,Kšœ˜Kšžœžœžœ%˜FKšžœ˜Kšœ#˜#Kšœ!˜!Kšžœ˜—K˜š‘ œ# œ˜KKšž˜Kšœžœ<˜CKš žœžœžœžœ &˜=šžœžœ˜Kšœ>˜>—Kšœ ˜ Kšœ ˜ Kšœ!˜!Kšžœ˜—K˜š‘œ ?œ˜qKšž˜Kšœžœ˜Kšžœ˜—K˜š‘œžœ˜Kšž˜šžœ˜"š‘œžœ žœžœ˜:KšœN™NKšœ'˜'Kšœ˜—Kšœ(˜(Kšž˜Kšœ˜—K˜š‘ œžœ˜Kšœ™Kšœ žœžœ˜KšœT˜TKš žœ žœžœ žœžœ˜)KšœE˜EKšœ˜Kšœ˜—K˜š ‘ œžœžœ žœžœ˜:Kš žœžœžœžœžœžœ˜\Kšžœžœ ˜Kšœ˜—K˜š‘œžœžœžœ˜(Kšžœ=˜CKšœ˜—K˜Kšœ˜Kšœ*˜*Kšœ˜Kšœ9 !˜ZKšœH˜HKšœ%˜%Kšœ˜Kšœ?˜?Kšœ ˜ Kšžœ˜—K˜š‘œžœ˜Kšž˜š‘œžœ žœ˜Kšœ˜Kšœ˜—Kšœ2˜2Kšœ#˜#KšœΖ˜ΖKšœl˜lKšœ?˜?Kšœ{˜{Kšœ6˜6Kšœu˜uKšœ1˜1Kšœ˜Kšœ+˜+KšœN˜NKšœ2˜2Kšžœ˜—K˜š‘œžœ žœ žœ žœžœžœ žœžœ žœžœ žœ˜ŒKšœ.™.Kšž˜K˜š‘œžœ žœ˜+Kšœ#™#Kšž˜Kšœ žœžœ˜Kš œ žœžœ žœžœžœ˜LKšœ™KšœD˜Dšžœ@žœ˜GKšžœžœ˜—Kšœ˜Kšžœžœ 7˜HKšžœ˜—K˜š ‘œžœ žœžœžœ žœ˜GKšž˜Kšœ#˜#Kšžœžœ(˜CKšœ'˜'Kšœžœ˜)Kšœ˜Kšžœ˜—K˜Kšœ žœžœ˜3Kšžœžœ,˜Fšžœžœžœ˜šžœžœž˜Kš œžœžœžœžœžœ˜=Kšœžœ ˜Kšžœ@˜G——šžœžœ˜Kšžœ žœ4˜EKšžœ˜#—Kšœžœ˜)šœ žœ>˜Išžœ ˜ Kšœ žœ˜Kšœ žœ˜Kšžœžœžœ˜!Kšœ˜—Kšœ˜—Kšžœ˜—K˜š‘œžœ žœžœ žœžœ žœžœžœžœžœ˜fKšž˜Kšœ5žœžœ˜Gšžœžœ žœ˜šžœžœžœž˜Kšœ˜Kšœ)˜)Kšœ˜Kšœ)˜)K˜2Kšœ ˜-Kšœ)˜)Kšœžœ˜ Kšœ5žœžœ˜GKšžœžœžœ˜Kšžœ˜—K˜—šžœžœžœ˜Kšœ<˜