MODULE DelOlder;
IMPORT Diagnostics;
IMPORT BigSets;
IMPORT Drectory;
IMPORT EnvironUtils;
IMPORT ErrorManager;
IMPORT HandleIO;
IMPORT KbdInput;
IMPORT M2Strings;
IMPORT PosUtils;
IMPORT StrConv;
IMPORT StrEdit;
IMPORT StringIO;
VAR
exiting, BatchMode : BOOLEAN;
PrimaryFileSpec, SecondaryFileSpec, PrimaryDirName, SecondaryDirName,
PrimaryFileSpecPart, SecondaryFileSpecPart: ARRAY [0..79] OF CHAR;
PrimaryDrive, SecondaryDrive: CHAR;
PROCEDURE Ask( question: ARRAY OF CHAR; VAR answer: ARRAY OF CHAR );
VAR
tmpstr: ARRAY [0..79] OF CHAR;
BEGIN
StringIO.WriteStr( StringIO.outp, question );
IF answer[0] # 0C THEN
(* There is a default. *)
StringIO.WriteStr( StringIO.outp, ' <' );
StringIO.WriteStr( StringIO.outp, answer );
StringIO.WriteStr( StringIO.outp, '> ' );
END;
StringIO.ReadStr( StringIO.inp, tmpstr );
IF tmpstr[0] = 0C THEN
RETURN;
END;
IF (( CAP(tmpstr[0]) = 'Q' ) OR (tmpstr[0] = CHR(27)))
AND (M2Strings.Length(tmpstr) = 1) THEN
ErrorManager.StraightToDOS('');
END;
M2Strings.Assign( tmpstr, answer );
END Ask;
PROCEDURE FirstIsOlder( VAR First, Second: Drectory.FileInfoRec ): BOOLEAN;
BEGIN
IF First.year < Second.year THEN
RETURN TRUE;
ELSIF First.year > Second.year THEN
RETURN FALSE;
END;
IF First.month < Second.month THEN
RETURN TRUE;
ELSIF First.month > Second.month THEN
RETURN FALSE;
END;
IF First.day < Second.day THEN
RETURN TRUE;
ELSIF First.day > Second.day THEN
RETURN FALSE;
END;
IF First.hour < Second.hour THEN
RETURN TRUE;
ELSIF First.hour > Second.hour THEN
RETURN FALSE;
END;
IF First.minute < Second.minute THEN
RETURN TRUE;
ELSIF First.minute > Second.minute THEN
RETURN FALSE;
END;
IF First.second < Second.second THEN
RETURN TRUE;
ELSE
RETURN FALSE;
END;
END FirstIsOlder;
PROCEDURE SameTimeStamp( VAR First, Second: Drectory.FileInfoRec ): BOOLEAN;
BEGIN
IF (First.year = Second.year) AND
(First.month = Second.month) AND
(First.day = Second.day) AND
(First.hour = Second.hour) AND
(First.minute = Second.minute) AND
(First.second = Second.second) THEN
RETURN TRUE;
ELSE
RETURN FALSE;
END;
END SameTimeStamp;
PROCEDURE MakeInfoStr( FileInfo: Drectory.FileInfoRec; VAR TheStr: ARRAY
OF CHAR );
VAR
dumstr: ARRAY [0..79] OF CHAR;
BEGIN
StrEdit.AssignStr( FileInfo.name, TheStr );
WHILE M2Strings.Length(TheStr) < 12 DO
StrEdit.Append( TheStr, ' ' );
END;
IF Drectory.SubdirectoryFile IN FileInfo.attribute THEN
StrEdit.Append( TheStr, '
' );
ELSE
StrConv.LongIntegerToStr( FileInfo.size, 8, dumstr );
StrEdit.Append( TheStr, dumstr );
END;
StrConv.DateToStr( FileInfo.month, FileInfo.day, FileInfo.year,
dumstr );
StrEdit.Append( TheStr, ' ' );
StrEdit.Append( TheStr, dumstr );
StrConv.TimeToStr( FileInfo.hour, FileInfo.minute, FileInfo.second,
FileInfo.second, dumstr );
M2Strings.Delete( dumstr, M2Strings.Length(dumstr) - 7, 6 );
StrEdit.Append( TheStr, ' ' );
StrEdit.Append( TheStr, dumstr );
END MakeInfoStr;
PROCEDURE yes() : BOOLEAN;
VAR
choice : CARDINAL;
BEGIN
(*yes*)
IF BatchMode THEN
StringIO.WriteStr( StringIO.outp, 'yes');
RETURN TRUE;
END;
choice := KbdInput.KeyHit( KbdInput.YorN );
IF KbdInput.CAPkey(choice) = ORD('Y') THEN
StringIO.WriteStr( StringIO.outp, 'yes');
RETURN TRUE;
ELSE
StringIO.WriteStr( StringIO.outp, 'no');
IF KbdInput.CAPkey(choice) = ORD('Q') THEN
exiting := TRUE;
END;
RETURN FALSE;
END;
END yes;
PROCEDURE Processor1(info : Drectory.FileInfoRec) : BOOLEAN;
VAR
TmpPrimaryFile, TmpSecondaryFile, PrimaryInfoStr, SecondaryInfoStr:
ARRAY [0..79] OF CHAR;
DirHandle: CARDINAL;
tmpinfo: Drectory.FileInfoRec;
BEGIN
IF PosUtils.Equal( '..', info.name ) OR
PosUtils.Equal( '.', info.name ) THEN
RETURN TRUE;
END;
M2Strings.Concat( PrimaryDirName, info.name, TmpPrimaryFile );
M2Strings.Concat( SecondaryDirName, info.name, TmpSecondaryFile );
M2Strings.Insert( ':', TmpPrimaryFile, 0 );
M2Strings.Insert( PrimaryDrive, TmpPrimaryFile, 0 );
M2Strings.Insert( ':', TmpSecondaryFile, 0 );
M2Strings.Insert( SecondaryDrive, TmpSecondaryFile, 0 );
IF HandleIO.FileExists( TmpSecondaryFile ) THEN
MakeInfoStr( info, PrimaryInfoStr );
DirHandle := 0FFFFH;
StringIO.PrintMessage( Drectory.FindFirstFile( TmpSecondaryFile,
DirHandle, tmpinfo ) );
MakeInfoStr( tmpinfo, SecondaryInfoStr );
IF ((M2Strings.CompareStr( PrimaryInfoStr, SecondaryInfoStr ) = 0) OR
FirstIsOlder( tmpinfo, info ) OR SameTimeStamp( tmpinfo, info) ) AND
(NOT PosUtils.Present('', PrimaryInfoStr) ) THEN
M2Strings.Insert( PrimaryDirName, PrimaryInfoStr, 0 );
M2Strings.Insert( ':', PrimaryInfoStr, 0 );
M2Strings.Insert( PrimaryDrive, PrimaryInfoStr, 0 );
M2Strings.Insert( SecondaryDirName, SecondaryInfoStr, 0 );
M2Strings.Insert( ':', SecondaryInfoStr, 0 );
M2Strings.Insert( SecondaryDrive, SecondaryInfoStr, 0 );
StrEdit.Append( SecondaryInfoStr, ' ' );
StringIO.WriteEol( StringIO.outp, '' );
StringIO.WriteStr( StringIO.outp, 'Keeping ' );
StringIO.WriteEol( StringIO.outp, PrimaryInfoStr );
StringIO.WriteStr( StringIO.outp, 'Delete? ' );
StringIO.WriteStr( StringIO.outp, SecondaryInfoStr );
IF yes() THEN
StringIO.PrintMessage( Drectory.DeleteFile( TmpSecondaryFile ) );
END;
IF exiting THEN
RETURN FALSE;
END;
END;
END;
RETURN TRUE;
END Processor1;
BEGIN
IF NOT EnvironUtils.ParsedParam( 1, PrimaryFileSpec ) THEN
StringIO.WriteEol( StringIO.outp, '' );
StringIO.WriteEol( StringIO.outp,
'DelOlder expects two wildcard specifications of files in different' );
StringIO.WriteEol( StringIO.outp,
'directories. It deletes all files in the second directory with ' );
StringIO.WriteEol( StringIO.outp,
'names that match those of files in the first directory if the ' );
StringIO.WriteEol( StringIO.outp,
'secondary files are identical to or older than the primary files. A ' );
StringIO.WriteEol( StringIO.outp,
'trailing /p makes it pause for confirmation before deleting each file.' );
StringIO.WriteEol( StringIO.outp, '' );
PrimaryFileSpec := '';
Ask( 'Primary file specification? (These files will survive.) ',
PrimaryFileSpec );
END;
IF NOT EnvironUtils.ParsedParam( 2, SecondaryFileSpec ) THEN
SecondaryFileSpec := '';
Ask( 'Secondary file specification? (These files may be deleted.) ',
SecondaryFileSpec );
END;
StrEdit.CrunchBlanks( PrimaryFileSpec );
StrEdit.CrunchBlanks( SecondaryFileSpec );
IF SecondaryFileSpec[M2Strings.Length(SecondaryFileSpec)-2]='/' THEN
IF CAP( SecondaryFileSpec[M2Strings.Length(SecondaryFileSpec)-1] ) = 'P' THEN
M2Strings.Delete(SecondaryFileSpec, M2Strings.Length(SecondaryFileSpec)-2, 2);
StrEdit.CutTrailingChars( ' ', SecondaryFileSpec);
BatchMode := FALSE;
ELSE
BatchMode := TRUE;
END;
ELSE
BatchMode := TRUE;
END;
BigSets.AppendSet( KbdInput.YorN, "{'q', 'Q'}" );
Drectory.GetDrivePathAndName( SecondaryFileSpec, SecondaryDrive,
SecondaryDirName, SecondaryFileSpecPart );
Drectory.GetDrivePathAndName( PrimaryFileSpec, PrimaryDrive,
PrimaryDirName, PrimaryFileSpecPart );
IF PosUtils.Equal( PrimaryFileSpecPart, '.' ) THEN
StringIO.PrintMessage( Drectory.GetCurrentDir( Drectory.GetDefaultDrive(),
PrimaryDirName ) );
END;
IF PosUtils.Equal( SecondaryFileSpecPart, '.' ) THEN
StringIO.PrintMessage( Drectory.GetCurrentDir( Drectory.GetDefaultDrive(),
SecondaryDirName ) );
END;
IF PrimaryFileSpecPart[0] = 0C THEN
PrimaryFileSpecPart := '*.*';
END;
IF SecondaryFileSpecPart[0] = 0C THEN
SecondaryFileSpecPart := '*.*';
END;
StrEdit.CutTrailingChars( '\', PrimaryDirName );
StrEdit.CutTrailingChars( '\', SecondaryDirName );
StrEdit.Append( PrimaryDirName, '\' );
StrEdit.Append( SecondaryDirName, '\' );
exiting := FALSE;
StringIO.PrintMessage(Drectory.FindFiles( PrimaryFileSpec, Processor1 ));
END DelOlder.