-- DFDeleteImpl.Mesa, last edit February 9, 1983 11:57 am
-- Pilot 6.0/ Mesa 7.0
DIRECTORY
CWF: TYPE USING [FWF0, FWF1, SetWriteProcedure, WF0, WF1, WFCR],
DFSubr: TYPE USING [AllocateDFSeq, DF, DFSeq, FlattenDF, FreeDFSeq, ReadInDir,
SortByCap, SortByFileName],
LongString: TYPE USING [AppendString],
IO: TYPE USING[Handle, PutChar, PutF, rope, UserAbort],
Rope: TYPE USING[Fetch, Length, ROPE, Text],
RopeInline: TYPE USING[InlineFlatten],
STPSubr: TYPE USING [StopSTP],
Stream: TYPE USING [Delete, Handle, PutChar],
Subr: TYPE USING [AbortMyself, Any, CheckForModify, debugflg, errorflg,
GetCreateDate, MakeTTYProcs, NewStream, PackedTime, PrintGreeting,
strcpy, SubrStop, TTYProcs, Write],
Time: TYPE USING [Current],
UECP: TYPE USING[Argv, Parse],
UserExec: TYPE USING[AcquireResource, AskUser, CommandProc, GetStreams,
RegisterCommand, ReleaseResource];
DFDeleteImpl: PROGRAM
IMPORTS CWF, DFSubr, IO, LongString, Rope, RopeInline,
STPSubr, Stream, Subr, Time, UECP, UserExec = {
-- MDS usage!!
stdout: IO.Handle;
-- end of mds
-- max number of files in all DF file we want to ignore
MAXDELETEFILE: CARDINAL = 800;
Main: UserExec.CommandProc = TRUSTED {
ENABLE UNWIND => [] ← UserExec.ReleaseResource[$DFDelete];
h: Subr.TTYProcs;
in, out: IO.Handle;
[in, out] ← UserExec.GetStreams[exec];
[] ← UserExec.AcquireResource[$DFDelete, "DFDelete", exec];
h ← Subr.MakeTTYProcs[in, out, exec, MyConfirm];
DFDeleteUsingProcs[h, event.commandLine];
[] ← UserExec.ReleaseResource[$DFDelete];
};
-- this is the procedure called by the Simple Executive
DFDeleteUsingProcs: PROC[h: Subr.TTYProcs, commandLine: Rope.ROPE] = {
dfseq: DFSubr.DFSeq ← NIL;
tok: Rope.ROPE;
starttime: Subr.PackedTime;
alsoDeleteReadOnly: BOOL ← FALSE;
argv: UECP.Argv ← UECP.Parse[commandLine];
Cleanup: PROC = {
DFSubr.FreeDFSeq[@dfseq];
STPSubr.StopSTP[];
Subr.SubrStop[];
};
stdout ← h.out;
[] ← CWF.SetWriteProcedure[MyPutChar];
starttime ← Time.Current[];
Subr.errorflg ← Subr.debugflg ← FALSE;
Subr.PrintGreeting["DFDelete"L];
dfseq ← DFSubr.AllocateDFSeq[maxEntries: MAXDELETEFILE, zoneType: shared];
{
ENABLE {
Subr.AbortMyself => {
CWF.WF0["DFDelete Aborted.\n"L];
GOTO leave;
};
UNWIND => Cleanup[];
};
IF h.in.UserAbort[] THEN SIGNAL Subr.AbortMyself;
FOR p: CARDINAL IN [1 .. argv.argc) DO
tok ← argv[p];
IF tok.Fetch[0] = '/ THEN {
IF tok.Fetch[1] = 'r THEN
alsoDeleteReadOnly ← TRUE
ELSE h.out.PutF["Unknown switch '%s'.\n", IO.rope[tok]];
}
ELSE {
str: STRING ← [100];
flat: Rope.Text ← RopeInline.InlineFlatten[tok];
Subr.strcpy[str, LOOPHOLE[flat]];
IF NOT Subr.Any[str, '.] THEN
LongString.AppendString[str, ".DF"L];
DFSubr.FlattenDF[dfseq: dfseq, dffilename: str, h: h];
};
ENDLOOP;
IF tok.Length[] = 0 THEN GOTO usage;
STPSubr.StopSTP[];
IF dfseq.size = 0 THEN GOTO leave;
DFSubr.ReadInDir[dfseq];
DFSubr.SortByCap[dfseq, 0, dfseq.size-1];
FOR i: CARDINAL IN [0 .. dfseq.size) DO
dfseq[i].need ← NOT dfseq[i].readonly OR alsoDeleteReadOnly;
ENDLOOP;
-- only ReadWrite files are marked need = TRUE
CWF.WF0["Reading create dates on local disk ... "L];
CheckCreateDates[dfseq];
CWF.WF0["Done.\n"L];
DFSubr.SortByFileName[dfseq, 0, dfseq.size-1, TRUE];
GenerateDelete[dfseq, alsoDeleteReadOnly, h];
EXITS
usage => CWF.WF0["Usage: DFDelete dffile(s).\n"L];
leave => NULL;
};
starttime ← Time.Current[] - starttime;
CWF.WF1["\nTotal elapsed time for DFDelete %lr."L,@starttime];
IF Subr.errorflg THEN CWF.WF0["\tErrors logged.\n"L];
CWF.WFCR[];
Cleanup[];
};
CheckCreateDates: PROC[dfseq: DFSubr.DFSeq] = {
df: DFSubr.DF;
FOR i: CARDINAL IN [0 .. dfseq.size) DO
df ← @dfseq[i];
IF df.need AND df.presentonlocaldisk
AND df.createtime ~= 0 THEN {
IF Subr.GetCreateDate[df.cap] ~= df.createtime THEN
df.need ← FALSE;
};
ENDLOOP;
};
GenerateDelete: PROC[dfseq: DFSubr.DFSeq, alsoDeleteReadOnly: BOOL, h: Subr.TTYProcs] = {
linesh: Stream.Handle ← NIL;
df: DFSubr.DF;
WP: PROC[ch: CHAR] = {
h.out.PutChar[ch];
Stream.PutChar[linesh, ch];
};
FOR i: CARDINAL IN [0 .. dfseq.size) DO
df ← @dfseq[i];
IF df.need AND df.presentonlocaldisk
AND df.createtime ~= 0 THEN {
IF linesh = NIL THEN {
CWF.WF1["(You should delete these files since %s\n"L,
IF alsoDeleteReadOnly THEN ""L ELSE "they appeared non-ReadOnly and "L];
CWF.WF0["their createdates are equal to those in the DF file(s).)\n"L];
IF NOT Subr.CheckForModify["Line.CM"L, h] THEN SIGNAL Subr.AbortMyself;
CWF.WF0["Execute: "L];
linesh ← Subr.NewStream["Line.CM"L, Subr.Write];
CWF.FWF0[WP, "Delete "L];
};
CWF.FWF1[WP, "%s "L, dfseq[i].shortname];
};
ENDLOOP;
IF linesh ~= NIL THEN {
Stream.Delete[linesh];
CWF.WF0["\n\n(Delete command also written on 'Line.CM'.)\n"L];
};
};
MyConfirm: PROC[in, out: IO.Handle, data: REF ANY, msg: Rope.ROPE, dch: CHAR]
RETURNS[CHAR] = {
value: ATOM;
value ← UserExec.AskUser[msg: msg, exec: NARROW[data],
keyList: LIST[$Yes, $No, $All, $Local, $Quit]]; -- order is important
SELECT value FROM
$All => RETURN['a];
$Local => RETURN['l];
$No => RETURN['n];
$Quit => RETURN['q];
$Yes => RETURN['y];
ENDCASE => ERROR;
};
MyPutChar: PROC[ch: CHAR] = {
stdout.PutChar[ch];
};
UserExec.RegisterCommand["DFDelete.~", Main];
}.