CDOut.mesa
by Ch. Jacobi, December 12, 1983 2:02 pm
some code from Kim Rachmeler
Last Edited by: Jacobi, April 4, 1984 5:25:45 pm PST
DIRECTORY
CDIO,
CD,
CDApplications,
CDDirectory,
CDEvents,
CDExtras,
CDInline,
CDIOExtras,
CDOrient,
CDPrivate,
CDProperties,
CDValue,
FileNames,
FS,
IO,
Process,
Rope,
TerminalIO,
TokenIO;
CDOut: CEDAR PROGRAM --monitored by TokenIO
IMPORTS CD, CDApplications, CDIO, CDIOExtras, CDDirectory, CDEvents, CDExtras, CDInline, CDOrient, CDPrivate, CDProperties, CDValue, FileNames, FS, IO, Process, Rope, TerminalIO, TokenIO
EXPORTS CDIO
SHARES CDProperties =
BEGIN
xChipndaleFile: INT = 12121983;
xVersion: INT = 3;
-- global variables; are protected by the requirement of attaching Tokenio
designToWrite: CD.Design;
directoryNum: INT;
directoryMark: TokenIO.Mark;
outputKey: REFNEW[INT];
thisTime: REF;
lastTime: REF;
isQuiet: BOOL;
WriteRope: PROC [r: Rope.ROPE] =
BEGIN
IF ~isQuiet THEN TerminalIO.WriteRope[r]
END;
WriteLevel: PUBLIC PROC [l: CD.Level] =
BEGIN
TokenIO.WriteAtom[CD.LevelKey[l]];
END;
WriteProperties: PUBLIC PROC [props: CD.Properties] =
BEGIN
FOR l: CD.Properties ← props, l.rest WHILE l#NIL DO
pp: CDProperties.PropertyProcs;
IF NOT ISTYPE[l.first.key, ATOM] THEN LOOP;
pp ← 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[$Property];
TokenIO.WritePushFlag[NARROW[l.first.key, ATOM]];
TokenIO.WriteRope[r];
TokenIO.WritePopFlag[];
};
at: ATOM => {
TokenIO.WriteAtom[$Property];
TokenIO.WritePushFlag[NARROW[l.first.key, ATOM]];
TokenIO.WriteAtom[at];
TokenIO.WritePopFlag[];
}
ENDCASE => NULL;
ENDLOOP;
END;
WriteApplicationPtr: PUBLIC PROC [ap: CD.ApplicationPtr] =
BEGIN
loc: CD.DesignPosition;
IF xVersion<=2 THEN loc ← ap.location
ELSE loc ← CDInline.BaseOfRect[CDApplications.ARectI[ap]];
TokenIO.WriteInt[loc.x];
TokenIO.WriteInt[loc.y];
CDIO.WriteOrientation[ap.orientation];
WriteProperties[ap.properties];
WriteObject[ap.ob];
END;
WriteApplicationList: PUBLIC PROC [list: CD.ApplicationList] =
BEGIN
count: INT ← 0;
FOR l: CD.ApplicationList ← list, l.rest WHILE l#NIL DO
count ← count+1;
ENDLOOP;
TokenIO.WriteInt[count];
FOR l: CD.ApplicationList ← list, l.rest WHILE l#NIL DO
WriteApplicationPtr[l.first];
ENDLOOP;
END;
WriteObject: PUBLIC PROC [ob: CD.ObPtr] =
BEGIN
xx: REF = CDProperties.GetPropFromObject[from: ob, prop: thisTime];
IF xx#NIL AND ISTYPE[xx, REF INT] THEN {
WriteRope["."];
TokenIO.WriteInt[NARROW[xx, REF INT]^];
RETURN
};
WriteRope["x"];
DoWriteObject[ob]
END;
DoWriteObject: PROC [ob: CD.ObPtr] = --INLINE--
BEGIN
IF ob.p.internalWrite=NIL THEN {
TokenIO.WritePushFlag[$Unknown];
TokenIO.WritePopFlag[];
WriteRope["unknown object\n"];
RETURN
};
TokenIO.WritePushFlag[NARROW[ob.p.objectType, ATOM]];
ob.p.internalWrite[ob];
IF ob.p.hasChildren THEN {
TokenIO.WriteRope[CDDirectory.Name[ob]];
TokenIO.WriteRope[CDDirectory.Key[ob]];
};
WriteProperties[ob.properties];
CDProperties.PutPropOnObject[onto: ob, prop: lastTime, val: NIL];
TokenIO.WritePopFlag[];
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 WriteApplicationPtr[pl.first.mightReplace]
ELSE TokenIO.WriteAtom[$Nil];
WriteObject[pl.first.dummyCell.ob]
END;
EachChildren: CDDirectory.EnumerateObjectsProc --PROC [me: ObPtr, x: REF]-- =
BEGIN
xx: REF = CDProperties.GetPropFromObject[from: me, prop: thisTime];
IF xx#NIL THEN RETURN; -- it and its children are already out
IF me.p.hasChildren THEN
CDDirectory.EnumerateChildObjects[me: me, p: EachChildren, x: x];
directoryNum ← directoryNum+1;
TokenIO.WriteInt[directoryNum];
DoWriteObject[me];
CDProperties.PutPropOnObject[onto: me, prop: thisTime, val: NEW[INT𡤍irectoryNum]];
END;
EachDirectoryEntry: CDDirectory.EachEntryAction --[name: Rope.ROPE, ob: CD.ObPtr] RETURNS [quit: BOOL�LSE]-- =
BEGIN
EachChildren[ob, NIL];
END;
DoWriteDesign: PROC [] =
BEGIN
thisTime ← NEW[INT];
lastTime ← CDValue.Fetch[boundTo: designToWrite, key: outputKey, propagation: design];
IF lastTime=NIL THEN {lastTime←NEW[INT]};
CDValue.Store[boundTo: designToWrite, key: outputKey, value: thisTime];
directoryNum𡤀
IF Rope.Length[designToWrite.name]<=0
OR Rope.Fetch[designToWrite.name]='/
OR Rope.Fetch[designToWrite.name]='[ THEN TokenIO.WriteRope[NIL]
ELSE TokenIO.WriteRope[designToWrite.name];
directoryMark ← TokenIO.MarkAndWriteInt[directoryNum]; -- number of entries in directory
[] ← CDDirectory.Enumerate[design: designToWrite, action: EachDirectoryEntry];
WriteProperties[designToWrite.properties];
WritePushLevel[designToWrite.actual];
TokenIO.UpdateMark[mark: directoryMark, value: directoryNum];
TokenIO.WriteAtom[$EndOfDesign];
END;
DontOverWrite: ERROR = CODE;
WriteDesign: PUBLIC PROC [design: CD.Design, to: REFNIL, quiet: BOOL, emergency: BOOL] RETURNS [done: BOOLFALSE] =
--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
BEGIN
ENABLE DontOverWrite => GOTO NotOpened;
DoAttach: PROC [] RETURNS [done: BOOL] =
BEGIN
DoRealAttach: PROC [] RETURNS [done: BOOLFALSE] =
BEGIN
TokenIO.AttachWriter[binFile ! TokenIO.Error => GOTO AttachProblem];
done ← TRUE;
EXITS
AttachProblem => RETURN
END;
count: NAT ← 0;
done ← DoRealAttach[];
WHILE NOT done AND emergency DO
TokenIO.StopWriting[];
Process.Pause[Process.SecondsToTicks[1]];
TokenIO.StopWriting[];
Process.Pause[Process.SecondsToTicks[2]];
count ← count+1;
IO.Reset[binFile];
TerminalIO.WriteRope["TRIES TO BREAK THE LOCK\n"];
TokenIO.ReleaseWriter[]; -- XXXXXXX DANGEROUS
Process.Pause[Process.SecondsToTicks[1]];
done ← DoRealAttach[];
IF NOT done AND count>5 THEN {
count𡤀
SIGNAL CDPrivate.DebugCall[what: "cannot attach"];
};
ENDLOOP
END;
InName: PROC [wDir: Rope.ROPENIL] RETURNS [name: Rope.ROPE] =
BEGIN
CheckExistance: PROC [name: Rope.ROPE] =
--Errors DontOverWrite if necessary
BEGIN
temfile: IO.STREAMFS.StreamOpen[name ! FS.Error => IF error.group#bug THEN GOTO NotFound];
--file exists already
TerminalIO.WriteRope["File "];
TerminalIO.WriteRope[name];
TerminalIO.WriteRope[" exists already; "];
IF ~TerminalIO.UserSaysYes[label: "overwrite? ", text: "overwrite?", default: FALSE] THEN ERROR DontOverWrite;
TerminalIO.WriteRope[" yes\n"];
EXITS
NotFound => { --this is the "normal" case of an not yet existing file
NULL
}
END;
IF emergency THEN name ← "///temp/chipndale/emergency/emergency.dale"
ELSE {
TerminalIO.WriteRope["output file name"];
IF ~Rope.IsEmpty[wDir] THEN {
TerminalIO.WriteRope[" ("];
TerminalIO.WriteRope[wDir];
TerminalIO.WriteRope[")"];
};
name ← TerminalIO.RequestRope[" > "];
name ← CDExtras.AppendExt[name, "dale"];
IF ~Rope.IsEmpty[wDir] THEN name ← FS.ExpandName[name, wDir].fullFName;
CheckExistance[name];
}
END;
Help: PROC [] =
BEGIN
WriteRope[" first, try it again; if it still does not work,\n"];
WriteRope[" try SHIFT-SHIFT-SWAT\n"];
WriteRope[" or hack ""← CDEmergencyHandling.SaveAll[]"" to an commandtool\n"];
END;
--WriteDesign
iMadeTheOpen: BOOL�LSE;
binFile: IO.STREAM;
sealMark: TokenIO.Mark;
name, fileName: Rope.ROPE;
wDir: Rope.ROPE ← CDIOExtras.GetDesignsWorkingDirectory[design];
IF Rope.IsEmpty[wDir] THEN wDir ← FileNames.CurrentWorkingDirectory[];
isQuiet ← quiet;
designToWrite ← design;
IF to#NIL AND ISTYPE[to, IO.STREAM] THEN {
binFile ← NARROW[to, IO.STREAM]
}
ELSE {
IF to=NIL THEN {
name ← InName[wDir];
}
ELSE IF ISTYPE[to, Rope.ROPE] THEN {
name ← NARROW[to, Rope.ROPE];
IF Rope.IsEmpty[name] THEN name ← InName[wDir];
}
ELSE {
TerminalIO.WriteRope["WriteDesign does not support type of 'to' parameter\n"];
GOTO NotOpened;
};
fileName ← FS.ExpandName[CDExtras.AppendExt[name, "dale"], wDir].fullFName;
binFile ← FS.StreamOpen[fileName, $create !
FS.Error => IF error.group#bug THEN {
binFile←NIL;
GOTO NotOpened
}
];
iMadeTheOpen ← TRUE;
};
IF NOT DoAttach[] THEN {
WriteRope["not attached, locks are hold\n"];
Help[];
RETURN
};
TokenIO.WriteInt[xChipndaleFile];
TokenIO.WriteInt[xVersion];
sealMark ← TokenIO.MarkAndWriteInt[0]; -- this is a bad seal
TokenIO.WriteAtom[designToWrite.technology.key];
TokenIO.WriteRope[designToWrite.technology.name];
IF CDEvents.ProcessEvent[ev: writeEvent, design: designToWrite, x: NIL, listenToDont: TRUE].dont THEN {
WriteRope["write not done\n"];
TokenIO.ReleaseWriter[];
IO.Close[binFile];
RETURN
};
DoWriteDesign[];
TokenIO.UpdateMark[sealMark, -1]; -- validate seal
TokenIO.ReleaseWriter[];
IF iMadeTheOpen THEN IO.Close[binFile];
TerminalIO.WriteRope["design "];
TerminalIO.WriteRope[designToWrite.name];
TerminalIO.WriteRope[" written on file "];
IF iMadeTheOpen THEN TerminalIO.WriteRope[fileName];
TerminalIO.WriteLn[];
done ← TRUE;
EXITS
NotOpened => {
WriteRope["File not created\n"];
};
END;
-- Module initialization
writeEvent: CDEvents.EventRegistration = CDEvents.RegisterEventType[$WriteTechnologyPrivate];
END.