home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
032.lha
/
doc
/
misc
/
cmp.d
next >
Wrap
Text File
|
1987-05-16
|
15KB
|
780 lines
#include:util.g
#include:crt.g
int
SCANRANGE = 20,
BINARYBLOCKCOUNT = 8,
BUFFERSIZE = 8 * 1024,
LINECOUNT = 25,
LINEBUFFERSIZE = 4 * 1024;
channel input binary ChB1, ChB2;
channel input text ChT1, ChT2;
file(BUFFERSIZE) File1, File2;
channel output text CRT;
uint
LineNext1,
LineNext2,
LineCount,
FullLineLength,
HalfLineLength;
uint
LineNumber1,
LineNumber2;
ushort LinesPerScreen;
bool
TextMode,
Visual,
Wrappable,
Eof1,
Eof2;
[LINECOUNT] uint
Line1,
Line2;
[LINEBUFFERSIZE] char
LineBuffer1,
LineBuffer2;
proc closeBoth()void:
if TextMode then
close(ChT1);
close(ChT2);
else
close(ChB1);
close(ChB2);
fi;
corp;
proc doAbort()void:
closeBoth();
CRT_Abort();
corp;
proc checkWait()void:
char ch;
if LineCount = LinesPerScreen - 1 then
if TextMode then
write(CRT; '\t', ChT1, " line ", LineNumber1, " \t\t\t");
else
write(CRT; '\t', ChB1, " \t\t\t\t");
fi;
if TextMode then
write(CRT; ChT2, " line ", LineNumber2, '\r');
else
write(CRT; ChB2, '\r');
fi;
ch := CRT_ReadChar();
CRT_ClearLine(LinesPerScreen - 1);
if ch = '\(0x03)' then
doAbort();
elif ch = '\r' or ch = '\n' then
LineCount := LineCount - 1;
CRT_Scroll();
CRT_ClearLine(LinesPerScreen - 2);
else
LineCount := 0;
CRT_ClearScreen();
fi;
fi;
LineCount := LineCount + 1;
corp;
proc nl()void:
write(CRT; "\r\n");
checkWait();
corp;
proc removeLine1()void:
uint pos, i, p;
LineNumber1 := LineNumber1 + 1;
pos := Line1[1];
p := 0;
i := Line1[LineNext1];
while pos ~= i do
LineBuffer1[p] := LineBuffer1[pos];
p := p + 1;
pos := pos + 1;
od;
LineNext1 := LineNext1 - 1;
pos := Line1[1];
for i from 0 upto LineNext1 do
Line1[i] := Line1[i + 1] - pos;
od;
corp;
proc removeLine2()void:
uint pos, i, p;
LineNumber2 := LineNumber2 + 1;
pos := Line2[1];
p := 0;
i := Line2[LineNext2];
while pos ~= i do
LineBuffer2[p] := LineBuffer2[pos];
p := p + 1;
pos := pos + 1;
od;
LineNext2 := LineNext2 - 1;
pos := Line2[1];
for i from 0 upto LineNext2 do
Line2[i] := Line2[i + 1] - pos;
od;
corp;
proc flush1()void:
uint pos, len, i;
pos := 0;
len := Line1[1] - 1;
while pos ~= len do
i := 0;
CRT_EnterHighLight();
while i ~= HalfLineLength and pos ~= len do
if LineBuffer1[pos] = '\t' then
LineBuffer1[pos] := '\(0x80)' + ((i + 8) / 8 * 8 - i);
fi;
if LineBuffer1[pos] >= '\(0x80)' then
while LineBuffer1[pos] ~= '\(0x80)' and
i ~= HalfLineLength do
write(CRT; ' ');
i := i + 1;
LineBuffer1[pos] := LineBuffer1[pos] - 1;
od;
if LineBuffer1[pos] = '\(0x80)' then
pos := pos + 1;
fi;
else
write(CRT; LineBuffer1[pos]);
i := i + 1;
pos := pos + 1;
fi;
od;
while i ~= HalfLineLength do
write(CRT; ' ');
i := i + 1;
od;
CRT_ExitHighLight();
write(CRT; '|');
nl();
od;
removeLine1();
corp;
proc flush2()void:
uint pos, len, i;
pos := 0;
len := Line2[1] - 1;
while pos ~= len do
for i from 0 upto HalfLineLength - 1 do
write(CRT; ' ');
od;
write(CRT; '|');
i := 0;
CRT_EnterHighLight();
while i ~= HalfLineLength and pos ~= len do
if LineBuffer2[pos] = '\t' then
LineBuffer2[pos] := '\(0x80)' + ((i + 8) / 8 * 8 - i);
fi;
if LineBuffer2[pos] >= '\(0x80)' then
while LineBuffer2[pos] ~= '\(0x80)' and
i ~= HalfLineLength do
write(CRT; ' ');
i := i + 1;
LineBuffer2[pos] := LineBuffer2[pos] - 1;
od;
if LineBuffer2[pos] = '\(0x80)' then
pos := pos + 1;
fi;
else
write(CRT; LineBuffer2[pos]);
i := i + 1;
pos := pos + 1;
fi;
od;
CRT_ExitHighLight();
if Wrappable and i = HalfLineLength then
checkWait();
else
nl();
fi;
od;
removeLine2();
corp;
proc flushBoth()void:
uint pos1, pos2, len1, len2, i;
pos1 := 0;
pos2 := 0;
len1 := Line1[1] - 1;
len2 := Line2[1] - 1;
if len1 = 0 and len2 = 0 then
/* need this, since the main while wouldn't do anything */
for i from 0 upto HalfLineLength - 1 do
write(CRT; ' ');
od;
write(CRT; '|');
nl();
fi;
while pos1 ~= len1 or pos2 ~= len2 do
i := 0;
while i ~= HalfLineLength and pos1 ~= len1 do
if LineBuffer1[pos1] = '\t' then
LineBuffer1[pos1] := '\(0x80)' + ((i + 8) / 8 * 8 - i);
fi;
if LineBuffer1[pos1] >= '\(0x80)' then
while LineBuffer1[pos1] ~= '\(0x80)' and
i ~= HalfLineLength do
write(CRT; ' ');
i := i + 1;
LineBuffer1[pos1] := LineBuffer1[pos1] - 1;
od;
if LineBuffer1[pos1] = '\(0x80)' then
pos1 := pos1 + 1;
fi;
else
write(CRT; LineBuffer1[pos1]);
i := i + 1;
pos1 := pos1 + 1;
fi;
od;
while i ~= HalfLineLength do
write(CRT; ' ');
i := i + 1;
od;
write(CRT; '|');
i := 0;
while i ~= HalfLineLength and pos2 ~= len2 do
if LineBuffer2[pos2] = '\t' then
LineBuffer2[pos2] := '\(0x80)' + ((i + 8) / 8 * 8 - i);
fi;
if LineBuffer2[pos2] >= '\(0x80)' then
while LineBuffer2[pos2] ~= '\(0x80)' and
i ~= HalfLineLength do
write(CRT; ' ');
i := i + 1;
LineBuffer2[pos2] := LineBuffer2[pos2] - 1;
od;
if LineBuffer2[pos2] = '\(0x80)' then
pos2 := pos2 + 1;
fi;
else
write(CRT; LineBuffer2[pos2]);
i := i + 1;
pos2 := pos2 + 1;
fi;
od;
if Wrappable and i = HalfLineLength then
checkWait();
else
nl();
fi;
od;
removeLine1();
removeLine2();
corp;
proc getLine1()void:
uint pos;
char ch;
bool first;
pos := Line1[LineNext1];
first := true;
while
if first then
if not read(ChT1; ch) then
first := false;
fi;
true
else
false
fi
do
if pos = LINEBUFFERSIZE then
if LineNext1 = 0 then
write(ChT1, ": input line too long.\r\n");
doAbort();
fi;
Line1[LineNext1 + 1] := pos;
if CharsEqual(&LineBuffer1[Line1[0]],
&LineBuffer2[Line2[0]]) then
flushBoth();
else
flush1();
flush2();
fi;
fi;
LineBuffer1[pos] := ch;
pos := pos + 1;
od;
if pos ~= Line1[LineNext1] then
LineBuffer1[pos - 1] := '\e';
Line1[LineNext1 + 1] := pos;
LineNext1 := LineNext1 + 1;
fi;
if ioerror(ChT1) = CH_EOF or not readln(ChT1;) then
Eof1 := true;
fi;
corp;
proc getLine2()void:
uint pos;
char ch;
bool first;
pos := Line2[LineNext2];
first := true;
while
if first then
if not read(ChT2; ch) then
first := false;
fi;
true
else
false
fi
do
if pos = LINEBUFFERSIZE then
if LineNext2 = 0 then
write(ChT2, ": input line too long.\r\n");
doAbort();
fi;
Line2[LineNext2 + 1] := pos;
if CharsEqual(&LineBuffer1[Line1[0]],
&LineBuffer2[Line2[0]]) then
flushBoth();
else
flush1();
flush2();
fi;
fi;
LineBuffer2[pos] := ch;
pos := pos + 1;
od;
if pos ~= Line2[LineNext2] then
LineBuffer2[pos - 1] := '\e';
Line2[LineNext2 + 1] := pos;
LineNext2 := LineNext2 + 1;
fi;
if ioerror(ChT2) = CH_EOF or not readln(ChT2;) then
Eof2 := true;
fi;
corp;
proc visualTextCompare()void:
uint i, j;
CRT_ClearScreen();
Eof1 := false;
Eof2 := false;
LineNext1 := 0;
LineNext2 := 0;
Line1[0] := 0;
Line2[0] := 0;
LineNumber1 := 1;
LineNumber2 := 1;
while
if LineNext1 = 0 then
getLine1();
fi;
if LineNext2 = 0 then
getLine2();
fi;
not Eof1 or not Eof2
do
if CharsEqual(&LineBuffer1[Line1[0]],
&LineBuffer2[Line2[0]]) then
flushBoth();
else
i := 1;
while
if Eof1 and Eof2 then
false
else
if i = LineNext1 and not Eof1 then
getLine1();
fi;
if i = LineNext2 and not Eof2 then
getLine2();
fi;
i ~= SCANRANGE and (not Eof1 or not Eof2) and
if Eof2 then
true
else
j := 0;
while j <= i and
not CharsEqual(&LineBuffer1[Line1[j]],
&LineBuffer2[Line2[i]])
do
j := j + 1;
od;
j > i
fi and
if Eof1 then
true
else
j := 0;
while j <= i and
not CharsEqual(&LineBuffer1[Line1[i]],
&LineBuffer2[Line2[j]])
do
j := j + 1;
od;
j > i
fi
fi
do
i := i + 1;
od;
if Eof1 and Eof2 then
elif not Eof2 and CharsEqual(&LineBuffer1[Line1[j]],
&LineBuffer2[Line2[i]]) then
while i ~= 0 do
flush2();
i := i - 1;
od;
elif not Eof1 and CharsEqual(&LineBuffer1[Line1[i]],
&LineBuffer2[Line2[j]]) then
while i ~= 0 do
flush1();
i := i - 1;
od;
else
if not Eof1 then
flush1();
fi;
if not Eof2 then
flush2();
fi;
fi;
fi;
od;
while LineNext1 ~= 0 do
flush1();
od;
while not Eof1 do
getLine1();
while LineNext1 ~= 0 do
flush1();
od;
od;
while LineNext2 ~= 0 do
flush2();
od;
while not Eof2 do
getLine2();
while LineNext2 ~= 0 do
flush2();
od;
od;
while LineCount ~= 1 do
nl();
od;
corp;
proc visualBinaryCompare()void:
[BINARYBLOCKCOUNT] byte block1, block2;
uint pos;
ushort i;
byte b1, b2;
bool different;
CRT_ClearScreen();
pos := 0;
while
for i from 0 upto BINARYBLOCKCOUNT - 1 do
block1[i] := 1;
block2[i] := 2;
od;
read(ChB1; block1) and read(ChB2; block2)
do
write(CRT; pos : x : -4);
for i from 0 upto BINARYBLOCKCOUNT - 1 do
b1 := block1[i];
b2 := block2[i];
write(CRT; if i = 0 then ':' else ' ' fi);
if b1 ~= b2 then
CRT_EnterHighLight();
fi;
write(CRT; b1 : x : -2);
if b1 ~= b2 then
CRT_ExitHighLight();
fi;
od;
write(CRT; '*');
different := false;
for i from 0 upto BINARYBLOCKCOUNT - 1 do
b1 := block1[i];
b2 := block2[i];
if b1 ~= b2 then
if not different then
different := true;
CRT_EnterHighLight();
fi;
else
if different then
different := false;
CRT_ExitHighLight();
fi;
fi;
write(CRT;
if b1 >= 0x20 and b1 <= 0x7f then
b1 + '\e'
else
'.'
fi);
od;
if different then
CRT_ExitHighLight();
fi;
write(CRT; "*|", pos : x : -4);
for i from 0 upto BINARYBLOCKCOUNT - 1 do
b1 := block1[i];
b2 := block2[i];
write(CRT; if i = 0 then ':' else ' ' fi);
if b1 ~= b2 then
CRT_EnterHighLight();
fi;
write(CRT; b2 : x : -2);
if b1 ~= b2 then
CRT_ExitHighLight();
fi;
od;
write(CRT; '*');
different := false;
for i from 0 upto BINARYBLOCKCOUNT - 1 do
b1 := block1[i];
b2 := block2[i];
if b1 ~= b2 then
if not different then
different := true;
CRT_EnterHighLight();
fi;
else
if different then
different := false;
CRT_ExitHighLight();
fi;
fi;
write(CRT;
if b2 >= 0x20 and b2 <= 0x7f then
b2 + '\e'
else
'.'
fi);
od;
if different then
CRT_ExitHighLight();
fi;
write(CRT; '*');
nl();
pos := pos + BINARYBLOCKCOUNT;
od;
while LineCount ~= 1 do
nl();
od;
corp;
proc showChar(char c)void:
write('\'', if c < ' ' or c > '~' then '.' else c fi, "' (hex ",
c - '\e' : x : -2, ')');
corp;
proc textCompare()void:
char c1, c2;
uint line, col;
bool eof1, eof2;
line := 1;
col := 1;
while
while if read(ChT1; c1) then 1 else 0 fi &
if read(ChT2; c2) then 1 else 0 fi ~= 0 and c1 = c2 do
if c1 = '\t' then
col := (col + 7) & (-8) + 1;
else
col := col + 1;
fi;
od;
eof1 := ioerror(ChT1) = CH_EOF;
eof2 := ioerror(ChT2) = CH_EOF;
not eof1 and not eof2 and c1 = c2
do
readln(ChT1;);
readln(ChT2;);
line := line + 1;
col := 1;
od;
if eof1 and eof2 then
writeln("Files ", ChT1, " and ", ChT2, " are identical.")
elif eof1 then
writeln("File ", ChT2, " contains more text than file ", ChT1,'.');
elif eof2 then
writeln("File ", ChT1, " contains more text than file ", ChT2,'.');
else
write("Line ", line, ", col ", col, ", ", ChT1, " has ");
showChar(c1);
write(", but ", ChT2, " has ");
showChar(c2);
writeln('.');
fi;
corp;
proc binaryCompare()void:
uint pos;
byte b1, b2;
bool eof1, eof2;
pos := 0;
while if read(ChB1; b1) then 1 else 0 fi &
if read(ChB2; b2) then 1 else 0 fi ~= 0 and b1 = b2 do
pos := pos + 1;
od;
eof1 := ioerror(ChB1) = CH_EOF;
eof2 := ioerror(ChB2) = CH_EOF;
if eof1 and eof2 then
writeln("Files ", ChB1, " and ", ChB2, " are identical.")
elif eof1 then
writeln("File ", ChB2, " contains more data than file ", ChB1,'.');
elif eof2 then
writeln("File ", ChB1, " contains more data than file ", ChB2,'.');
else
writeln("At ", pos, " (hex ", pos : x : -4, "), ", ChB1,
" has hex ", b1 : x : -2, ", but ", ChB2,
" has hex ", b2 : x : -2, '.');
fi;
corp;
proc badUsage()void:
writeln("Use is: cmp [-?tbv] file1 file2");
exit(1);
corp;
proc instructions()void:
CRT_Initialize("Cmp V1.0", 23, 77);
CRT_Chars(
"\n\n\n"
"Cmp can compare text and binary files, either visually or using a "
"quick, non-visual mode. Flags 'b' and 't' select either binary or "
"text mode (default binary). Flag 'v' selects a visual compare, "
"quick being the default. Cmp will wait at the end of each "
"screenful. When waiting, a carriage "
"return will advance 1 line, any other key will advance 1 screen. "
"Examples:\n\n"
" cmp fyle1.dat fyle2.dat\n"
" - compare files as binary, using non-visual compare\n\n"
" cmp -vt fyle1.txt fyle2.txt\n"
" - compare text files in visual\n\n"
" cmp -t fyle1.txt fyle2.txt\n"
" - non-visual compare of text files"
);
CRT_Terminate();
exit(1);
corp;
proc main()void:
*char par;
par := GetPar();
TextMode := false;
Visual := false;
if par ~= nil and par* = '-' then
while
par := par + 1;
par* ~= '\e'
do
case par*
incase '?':
instructions();
incase 'v':
incase 'V':
Visual := true;
incase 't':
incase 'T':
TextMode := true;
incase 'b':
incase 'B':
TextMode := false;
default:
badUsage();
esac;
od;
par := GetPar();
fi;
if par = nil then
badUsage();
fi;
if not
if TextMode then
open(ChT1, File1, par)
else
open(ChB1, File1, par)
fi
then
writeln("Can't open file \"", par, "\".");
exit(1);
fi;
par := GetPar();
if par = nil then
badUsage();
fi;
if not
if TextMode then
open(ChT2, File2, par)
else
open(ChB2, File2, par)
fi
then
writeln("Can't open file \"", par, "\".");
if TextMode then
close(ChT1);
else
close(ChB1);
fi;
exit(1);
fi;
if Visual then
CRT_Initialize("Cmp V1.0", 0, 1);
open(CRT, CRT_PutChar);
LinesPerScreen := CRT_NLines();
LineCount := 1;
if TextMode then
FullLineLength := CRT_NCols();
HalfLineLength := (FullLineLength - 1) / 2;
Wrappable := HalfLineLength * 2 + 1 = FullLineLength;
visualTextCompare();
else
if CRT_NCols() < 78 then
writeln("Cmp: less than 78 columns - aborting.");
else
visualBinaryCompare();
fi;
fi;
CRT_Terminate();
else
if TextMode then
textCompare();
else
binaryCompare();
fi;
fi;
closeBoth();
corp;