<> <> <> <> DIRECTORY Ascii, CD, CDDirectory, CDDirectoryOps, CDMarks, CDSequencer USING [MarkChanged], CDSimpleOps, TerminalIO, Rope; CDDirectoryOpsImpl: CEDAR PROGRAM IMPORTS Ascii, CDDirectory, CDMarks, CDSequencer, CDSimpleOps, Rope, TerminalIO EXPORTS CDDirectoryOps = BEGIN MarkUnMarkedFromTop: PROC [design: CD.Design, mark: CDMarks.MarkRange] = { FOR l: LIST OF CD.PushRec _ design.actual, l.rest WHILE l#NIL DO IF l.first.mightReplace#NIL THEN { CDMarks.MarkUnMarkedInclusiveChildren[design, l.first.mightReplace.ob, mark]; }; CDMarks.MarkUnMarkedInclusiveChildren[design, l.first.dummyCell.ob, mark]; ENDLOOP; }; RemoveIfUnused: PUBLIC PROC [design: CD.Design, ob: CD.Object] RETURNS [done: BOOL _ FALSE, msg: Rope.ROPE _ NIL] = { usedBy: Rope.ROPE_NIL; name: Rope.ROPE; toDeleteOb: CD.Object; found: BOOL; DoitWithMark: PROC [mark: CDMarks.MarkRange] = { EachEntryCheck: CDDirectory.EachEntryAction = { -- PROC [name: Rope.ROPE, ob: CD.Object] RETURNS [quit: BOOL_FALSE] IF ob.marked#mark AND ob#toDeleteOb THEN { <<--an occurence of cellOb should not be marked>> CDMarks.MarkUnMarkedInclusiveChildren[design, ob, mark]; IF toDeleteOb.marked=mark THEN { usedBy _ name; quit _ TRUE } }; }; MarkUnMarkedFromTop[design, mark]; IF toDeleteOb.marked=mark THEN { usedBy _ "top level"; found _ TRUE } ELSE found _ CDDirectory.Enumerate[design, EachEntryCheck].quit; }; name _ CDDirectory.Name[ob]; [found, toDeleteOb] _ CDDirectory.Fetch[design, name]; IF ~found THEN RETURN [done _ FALSE, msg _ "object was not in directory"]; IF toDeleteOb#ob THEN RETURN [done _ FALSE, msg _ "naming problem"]; <<-- mark all entries (excluding toDeleteOb), and all their children>> <<-- test then if toDeleteOb is marked; if it is, it is a child and used >> CDMarks.DoWithMark[design, DoitWithMark]; IF found THEN RETURN [done _ FALSE, msg _ Rope.Cat["is used by ", usedBy, " (and maybe others)"]]; CDSimpleOps.FlushDeletedCache[design]; IF ~CDDirectory.Remove[design, name, toDeleteOb] THEN RETURN [done _ FALSE, msg _ "error in delete routine"]; RETURN [done _ TRUE, msg _ NIL]; }; CompletelyDestroy: PROC [design: CD.Design, list: LIST OF CD.Object] = BEGIN tem: LIST OF CD.Object; IF list#NIL THEN { CDSimpleOps.FlushDeletedCache[design]; WHILE list#NIL DO IF list.first.class.inDirectory THEN <> list.first^.properties _ NIL; list.first _ NIL; tem _ list; list _ list.rest; tem.rest _ NIL; ENDLOOP } END; PruneDirectory: PUBLIC PROC [design: CD.Design, autoOnly: BOOL _ FALSE, askFirst: BOOL_FALSE] = { Doit: PROC [mark: CDMarks.MarkRange] = { RemoveIfNotMarked: PROC [name: Rope.ROPE, ob: CD.Object] RETURNS [quit: BOOL_FALSE] = { IF ob.marked#mark THEN { d: BOOL _ CDDirectory.Remove[design: design, name: name, expectObject: ob]; IF d THEN removed _ CONS[ob, removed]; } }; ListNotMarked: PROC [name: Rope.ROPE, ob: CD.Object] RETURNS [quit: BOOL_FALSE] = { IF ob.marked#mark THEN { TerminalIO.PutF1[" - %g\n", [rope[name]]]; cnt _ cnt + 1 } }; AlsoMarkNamedObjects: PROC[name: Rope.ROPE, ob: CD.Object] RETURNS [quit: BOOL_FALSE] = { IF ob.marked#mark THEN { ch: CHAR = IF Rope.Length[name]<=0 THEN 'A ELSE Rope.Fetch[name]; IF Ascii.Letter[ch] OR Ascii.Digit[ch] THEN { CDMarks.MarkUnMarkedInclusiveChildren[design, ob, mark]; } }; }; removed: LIST OF CD.Object _ NIL; cnt: NAT _ 0; MarkUnMarkedFromTop[design, mark]; IF autoOnly THEN { [] _ CDDirectory.Enumerate[design: design, action: AlsoMarkNamedObjects]; }; IF askFirst THEN { TerminalIO.PutRope[" List of objects not used:\n"]; [] _ CDDirectory.Enumerate[design: design, action: ListNotMarked]; TerminalIO.PutF1[" %g objects not used in design\n", [integer[cnt]]]; }; IF cnt>0 THEN { IF askFirst AND ~TerminalIO.Confirm["delete listed objects"] THEN { removed _ NIL; TerminalIO.PutRope[" not done\n"]; RETURN }; CDSequencer.MarkChanged[design]; [] _ CDDirectory.Enumerate[design: design, action: RemoveIfNotMarked]; CompletelyDestroy[design, removed]; IF askFirst THEN TerminalIO.PutRope[" deleted\n"]; }; removed _ NIL; }; CDSimpleOps.FlushDeletedCache[design]; CDMarks.DoWithMark[design, Doit ! CDMarks.MarkOccupied => GOTO requestProblem]; EXITS requestProblem => TerminalIO.PutRope["**Mark problem\n"]; }; RenameNRemove: PUBLIC PROC [design: CD.Design, ob: CD.Object, name: Rope.ROPE] = { ob1: CD.Object; IF ~ob.class.inDirectory THEN ERROR; ob1 _ CDDirectory.Fetch[design, name].object; IF ob1#NIL THEN { IF ob1=ob THEN RETURN; [] _ CDDirectory.Rename[design: design, object: ob1, newName: Rope.Cat[name, "@old"], fiddleName: TRUE]; }; [] _ CDDirectory.Rename[design: design, object: ob, newName: name, fiddleName: TRUE]; IF ob1#NIL THEN [] _ RemoveIfUnused[design: design, ob: ob1]; }; END.