-- DFDiffImpl.Mesa, last edit February 9, 1983 12:34 pm
-- Pilot 6.0/ Mesa 7.0
DIRECTORY
CWF: TYPE USING [SetWriteProcedure, WF0, WF1, WF2, WFCR],
DFSubr: TYPE USING [AllocateDFSeq, CompareDFs, DFSeq, FreeDFSeq,
ParseStream, SortByFileName],
IO: TYPE USING[Handle, PutChar, UserAbort],
Rope: TYPE USING[ROPE, Text],
RopeInline: TYPE USING[InlineFlatten],
UnsafeSTP: TYPE USING [Error, Handle],
STPSubr: TYPE USING [GeneralOpen],
Stream: TYPE USING [Delete, Handle],
String: TYPE USING [AppendString],
Subr: TYPE USING [AbortMyself, Any, errorflg, FileError, MakeTTYProcs, PrintGreeting,
strcpy, SubrInit, SubrStop, TTYProcs],
Time: TYPE USING [Current],
UECP: TYPE USING[Argv, Parse],
UserExec: TYPE USING[AcquireResource, AskUser, CommandProc, ExecHandle, GetStreams,
RegisterCommand, ReleaseResource];
DFDiffImpl: PROGRAM
IMPORTS CWF, DFSubr, IO, RopeInline, STP: UnsafeSTP, STPSubr, Stream, String,
Subr, Time, UECP, UserExec = {
-- MDS usage!!
stdout: IO.Handle;
-- end of mds
MAXFILES: CARDINAL = 900;
Main: UserExec.CommandProc = TRUSTED {
ENABLE UNWIND => [] ← UserExec.ReleaseResource[$DFDiff];
h: Subr.TTYProcs;
in, out: IO.Handle;
[in, out] ← UserExec.GetStreams[exec];
[] ← UserExec.AcquireResource[$DFDiff, "DFDiff", exec];
h ← Subr.MakeTTYProcs[in, out, exec, MyConfirm];
DFDiffUsingProcs[h, event.commandLine];
[] ← UserExec.ReleaseResource[$DFDiff];
};
DFDiffUsingProcs: PROC[h: Subr.TTYProcs, commandLine: Rope.ROPE] = {
sold: STRING ← [100];
snew: STRING ← [100];
shold, shnew: Stream.Handle;
dfseqold, dfseqnew: DFSubr.DFSeq ← NIL;
starttime: LONG CARDINAL;
argv: UECP.Argv ← UECP.Parse[commandLine];
flat: Rope.Text;
Cleanup: PROC = {
DFSubr.FreeDFSeq[@dfseqold];
DFSubr.FreeDFSeq[@dfseqnew];
Subr.SubrStop[];
};
{
ENABLE {
UNWIND => Cleanup[];
Subr.AbortMyself => {
CWF.WF0["\nDFDiff Aborted.\n"L];
GOTO leave;
};
STP.Error => {
CWF.WF0["FTP Error. "L];
IF error ~= NIL THEN CWF.WF1["message: %s\n"L,error];
Subr.errorflg ← TRUE;
GOTO leave;
};
};
stdout ← h.out;
[] ← CWF.SetWriteProcedure[MyPutChar];
starttime ← Time.Current[];
Subr.SubrInit[256];
Subr.PrintGreeting["DFDiff"L];
dfseqold ← DFSubr.AllocateDFSeq[maxEntries: MAXFILES, zoneType: shared];
dfseqnew ← DFSubr.AllocateDFSeq[maxEntries: MAXFILES, zoneType: shared];
IF argv.argc < 3 THEN GOTO usage;
flat ← RopeInline.InlineFlatten[argv[2]];
Subr.strcpy[sold, LOOPHOLE[flat]];
flat ← RopeInline.InlineFlatten[argv[3]];
Subr.strcpy[snew, LOOPHOLE[flat]];
IF NOT Subr.Any[sold, '.] THEN String.AppendString[sold, ".df"L];
IF NOT Subr.Any[snew, '.] THEN String.AppendString[snew, ".df"L];
CWF.WF1["Opening %s"L, sold];
[shold] ← STPSubr.GeneralOpen[sold, h
! Subr.FileError => GOTO err1];
CWF.WF1["Opening %s"L, snew];
[shnew] ← STPSubr.GeneralOpen[snew, h
! Subr.FileError => GOTO err2];
IF h.in.UserAbort[] THEN SIGNAL Subr.AbortMyself;
DFSubr.ParseStream[shold, dfseqold, sold, NIL, TRUE, FALSE, FALSE, h];
IF h.in.UserAbort[] THEN SIGNAL Subr.AbortMyself;
DFSubr.ParseStream[shnew, dfseqnew, snew, NIL, TRUE, FALSE, FALSE, h];
Stream.Delete[shold];
Stream.Delete[shnew];
IF h.in.UserAbort[] THEN SIGNAL Subr.AbortMyself;
DFSubr.SortByFileName[dfseqold, 0, dfseqold.size-1, TRUE];
IF h.in.UserAbort[] THEN SIGNAL Subr.AbortMyself;
DFSubr.SortByFileName[dfseqnew, 0, dfseqnew.size-1, TRUE];
CWF.WF2["Old file: %s, new file: %s\n"L, sold, snew];
IF h.in.UserAbort[] THEN SIGNAL Subr.AbortMyself;
CompareDFSeqs[dfseqold, dfseqnew];
IF h.in.UserAbort[] THEN SIGNAL Subr.AbortMyself;
DFSubr.FreeDFSeq[@dfseqold];
DFSubr.FreeDFSeq[@dfseqnew];
EXITS
err1 => CWF.WF1["Error - can't open %s.\n"L, sold];
err2 => CWF.WF1["Error - can't open %s.\n"L, snew];
usage => CWF.WF0["Error - usage: DFDiff old-df-file new-df-file\n"L];
leave => NULL;
};
starttime ← Time.Current[] - starttime;
CWF.WF1["\nTotal elapsed time for DFDiff %lr."L,@starttime];
IF Subr.errorflg THEN CWF.WF0["\tErrors logged.\n"L];
CWF.WFCR[];
Cleanup[];
};
Choice: TYPE = {added, deleted, different};
CompareDFSeqs: PROC[dfseqold, dfseqnew: DFSubr.DFSeq] = {
res: INTEGER;
iold, inew: CARDINAL;
FOR choice: Choice IN Choice DO
SELECT choice FROM
added => CWF.WF0["\nAdded:\n"L];
deleted => CWF.WF0["\nDeleted:\n"L];
different => CWF.WF0["\nDifferent:\n"L];
ENDCASE => ERROR;
iold ← inew ← 0;
WHILE iold < dfseqold.size OR inew < dfseqnew.size DO
IF iold >= dfseqold.size THEN res ← 1
ELSE IF inew >= dfseqnew.size THEN res ← -1
ELSE res ← DFSubr.CompareDFs[@dfseqold[iold], @dfseqnew[inew], TRUE];
IF res < 0 THEN {
IF choice=deleted THEN {
CWF.WF1[" %-40s"L, dfseqold[iold].shortname];
IF dfseqold[iold].createtime ~= 0 THEN
CWF.WF1[" %lt"L,
@dfseqold[iold].createtime];
CWF.WFCR[];
};
iold ← iold + 1;
}
ELSE IF res > 0 THEN {
IF choice = added THEN {
CWF.WF1[" %-40s"L, dfseqnew[inew].shortname];
IF dfseqnew[inew].createtime ~= 0 THEN
CWF.WF1[" %lt"L,
@dfseqnew[inew].createtime];
CWF.WFCR[];
};
inew ← inew + 1;
}
ELSE {-- they are equivalent names
IF dfseqold[iold].createtime ~=
dfseqnew[inew].createtime AND choice = different THEN {
CWF.WF1[" %-34s"L, dfseqnew[inew].shortname];
IF dfseqnew[inew].createtime ~= 0 THEN
CWF.WF1[" new = %lt"L,
@dfseqnew[inew].createtime];
CWF.WFCR[];
};
inew ← inew + 1;
iold ← iold + 1;
};
ENDLOOP;
ENDLOOP;
};
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]]; -- order is important
SELECT value FROM
$No => RETURN['n];
$Yes => RETURN['y];
ENDCASE => ERROR;
};
MyPutChar: PROC[ch: CHAR] = {
stdout.PutChar[ch];
};
-- start code
UserExec.RegisterCommand["DFDiff.~", Main];
}.